Merge branch 'master' into refactoring-static-analyser

pull/1104/head
David Zagi 4 years ago committed by GitHub
commit a053eefe5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .circleci/config.yml
  2. 4
      apps/remix-ide-e2e/src/commands/debugTransaction.ts
  3. 22
      apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts
  4. 5
      apps/remix-ide-e2e/src/commands/testFunction.ts
  5. 2
      apps/remix-ide/src/app.js
  6. 9
      apps/remix-ide/src/app/files/fileManager.js
  7. 2
      apps/remix-ide/src/app/panels/file-panel.js
  8. 5
      apps/remix-ide/src/app/panels/tab-proxy.js
  9. 4
      apps/remix-ide/src/app/tabs/runTab/settings.js
  10. 71
      apps/remix-ide/src/app/ui/landing-page/landing-page.js
  11. 9
      apps/remix-ide/src/migrateFileSystem.js
  12. 2
      libs/remix-ui/file-explorer/src/lib/file-explorer.tsx
  13. 7
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
  14. 43
      release-management.md
  15. 94
      release-process.md

@ -31,9 +31,6 @@ jobs:
- run: - run:
name: Remix IDE e2e Linting name: Remix IDE e2e Linting
command: npm run lint remix-ide-e2e command: npm run lint remix-ide-e2e
- run: npm run lint:libs
- run: npm run lint
- run: npm run lint remix-ide-e2e
remix-libs: remix-libs:
docker: docker:

@ -14,12 +14,12 @@ class debugTransaction extends EventEmitter {
} }
function checkStyle (browser: NightwatchBrowser, index: number, callback: VoidFunction) { function checkStyle (browser: NightwatchBrowser, index: number, callback: VoidFunction) {
browser.pause(2000).execute(function (index: number) { browser.pause(5000).execute(function (index: number) {
const debugBtn = document.querySelectorAll('*[data-shared="txLoggerDebugButton"]')[index] as HTMLInputElement const debugBtn = document.querySelectorAll('*[data-shared="txLoggerDebugButton"]')[index] as HTMLInputElement
debugBtn && debugBtn.click() debugBtn && debugBtn.click()
}, [index], function () { }, [index], function () {
browser.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]').perform(() => callback()) browser.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]', 60000).perform(() => callback())
}) })
} }

@ -10,25 +10,11 @@ class GoToVmTraceStep extends EventEmitter {
} }
function goToVMtraceStep (browser: NightwatchBrowser, step: number, incr: number, done: VoidFunction) { function goToVMtraceStep (browser: NightwatchBrowser, step: number, incr: number, done: VoidFunction) {
if (!incr) incr = 0 browser.execute(function (step) { (document.getElementById('slider') as HTMLInputElement).value = (step - 1).toString() }, [step])
browser.execute(function () { .setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW))
return document.querySelector('#stepdetail').innerHTML .perform(() => {
}, [], function (result) {
if (typeof result.value === 'string' && (result.value.indexOf('vm trace step:') !== -1 && result.value.indexOf(step.toString()) !== -1)) {
done() done()
} else if (incr > 1000) { })
browser.assert.fail('goToVMtraceStep fails', 'info about error', '')
done()
} else {
incr++
browser.click('#intoforward')
.perform(() => {
setTimeout(() => {
goToVMtraceStep(browser, step, incr, done)
}, 200)
})
}
})
} }
module.exports = GoToVmTraceStep module.exports = GoToVmTraceStep

@ -22,9 +22,10 @@ class TestFunction extends EventEmitter {
}) })
}) })
.perform((done) => { .perform((done) => {
browser.waitForElementVisible(`[data-id="block_tx${txHash}"]`) browser.waitForElementVisible(`[data-id="block_tx${txHash}"]`, 60000)
.click(`[data-id="block_tx${txHash}"]`) .click(`[data-id="block_tx${txHash}"]`)
.waitForElementVisible(`*[data-id="txLoggerTable${txHash}"]`) .waitForElementVisible(`*[data-id="txLoggerTable${txHash}"]`, 60000)
.pause(10000)
// fetch and format transaction logs as key => pair object // fetch and format transaction logs as key => pair object
.elements('css selector', `*[data-shared="key_${txHash}"]`, (res) => { .elements('css selector', `*[data-shared="key_${txHash}"]`, (res) => {
Array.isArray(res.value) && res.value.forEach(function (jsonWebElement) { Array.isArray(res.value) && res.value.forEach(function (jsonWebElement) {

@ -450,7 +450,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
} }
await appManager.activatePlugin(['contentImport', 'theme', 'editor', 'fileManager', 'compilerMetadata', 'compilerArtefacts', 'network', 'web3Provider', 'offsetToLineColumnConverter']) await appManager.activatePlugin(['contentImport', 'theme', 'editor', 'fileManager', 'compilerMetadata', 'compilerArtefacts', 'network', 'web3Provider', 'offsetToLineColumnConverter'])
await appManager.activatePlugin(['mainPanel', 'menuicons']) await appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs'])
await appManager.activatePlugin(['sidePanel']) // activating host plugin separately await appManager.activatePlugin(['sidePanel']) // activating host plugin separately
await appManager.activatePlugin(['home']) await appManager.activatePlugin(['home'])
await appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'fileExplorers', 'settings', 'contextualListener', 'terminal', 'fetchAndCompile']) await appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'fileExplorers', 'settings', 'contextualListener', 'terminal', 'fetchAndCompile'])

@ -398,6 +398,15 @@ class FileManager extends Plugin {
return this._deps.config.get('currentFile') return this._deps.config.get('currentFile')
} }
closeAllFiles () {
// TODO: Only keep `this.emit` (issue#2210)
this.emit('filesAllClosed')
this.events.emit('filesAllClosed')
for (const file in this.openedFiles) {
this.closeFile(file)
}
}
closeFile (name) { closeFile (name) {
delete this.openedFiles[name] delete this.openedFiles[name]
if (!Object.keys(this.openedFiles).length) { if (!Object.keys(this.openedFiles).length) {

@ -225,7 +225,7 @@ module.exports = class Filepanel extends ViewPlugin {
/** these are called by the react component, action is already finished whent it's called */ /** these are called by the react component, action is already finished whent it's called */
async setWorkspace (workspace) { async setWorkspace (workspace) {
this._deps.fileManager.removeTabsOf(this._deps.fileProviders.workspace) this._deps.fileManager.closeAllFiles()
if (workspace.isLocalhost) { if (workspace.isLocalhost) {
this.call('manager', 'activatePlugin', 'remixd') this.call('manager', 'activatePlugin', 'remixd')
} else if (await this.call('manager', 'isActive', 'remixd')) { } else if (await this.call('manager', 'isActive', 'remixd')) {

@ -37,6 +37,11 @@ export class TabProxy extends Plugin {
this.updateImgStyles() this.updateImgStyles()
}) })
fileManager.events.on('filesAllClosed', () => {
this.call('manager', 'activatePlugin', 'home')
this._view.filetabs.active = 'home'
})
fileManager.events.on('fileRemoved', (name) => { fileManager.events.on('fileRemoved', (name) => {
const workspace = this.fileManager.currentWorkspace() const workspace = this.fileManager.currentWorkspace()

@ -403,13 +403,13 @@ class SettingsUI {
if (!accounts) accounts = [] if (!accounts) accounts = []
if (this.accountListCallId > callid) return if (this.accountListCallId > callid) return
this.accountListCallId++ this.accountListCallId++
for (var loadedaddress in this.loadedAccounts) { for (const loadedaddress in this.loadedAccounts) {
if (accounts.indexOf(loadedaddress) === -1) { if (accounts.indexOf(loadedaddress) === -1) {
txOrigin.removeChild(txOrigin.querySelector('option[value="' + loadedaddress + '"]')) txOrigin.removeChild(txOrigin.querySelector('option[value="' + loadedaddress + '"]'))
delete this.loadedAccounts[loadedaddress] delete this.loadedAccounts[loadedaddress]
} }
} }
for (var i in accounts) { for (const i in accounts) {
const address = accounts[i] const address = accounts[i]
if (!this.loadedAccounts[address]) { if (!this.loadedAccounts[address]) {
txOrigin.appendChild(yo`<option value="${address}" >${address}</option>`) txOrigin.appendChild(yo`<option value="${address}" >${address}</option>`)

@ -22,6 +22,7 @@ const css = csjs`
user-select: none; user-select: none;
} }
.text:hover { .text:hover {
cursor: pointer;
text-decoration: underline; text-decoration: underline;
} }
.homeContainer { .homeContainer {
@ -300,6 +301,11 @@ export class LandingPage extends ViewPlugin {
await this.appManager.activatePlugin('pluginManager') await this.appManager.activatePlugin('pluginManager')
this.verticalIcons.select('pluginManager') this.verticalIcons.select('pluginManager')
} }
const startRestoreBackupZip = async () => {
await this.appManager.activatePlugin(['restorebackupzip'])
this.verticalIcons.select('restorebackupzip')
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'restorebackupzip'])
}
const createNewFile = () => { const createNewFile = () => {
this.call('fileExplorers', 'createNewFile') this.call('fileExplorers', 'createNewFile')
@ -456,7 +462,7 @@ export class LandingPage extends ViewPlugin {
) )
} }
const img = yo`<img class=${css.logoImg} src="assets/img/guitarRemiCroped.webp" onclick="${() => playRemi()}"></img>` const img = yo`<img class="m-4 ${css.logoImg}" src="assets/img/guitarRemiCroped.webp" onclick="${() => playRemi()}"></img>`
const playRemi = async () => { await document.getElementById('remiAudio').play() } const playRemi = async () => { await document.getElementById('remiAudio').play() }
// to retrieve medium posts // to retrieve medium posts
document.body.appendChild(yo`<script src="https://www.twilik.com/assets/retainable/rss-embed/retainable-rss-embed.js"></script>`) document.body.appendChild(yo`<script src="https://www.twilik.com/assets/retainable/rss-embed/retainable-rss-embed.js"></script>`)
@ -466,24 +472,46 @@ export class LandingPage extends ViewPlugin {
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<div class="d-flex flex-column"> <div class="d-flex flex-column">
<div class="border-bottom d-flex justify-content-between clearfix py-3 mb-4"> <div class="border-bottom d-flex justify-content-between clearfix py-3 mb-4">
<div class="mx-4 w-100"> <div class="mx-4 w-100 d-flex">
${img} ${img}
<audio id="remiAudio" muted=false src="assets/audio/remiGuitar-single-power-chord-A-minor.wav"></audio> <audio id="remiAudio" muted=false src="assets/audio/remiGuitar-single-power-chord-A-minor.wav"></audio>
<div class="w-80 pl-5 ml-5">
<h5 class="mb-1">Quicklinks</h5>
<a class="${css.text} mr-1" target="__blank" href="https://medium.com/remix-ide/migrating-files-to-workspaces-8e34737c751c?source=friends_link&sk=b75cfd9093aa23c78be13cce49e4a5e8">Guide </a>for migrating the old File System
<p class="font-weight-bold mb-0 py-1">Migration tools:</p>
<li class="pl-1">
<spam class="pl-0">
<u class="${css.text} pr-1" onclick=${() => migrateWorkspace()}>Basic migration</u>
</spam>
</li>
<li class="pl-1">
<u class="${css.text} pr-1" onclick=${() => downloadFiles()}>Download all Files</u>
as a backup zip
</li>
<li class="pl-1">
<u class="${css.text} pr-1" onclick=${() => startRestoreBackupZip()}>Restore files</u>from backup zip
</li>
<p class="font-weight-bold mb-0 mt-2">Help:</p>
<dir class="d-flex flex-column mt-1 pl-0">
<a class="${css.text} mx-1" target="__blank" href="https://gitter.im/ethereum/remix">Gitter channel</a>
<a class="${css.text} mx-1" target="__blank" href="https://github.com/ethereum/remix-project/issues">Report on Github</a>
</dir>
</div>
</div> </div>
</div> </div>
<div class="row ${css.hpSections} mx-4" data-id="landingPageHpSections"> <div class="row ${css.hpSections} mx-4" data-id="landingPageHpSections">
<div class="ml-3"> <div class="ml-3">
<div class="plugins mb-5"> <div class="plugins mb-5">
<h4>Featured Plugins</h4> <h4>Featured Plugins</h4>
<div class="d-flex flex-row pt-2"> <div class="d-flex flex-row pt-2">
${this.solEnv} ${this.solEnv}
${this.learnEthEnv} ${this.learnEthEnv}
${this.solhintEnv} ${this.solhintEnv}
${this.sourcifyEnv} ${this.sourcifyEnv}
${this.debuggerEnv} ${this.debuggerEnv}
${this.moreEnv} ${this.moreEnv}
</div>
</div> </div>
</div>
<div class="d-flex"> <div class="d-flex">
<div class="file"> <div class="file">
<h4>File</h4> <h4>File</h4>
@ -495,22 +523,17 @@ export class LandingPage extends ViewPlugin {
<i class="mr-1 far fa-file-alt"></i> <i class="mr-1 far fa-file-alt"></i>
<label class="ml-1 ${css.labelIt} ${css.bigLabelSize} ${css.text}"> <label class="ml-1 ${css.labelIt} ${css.bigLabelSize} ${css.text}">
Open Files Open Files
<input title="open file" type="file" onchange="${ <input title="open file" type="file" onchange="${(event) => {
(event) => { event.stopPropagation()
event.stopPropagation() uploadFile(event.target)
uploadFile(event.target) }
} }" multiple />
}" multiple />
</label> </label>
</p> </p>
<p class="mb-1"> <p class="mb-1">
<i class="far fa-hdd"></i> <i class="far fa-hdd"></i>
<span class="ml-1 ${css.text}" onclick=${() => connectToLocalhost()}>Connect to Localhost</span> <span class="ml-1 ${css.text}" onclick=${() => connectToLocalhost()}>Connect to Localhost</span>
</p> </p>
<p class="mb-1">
<i class="mr-1 fas fa-download""></i>
<span class="ml-1 mb-1 ${css.text}" onclick=${() => downloadFiles()}>Download all Files</span>
</p>
<p class="mt-3 mb-0"><label>IMPORT FROM:</label></p> <p class="mt-3 mb-0"><label>IMPORT FROM:</label></p>
<div class="btn-group"> <div class="btn-group">
<button class="btn mr-1 btn-secondary" data-id="landingPageImportFromGistButton" onclick="${() => importFromGist()}">Gist</button> <button class="btn mr-1 btn-secondary" data-id="landingPageImportFromGistButton" onclick="${() => importFromGist()}">Gist</button>
@ -529,7 +552,7 @@ export class LandingPage extends ViewPlugin {
<p class="mb-1"> <p class="mb-1">
<i class="mr-1 fab fa-gitter"></i> <i class="mr-1 fab fa-gitter"></i>
<a class="${css.text}" target="__blank" href="https://gitter.im/ethereum/remix">Gitter channel</a> <a class="${css.text}" target="__blank" href="https://gitter.im/ethereum/remix">Gitter channel</a>
</p> </p>
<p class="mb-1"> <p class="mb-1">
${this.websiteIcon} ${this.websiteIcon}
<a class="${css.text}" target="__blank" href="https://remix-project.org">Featuring website</a> <a class="${css.text}" target="__blank" href="https://remix-project.org">Featuring website</a>
@ -538,10 +561,6 @@ export class LandingPage extends ViewPlugin {
<i class="fab fa-ethereum ${css.image}"></i> <i class="fab fa-ethereum ${css.image}"></i>
<span class="${css.text}" onclick=${() => switchToPreviousVersion()}>Old experience</span> <span class="${css.text}" onclick=${() => switchToPreviousVersion()}>Old experience</span>
</p> </p>
<p>
<i class="fas fa-exclamation-triangle text-warning ${css.image}"></i>
<span class="${css.text}" onclick=${() => migrateWorkspace()}>Migrate old filesystem to workspace</span>
</p>
</div> </div>
</div> </div>
</div> </div>

@ -1,6 +1,7 @@
import { Storage } from '@remix-project/remix-lib' import { Storage } from '@remix-project/remix-lib'
import { joinPath } from './lib/helper' import { joinPath } from './lib/helper'
import yo from 'yo-yo'
const modalDialogCustom = require('./app/ui/modal-dialog-custom')
/* /*
Migrating the files to the BrowserFS storage instead or raw localstorage Migrating the files to the BrowserFS storage instead or raw localstorage
*/ */
@ -53,7 +54,11 @@ const populateWorkspace = async (workspace, json, browserProvider) => {
browserProvider.createDir(joinPath(workspace, item)) browserProvider.createDir(joinPath(workspace, item))
await populateWorkspace(workspace, json[item].children, browserProvider) await populateWorkspace(workspace, json[item].children, browserProvider)
} else { } else {
await browserProvider.set(joinPath(workspace, item), json[item].content) await browserProvider.set(joinPath(workspace, item), json[item].content, (err) => {
if (err && err.message) {
modalDialogCustom.alert(yo`<div>There was an error migrating your files:${err.message} <div>Please use the ‘Download all Files' action, clear the local storage and re-import your files manually or use the 'Restore files' action.</div></div>`)
}
})
} }
} }
} }

@ -1001,7 +1001,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
<div onClick={(e) => { <div onClick={(e) => {
e.stopPropagation() e.stopPropagation()
if (e && (e.target as any).getAttribute('data-id') === 'fileExplorerUploadFileuploadFile') return // we don't want to let propagate the input of type file if (e && (e.target as any).getAttribute('data-id') === 'fileExplorerUploadFileuploadFile') return // we don't want to let propagate the input of type file
if (e && (e.target as any).getAttribute('data-id') === 'fileExplorerFileUpload') return // we don't want to let propagate the input of type file
let expandPath = [] let expandPath = []
if (!state.expandPath.includes(props.name)) { if (!state.expandPath.includes(props.name)) {

@ -208,6 +208,7 @@ export const Workspace = (props: WorkspaceProps) => {
} }
const onFinishDeleteWorkspace = async () => { const onFinishDeleteWorkspace = async () => {
await props.fileManager.closeAllFiles()
const workspacesPath = props.workspace.workspacesPath const workspacesPath = props.workspace.workspacesPath
props.browser.remove(workspacesPath + '/' + state.currentWorkspace) props.browser.remove(workspacesPath + '/' + state.currentWorkspace)
const name = state.currentWorkspace const name = state.currentWorkspace
@ -223,7 +224,7 @@ export const Workspace = (props: WorkspaceProps) => {
} }
const setWorkspace = async (name) => { const setWorkspace = async (name) => {
props.setWorkspace({ name, isLocalhost: name === LOCALHOST }) await props.setWorkspace({ name, isLocalhost: name === LOCALHOST })
if (name === LOCALHOST) { if (name === LOCALHOST) {
props.workspace.clearWorkspace() props.workspace.clearWorkspace()
} else if (name === NO_WORKSPACE) { } else if (name === NO_WORKSPACE) {
@ -238,8 +239,8 @@ export const Workspace = (props: WorkspaceProps) => {
} }
const remixdExplorer = { const remixdExplorer = {
hide: () => { hide: async () => {
if (state.currentWorkspace === LOCALHOST) setWorkspace(NO_WORKSPACE) await setWorkspace(NO_WORKSPACE)
props.fileManager.setMode('browser') props.fileManager.setMode('browser')
setState(prevState => { setState(prevState => {
return { ...prevState, hideRemixdExplorer: true, loadingLocalhost: false } return { ...prevState, hideRemixdExplorer: true, loadingLocalhost: false }

@ -0,0 +1,43 @@
# Release Management
Release managers are responsible for the release management lifecycle, focusing on coordinating various aspects of production and projects into one integrated solution. They are responsible for ensuring that resources, timelines, and the overall quality of the process are all considered and accounted for.
# Steps of Release Management
## Release planning:
In this stage, release manager will elaborate a plan for the coming release.
Together with the team, the release manager will form a list of issues and PRs that should be addressed during the release.
More generally and a non negligeable part of the planning is to properly ensure that bugs, issues that weren't totally identified in the roadmap, and the roadmap issues are still being processed as they should.
## Configuring releases:
Release managers will oversee the various aspects of a project before it is due to be deployed, ensuring everyone is on track and meeting the agreed timeline.
## Quality checks:
The quality of the release needs to be reviewed before a project is officially launched.
The release manager is in charge of ensuring manual testing is properly planned and done.
Also that unit testing and e2e for new feaures have been included.
## Deployment:
After being quality checked, the project is ready to be deployed.
The release manager is still responsible for ensuring a project is rolled out smoothly and efficiently.
# Responsibilities
- Planning release windows and the overall release lifecycle.
- Managing risks that may affect release scope.
- Measure and monitor progress.
- Ensure releases are delivered within requirements.
- Manage relationships and coordinate projects.
# Miscellaneous
- Regular check for new filed issues, identify those that requires to be published (included in the release)
- In some really specific situation, it could be required to deploy intermediate releases (e.g critical bug fixes).
- Planning, refinement, retrospective meetings have to be organized by the release manager and any other required meetings.
- Release manager should feel free to implement new techniques and put their own finger print to their release, this could potentially benefit upcoming releases.
# Release Management Role
Aniket, Liana, David, Rob, Filip

@ -1,43 +1,79 @@
# Release Management # Release process
Release managers are responsible for the release management lifecycle, focusing on coordinating various aspects of production and projects into one integrated solution. They are responsible for ensuring that resources, timelines, and the overall quality of the process are all considered and accounted for. This document includes:
- how to publish remix libs to NPM
- how to update remix.ethereum.org
- how to update remix-alpha.ethereum.org
- how to update remix-beta.ethereum.org
- how to release remix IDE
# Steps of Release Management ## Remix libs release
- git fetch origin master
- git checkout origin/master
- git checkout -b bumpLibsVersion
- npm run publish:libs (this command uses lerna)
- commit
## Release planning: ## Remix IDE release Part 1. First push master to beta. Feature Freeze
In this stage, release manager will elaborate a plan for the coming release. - git co -b remix_beta origin/remix_beta
Together with the team, the release manager will form a list of issues and PRs that should be addressed during the release. - git reset --hard -master-commit-hash-
More generally and a non negligeable part of the planning is to properly ensure that bugs, issues that weren't totally identified in the roadmap, and the roadmap issues are still being processed as they should. - git push -f origin remix_beta
## Configuring releases: ## Testing phase
Release managers will oversee the various aspects of a project before it is due to be deployed, ensuring everyone is on track and meeting the agreed timeline. ## In case of fixing bugs push PR's also to beta to include in Release
## Quality Checks: ## Remix IDE release Part 2. Bump the version in beta and release
The quality of the release needs to be reviewed before a project is officially launched.
The release manager is in charge of ensuring manual testing is properly planned and done.
Also that unit testing and e2e for new feaures have been included.
## Deployment: - git fetch origin remix_beta
After being quality checked, the project is ready to be deployed. - git checkout origin/remix_beta
The release manager is still responsible for ensuring a project is rolled out smoothly and efficiently. - git checkout -b bumpVersion
- update package.json version
- remove package-lock.json version and generate a new one with `npm install`
- merge PR to origin/remix_beta
- git fetch origin remix_beta
- git checkout origin/remix_beta
- git tag v(version-number)
- git push --tags
- github-changes -o ethereum -r remix-project -a --only-pulls --use-commit-body --branch remix_beta --only-merges --between-tags previous_version...next_version
- publish a release in github using the changelog
## Remix IDE release Part 3. Bump dev branch (master)
# Responsibilities - git fetch origin master
- git checkout origin/master
- git checkout -b bumpDevVersion
- update package.json version: bump the version and add the tag `dev` if not already present.
- remove package-lock.json version and generate a new one with `npm install`
- create a PR and merge it to origin/master
- Planning release windows and the overall release lifecycle. ## Remix IDE release Part 4. remix.ethereum.org update
- Managing risks that may affect release scope.
- Measure and monitor progress.
- Ensure releases are delivered within requirements.
- Manage relationships and coordinate projects.
# Miscellaneous This is not strictly speaking a release. Updating the remix site is done through the Travis build:
- Regular check for new filed issues, identify those that requires to be published (included in the release) - git co -b remix_live origin/remix_live
- In some really specific situation, it could be required to deploy intermediate releases (e.g critical bug fixes). - git reset --hard -master-commit-hash- (or remix_beta-commit-hash-)
- Planning, refinement, retrospective meetings have to be organized by the release manager and any other required meetings. - git push -f origin remix_live
- Release manager should feel free to implement new techniques and put their own finger print to their release, this could potentially benefit upcoming releases.
CircleCI will build automaticaly and remix.ethereum.org will be updated
# Release Management Role ## Remix IDE release Part 5. Update Zip in release
- after remix_live is updated, drop the zip (from https://github.com/ethereum/remix-live/) to the release.
Aniket, Liana, David, Rob, Filip ## Remix-ide beta release
- git fetch origin master
- git checkout origin/master
- git checkout -b bumpVersion
- update package.json version to the new version "vx.x.x-beta.1"
- remove package-lock/json version and generate a new one with `npm install`
- merge PR
- git fetch origin master
- git checkout origin/master
- git tag v(version-number) (with "vx.x.x-beta.1")
- git push --tags
- github-changes -o ethereum -r remix-project -a --only-pulls --use-commit-body --only-merges --between-tags previous_version...next_version
- publish a beta release in github using the changelog
- drop zip file to the beta release (from https://github.com/ethereum/remix-live-alpha)
## remix-alpha.ethereum.org update
remix-alpha.ethereum.org is automaticaly updated every time commits are pushed to master
Loading…
Cancel
Save