diff --git a/.circleci/config.yml b/.circleci/config.yml index 53a50ff692..ab5e15436f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,10 +30,7 @@ jobs: command: npm run lint - run: name: Remix IDE e2e Linting - command: npm run lint remix-ide-e2e - - run: npm run lint:libs - - run: npm run lint - - run: npm run lint remix-ide-e2e + command: npm run lint remix-ide-e2e remix-libs: docker: diff --git a/apps/remix-ide-e2e/src/commands/debugTransaction.ts b/apps/remix-ide-e2e/src/commands/debugTransaction.ts index 37a63acb9f..67955ea38d 100644 --- a/apps/remix-ide-e2e/src/commands/debugTransaction.ts +++ b/apps/remix-ide-e2e/src/commands/debugTransaction.ts @@ -14,12 +14,12 @@ class debugTransaction extends EventEmitter { } 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 debugBtn && debugBtn.click() }, [index], function () { - browser.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]').perform(() => callback()) + browser.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]', 60000).perform(() => callback()) }) } diff --git a/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts b/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts index c9da6d8229..e84ab52367 100644 --- a/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts +++ b/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts @@ -10,25 +10,11 @@ class GoToVmTraceStep extends EventEmitter { } function goToVMtraceStep (browser: NightwatchBrowser, step: number, incr: number, done: VoidFunction) { - if (!incr) incr = 0 - browser.execute(function () { - return document.querySelector('#stepdetail').innerHTML - }, [], function (result) { - if (typeof result.value === 'string' && (result.value.indexOf('vm trace step:') !== -1 && result.value.indexOf(step.toString()) !== -1)) { + browser.execute(function (step) { (document.getElementById('slider') as HTMLInputElement).value = (step - 1).toString() }, [step]) + .setValue('*[data-id="slider"]', new Array(1).fill(browser.Keys.RIGHT_ARROW)) + .perform(() => { 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 diff --git a/apps/remix-ide-e2e/src/commands/testFunction.ts b/apps/remix-ide-e2e/src/commands/testFunction.ts index 802bb3103e..e16d613718 100644 --- a/apps/remix-ide-e2e/src/commands/testFunction.ts +++ b/apps/remix-ide-e2e/src/commands/testFunction.ts @@ -22,9 +22,10 @@ class TestFunction extends EventEmitter { }) }) .perform((done) => { - browser.waitForElementVisible(`[data-id="block_tx${txHash}"]`) + browser.waitForElementVisible(`[data-id="block_tx${txHash}"]`, 60000) .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 .elements('css selector', `*[data-shared="key_${txHash}"]`, (res) => { Array.isArray(res.value) && res.value.forEach(function (jsonWebElement) { diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js index ce1919451a..eedcf7d778 100644 --- a/apps/remix-ide/src/app.js +++ b/apps/remix-ide/src/app.js @@ -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(['mainPanel', 'menuicons']) + await appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs']) await appManager.activatePlugin(['sidePanel']) // activating host plugin separately await appManager.activatePlugin(['home']) await appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'fileExplorers', 'settings', 'contextualListener', 'terminal', 'fetchAndCompile']) diff --git a/apps/remix-ide/src/app/files/fileManager.js b/apps/remix-ide/src/app/files/fileManager.js index b1a3bdf914..932368c20b 100644 --- a/apps/remix-ide/src/app/files/fileManager.js +++ b/apps/remix-ide/src/app/files/fileManager.js @@ -398,6 +398,15 @@ class FileManager extends Plugin { 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) { delete this.openedFiles[name] if (!Object.keys(this.openedFiles).length) { diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index bf5fd6ba05..7e44fc2520 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -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 */ async setWorkspace (workspace) { - this._deps.fileManager.removeTabsOf(this._deps.fileProviders.workspace) + this._deps.fileManager.closeAllFiles() if (workspace.isLocalhost) { this.call('manager', 'activatePlugin', 'remixd') } else if (await this.call('manager', 'isActive', 'remixd')) { diff --git a/apps/remix-ide/src/app/panels/tab-proxy.js b/apps/remix-ide/src/app/panels/tab-proxy.js index 0bdef0c2ec..179a37065c 100644 --- a/apps/remix-ide/src/app/panels/tab-proxy.js +++ b/apps/remix-ide/src/app/panels/tab-proxy.js @@ -37,6 +37,11 @@ export class TabProxy extends Plugin { this.updateImgStyles() }) + fileManager.events.on('filesAllClosed', () => { + this.call('manager', 'activatePlugin', 'home') + this._view.filetabs.active = 'home' + }) + fileManager.events.on('fileRemoved', (name) => { const workspace = this.fileManager.currentWorkspace() diff --git a/apps/remix-ide/src/app/tabs/runTab/settings.js b/apps/remix-ide/src/app/tabs/runTab/settings.js index 8fc7da3700..c4ee816bc8 100644 --- a/apps/remix-ide/src/app/tabs/runTab/settings.js +++ b/apps/remix-ide/src/app/tabs/runTab/settings.js @@ -403,13 +403,13 @@ class SettingsUI { if (!accounts) accounts = [] if (this.accountListCallId > callid) return this.accountListCallId++ - for (var loadedaddress in this.loadedAccounts) { + for (const loadedaddress in this.loadedAccounts) { if (accounts.indexOf(loadedaddress) === -1) { txOrigin.removeChild(txOrigin.querySelector('option[value="' + loadedaddress + '"]')) delete this.loadedAccounts[loadedaddress] } } - for (var i in accounts) { + for (const i in accounts) { const address = accounts[i] if (!this.loadedAccounts[address]) { txOrigin.appendChild(yo``) diff --git a/apps/remix-ide/src/app/ui/landing-page/landing-page.js b/apps/remix-ide/src/app/ui/landing-page/landing-page.js index 009bbe50f4..4383acaf77 100644 --- a/apps/remix-ide/src/app/ui/landing-page/landing-page.js +++ b/apps/remix-ide/src/app/ui/landing-page/landing-page.js @@ -22,6 +22,7 @@ const css = csjs` user-select: none; } .text:hover { + cursor: pointer; text-decoration: underline; } .homeContainer { @@ -300,6 +301,11 @@ export class LandingPage extends ViewPlugin { await this.appManager.activatePlugin('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 = () => { this.call('fileExplorers', 'createNewFile') @@ -456,7 +462,7 @@ export class LandingPage extends ViewPlugin { ) } - const img = yo`` + const img = yo`` const playRemi = async () => { await document.getElementById('remiAudio').play() } // to retrieve medium posts document.body.appendChild(yo``) @@ -466,24 +472,46 @@ export class LandingPage extends ViewPlugin {
-
+
${img} +
+
Quicklinks
+ Guide for migrating the old File System +

Migration tools:

+
  • + + migrateWorkspace()}>Basic migration + +
  • +
  • + downloadFiles()}>Download all Files + as a backup zip +
  • +
  • + startRestoreBackupZip()}>Restore filesfrom backup zip +
  • +

    Help:

    + + Gitter channel + Report on Github + +
    -

    Featured Plugins

    -
    - ${this.solEnv} - ${this.learnEthEnv} - ${this.solhintEnv} - ${this.sourcifyEnv} - ${this.debuggerEnv} - ${this.moreEnv} +

    Featured Plugins

    +
    + ${this.solEnv} + ${this.learnEthEnv} + ${this.solhintEnv} + ${this.sourcifyEnv} + ${this.debuggerEnv} + ${this.moreEnv} +
    -

    File

    @@ -495,22 +523,17 @@ export class LandingPage extends ViewPlugin {

    connectToLocalhost()}>Connect to Localhost

    -

    - - downloadFiles()}>Download all Files -

    @@ -529,7 +552,7 @@ export class LandingPage extends ViewPlugin {

    Gitter channel -

    +

    ${this.websiteIcon} Featuring website @@ -538,10 +561,6 @@ export class LandingPage extends ViewPlugin { switchToPreviousVersion()}>Old experience

    -

    - - migrateWorkspace()}>Migrate old filesystem to workspace -

    diff --git a/apps/remix-ide/src/migrateFileSystem.js b/apps/remix-ide/src/migrateFileSystem.js index ab47956743..94ef8c0b7d 100644 --- a/apps/remix-ide/src/migrateFileSystem.js +++ b/apps/remix-ide/src/migrateFileSystem.js @@ -1,6 +1,7 @@ import { Storage } from '@remix-project/remix-lib' 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 */ @@ -53,7 +54,11 @@ const populateWorkspace = async (workspace, json, browserProvider) => { browserProvider.createDir(joinPath(workspace, item)) await populateWorkspace(workspace, json[item].children, browserProvider) } 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`
    There was an error migrating your files:${err.message}
    Please use the ‘Download all Files' action, clear the local storage and re-import your files manually or use the 'Restore files' action.
    `) + } + }) } } } diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index f02aae45a5..33bfd203fa 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -1001,7 +1001,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
    { 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') === 'fileExplorerFileUpload') return // we don't want to let propagate the input of type file let expandPath = [] if (!state.expandPath.includes(props.name)) { diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index dbde392b20..6a41a942bc 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -208,6 +208,7 @@ export const Workspace = (props: WorkspaceProps) => { } const onFinishDeleteWorkspace = async () => { + await props.fileManager.closeAllFiles() const workspacesPath = props.workspace.workspacesPath props.browser.remove(workspacesPath + '/' + state.currentWorkspace) const name = state.currentWorkspace @@ -223,7 +224,7 @@ export const Workspace = (props: WorkspaceProps) => { } const setWorkspace = async (name) => { - props.setWorkspace({ name, isLocalhost: name === LOCALHOST }) + await props.setWorkspace({ name, isLocalhost: name === LOCALHOST }) if (name === LOCALHOST) { props.workspace.clearWorkspace() } else if (name === NO_WORKSPACE) { @@ -238,8 +239,8 @@ export const Workspace = (props: WorkspaceProps) => { } const remixdExplorer = { - hide: () => { - if (state.currentWorkspace === LOCALHOST) setWorkspace(NO_WORKSPACE) + hide: async () => { + await setWorkspace(NO_WORKSPACE) props.fileManager.setMode('browser') setState(prevState => { return { ...prevState, hideRemixdExplorer: true, loadingLocalhost: false } diff --git a/release-management.md b/release-management.md new file mode 100644 index 0000000000..0b81f93395 --- /dev/null +++ b/release-management.md @@ -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 diff --git a/release-process.md b/release-process.md index 354fd23b3a..ceb1caccbc 100644 --- a/release-process.md +++ b/release-process.md @@ -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: -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. +## Remix IDE release Part 1. First push master to beta. Feature Freeze + - git co -b remix_beta origin/remix_beta + - git reset --hard -master-commit-hash- + - git push -f origin remix_beta + +## Testing phase +## In case of fixing bugs push PR's also to beta to include in Release + +## Remix IDE release Part 2. Bump the version in beta and release -## 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. + - git fetch origin remix_beta + - git checkout origin/remix_beta + - 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) -## 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. + - 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 + +## Remix IDE release Part 4. remix.ethereum.org update -## 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. +This is not strictly speaking a release. Updating the remix site is done through the Travis build: + - git co -b remix_live origin/remix_live + - git reset --hard -master-commit-hash- (or remix_beta-commit-hash-) + - git push -f origin remix_live -# Responsibilities + CircleCI will build automaticaly and remix.ethereum.org will be updated - - 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. +## 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. + +## 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 -# 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 +remix-alpha.ethereum.org is automaticaly updated every time commits are pushed to master \ No newline at end of file