diff --git a/README.md b/README.md index 050aeb4080..5ed9633bb8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ [![Build Status](https://travis-ci.org/ethereum/remix-ide.svg?branch=master)](https://travis-ci.org/ethereum/remix-ide) +[![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=MTc5WVBoNnhOTGhaUng3ZFI3MDZvNWkraHIrd1FNanZIZk80SG9uMkFIND0tLUoyUjd1YVhWRnRrcUJMMnFlbmN3Y0E9PQ==--4085377897aef217e507c8fc46d463eb699838b8)](https://www.browserstack.com/automate/public-build/MTc5WVBoNnhOTGhaUng3ZFI3MDZvNWkraHIrd1FNanZIZk80SG9uMkFIND0tLUoyUjd1YVhWRnRrcUJMMnFlbmN3Y0E9PQ==--4085377897aef217e507c8fc46d463eb699838b8) + + # Remix @@ -32,8 +35,9 @@ Or if you want to clone the github repository (`wget` need to be installed first ```bash git clone https://github.com/ethereum/remix-ide.git cd remix-ide +npm run setupremix # this will clone https://github.com/ethereum/remix for you and link it to remix-ide npm install -npm run build && npm run serve +npm start ``` ## DEVELOPING: @@ -44,21 +48,6 @@ Then open your `text editor` and start developing. The browser will automatically refresh when files are saved. Most of the the time working with other modules (like debugger etc.) hosted in the [Remix repository](https://github.com/ethereum/remix) is not needed. -But in case changes have to be made in that repository too, the following command will help you link Remix with your local remix-ide repository: - -After `npm install` run also: - -```bash -npm run pullremix - -npm run linkremixcore - -npm run linkremixlib - -npm run linkremixsolidity - -npm run linkremixdebugger -``` ### Troubleshooting building diff --git a/release-process.md b/release-process.md new file mode 100644 index 0000000000..a5e0ffdb6e --- /dev/null +++ b/release-process.md @@ -0,0 +1,45 @@ +This document includes: + - how to make npm, github release of remix-* packages + - how to update remix.ethereum.org. + - how to update remix-alpha.ethereum.org. + +# remix-* release (npm release, github release) + + - For a specifix module (lib/core/debug/ide/solidity/tests) + - In a new branch, bump the version in package.json, push it and create PR. + - Wait for tests completion. + - merge PR + - build the branch ( `npm run build` for remix-ide ). + - execute `npm publish`. + - create new `tag` ( e.g `git tag v0.6.1-alpha.2` ). + - push the tag ( `git push --tag` ). + - execute `gren changelog --generate -t .. --data-source=prs`. + - in `changelog.md` remove the closed and non merged PR. + - publish a release in github using the changelog. + + +# remix.ethereum.org update + +This is not strictly speaking a release. Updating the remix site is done through the Travis build: + + - In remix-ide repository + - Switch to the branch `remix_live` + - Rebase the branch against master + - Force push + - https://travis-ci.org/ethereum/remix-ide + - Click `More options` + - Click `Trigger build` + - Select `remix_live` + - Click `Trigger custom build` + - Once the build is finished (can take a while) and successful, check remix.ethereum.org is updated accordingly + +# remix-alpha.ethereum.org update + +This is not strictly speaking a release. Updating the remix-alpha site is done through the Travis build: + + - https://travis-ci.org/ethereum/remix-ide + - Click `More options` + - Click `Trigger build` + - Select `Master` + - Click `Trigger custom build` + - Once the build is finished (can take a while) and successful, check remix-alpha.ethereum.org is updated accordingly diff --git a/src/app/panels/righthand-panel.js b/src/app/panels/righthand-panel.js index 94e75752b7..84aff7cceb 100644 --- a/src/app/panels/righthand-panel.js +++ b/src/app/panels/righthand-panel.js @@ -37,9 +37,8 @@ function RighthandPanel (appAPI = {}, events = {}, opts = {}) { ` - appAPI.switchTab = (tabClass) => { - this.event.trigger('switchTab', [tabClass]) - } + // selectTabByClassName + appAPI.switchTab = tabClass => self._view.tabbedMenu.selectTabByClassName(tabClass) events.rhp = self.event diff --git a/src/app/plugin/pluginManager.js b/src/app/plugin/pluginManager.js index 6a08bac100..0c1c5ba955 100644 --- a/src/app/plugin/pluginManager.js +++ b/src/app/plugin/pluginManager.js @@ -75,48 +75,47 @@ * See index.html and remix.js in test-browser folder for sample * */ -class PluginManager { +module.exports = class PluginManager { constructor (api = {}, events = {}, opts = {}) { - var self = this - this.plugins = {} - this.inFocus - var allowedapi = {'setConfig': 1, 'getConfig': 1, 'removeConfig': 1} - events.compiler.register('compilationFinished', (success, data, source) => { - if (this.inFocus) { + const self = this + self._opts = opts + self._api = api + self._events = events + self.plugins = {} + self.inFocus + self.allowedapi = {'setConfig': 1, 'getConfig': 1, 'removeConfig': 1} + self._events.compiler.register('compilationFinished', (success, data, source) => { + if (self.inFocus) { // trigger to the current focus - this.post(this.inFocus, JSON.stringify({ + self.post(self.inFocus, JSON.stringify({ action: 'notification', key: 'compiler', type: 'compilationFinished', - value: [ - success, - data, - source - ] + value: [ success, data, source ] })) } }) - events.app.register('tabChanged', (tabName) => { - if (this.inFocus && this.inFocus !== tabName) { + self._events.app.register('tabChanged', (tabName) => { + if (self.inFocus && self.inFocus !== tabName) { // trigger unfocus - this.post(this.inFocus, JSON.stringify({ + self.post(self.inFocus, JSON.stringify({ action: 'notification', key: 'app', type: 'unfocus', value: [] })) } - if (this.plugins[tabName]) { + if (self.plugins[tabName]) { // trigger focus - this.post(tabName, JSON.stringify({ + self.post(tabName, JSON.stringify({ action: 'notification', key: 'app', type: 'focus', value: [] })) - this.inFocus = tabName - this.post(tabName, JSON.stringify({ + self.inFocus = tabName + self.post(tabName, JSON.stringify({ action: 'notification', key: 'compiler', type: 'compilationData', @@ -136,10 +135,10 @@ class PluginManager { value: [ result ] })) } - if (event.type === 'message' && this.inFocus && this.plugins[this.inFocus] && this.plugins[this.inFocus].origin === event.origin) { + if (event.type === 'message' && self.inFocus && self.plugins[self.inFocus] && self.plugins[self.inFocus].origin === event.origin) { var data = JSON.parse(event.data) - data.value.unshift(this.inFocus) - if (allowedapi[data.type]) { + data.value.unshift(self.inFocus) + if (self.allowedapi[data.type]) { data.value.push((error, result) => { response(data.key, data.type, data.id, error, result) }) @@ -149,13 +148,13 @@ class PluginManager { }, false) } register (desc, content) { - this.plugins[desc.title] = {content, origin: desc.url} + const self = this + self.plugins[desc.title] = {content, origin: desc.url} } post (name, value) { - if (this.plugins[name]) { - this.plugins[name].content.querySelector('iframe').contentWindow.postMessage(value, this.plugins[name].origin) + const self = this + if (self.plugins[name]) { + self.plugins[name].content.querySelector('iframe').contentWindow.postMessage(value, self.plugins[name].origin) } } } - -module.exports = PluginManager diff --git a/src/app/tabs/analysis-tab.js b/src/app/tabs/analysis-tab.js index 6dea63f56c..f2bda461ca 100644 --- a/src/app/tabs/analysis-tab.js +++ b/src/app/tabs/analysis-tab.js @@ -1,12 +1,32 @@ var yo = require('yo-yo') -var css = require('./styles/analysis-tab-styles') +var csjs = require('csjs-inject') +var remixLib = require('remix-lib') -function analysisTab (api = {}, events = {}, opts = {}) { - var el = yo` -
-
- ` - return { render () { return el } } -} +var EventManager = remixLib.EventManager -module.exports = analysisTab +module.exports = class AnalysisTab { + constructor (opts = { api: {}, events: {} }) { + const self = this + self.event = new EventManager() + self._api = opts.api + self._events = opts.events + self._view = { el: null } + self.data = {} + self._components = {} + } + render () { + const self = this + if (self._view.el) return self._view.el + self._view.el = yo` +
` + return self._view.el + } +} +const css = csjs` + .analysisTabView { + padding: 2%; + padding-bottom: 3em; + display: flex; + flex-direction: column; + } +` diff --git a/src/app/tabs/plugin-tab.js b/src/app/tabs/plugin-tab.js index 6a8c700485..9b92233c0c 100644 --- a/src/app/tabs/plugin-tab.js +++ b/src/app/tabs/plugin-tab.js @@ -1,12 +1,37 @@ var yo = require('yo-yo') -var css = require('./styles/plugin-tab-styles') +var csjs = require('csjs-inject') +var remixLib = require('remix-lib') -function plugintab (api = {}, events = {}, opts = {}) { - var el = yo` -
- -
` - return { render () { return el } } -} +var EventManager = remixLib.EventManager -module.exports = plugintab +module.exports = class plugintab { + constructor (api = {}, events = {}, opts = {}) { + const self = this + self.event = new EventManager() + self._opts = opts + self._api = api + self._events = events + self._view = { el: null } + self._components = {} + } + render () { + const self = this + if (self._view.el) return self._view.el + self._view.el = yo` +
+ +
` + return self._view.el + } +} +const css = csjs` + .pluginTabView { + height: 100%; + width: 100%; + } + .iframe { + height: 100%; + width: 100%; + border: 0; + } +` diff --git a/src/app/tabs/run-tab.js b/src/app/tabs/run-tab.js index 6efe21e5aa..d97155f89f 100644 --- a/src/app/tabs/run-tab.js +++ b/src/app/tabs/run-tab.js @@ -65,7 +65,7 @@ function runTab (appAPI = {}, appEvents = {}, opts = {}) { function setFinalContext () { // set the final context. Cause it is possible that this is not the one we've originaly selected selectExEnv.value = executionContext.getProvider() - fillAccountsList(appAPI, el) + fillAccountsList(appAPI, opts, el) event.trigger('clearInstance', []) } diff --git a/src/app/tabs/styles/analysis-tab-styles.js b/src/app/tabs/styles/analysis-tab-styles.js deleted file mode 100644 index 7d9080ed03..0000000000 --- a/src/app/tabs/styles/analysis-tab-styles.js +++ /dev/null @@ -1,26 +0,0 @@ -// -------------- styling ---------------------- -var csjs = require('csjs-inject') -var styleGuide = require('../../ui/styles-guide/theme-chooser') -var styles = styleGuide.chooser() - -var css = csjs` - .analysisTabView { - padding: 2%; - padding-bottom: 3em; - display: flex; - flex-direction: column; - } - #staticanalysisView { - display: block; - } - .infoBox { - ${styles.infoTextBox} - margin-bottom: 1em; - } - .textBox { - ${styles.textBoxL} - margin-bottom: 1em; - } -` - -module.exports = css diff --git a/src/app/tabs/styles/plugin-tab-styles.js b/src/app/tabs/styles/plugin-tab-styles.js deleted file mode 100644 index 3e22de4fa8..0000000000 --- a/src/app/tabs/styles/plugin-tab-styles.js +++ /dev/null @@ -1,16 +0,0 @@ -var csjs = require('csjs-inject') - -var css = csjs` - .pluginTabView { - height: 100%; - width: 100%; - } - - .iframe { - height: 100%; - width: 100%; - border: 0; - } -` - -module.exports = css diff --git a/src/app/tabs/styles/tabbed-menu-styles.js b/src/app/tabs/styles/tabbed-menu-styles.js deleted file mode 100644 index a076ae1131..0000000000 --- a/src/app/tabs/styles/tabbed-menu-styles.js +++ /dev/null @@ -1,38 +0,0 @@ -var csjs = require('csjs-inject') -var styleGuide = require('../../ui/styles-guide/theme-chooser') -var styles = styleGuide.chooser() - -var css = csjs` - li.active { - background-color: ${styles.rightPanel.backgroundColor_Tab}; - color: ${styles.appProperties.mainText_Color} - } - .options { - float: left; - padding-top: 0.7em; - min-width: 60px; - font-size: 0.9em; - cursor: pointer; - font-size: 1em; - text-align: center; - } - .opts { - display: flex; - list-style: none; - margin: 0; - padding: 0; - } - .opts_li { - display: block; - font-weight: bold; - color: ${styles.rightPanel.text_Teriary} - } - .opts_li.active { - color: ${styles.rightPanel.text_Primary} - } - .opts_li:hover { - color: ${styles.rightPanel.icon_HoverColor_TogglePanel} - } -` - -module.exports = css diff --git a/src/app/tabs/tabbed-menu.js b/src/app/tabs/tabbed-menu.js index 85d402febb..ba70f27636 100644 --- a/src/app/tabs/tabbed-menu.js +++ b/src/app/tabs/tabbed-menu.js @@ -1,52 +1,101 @@ var yo = require('yo-yo') +var csjs = require('csjs-inject') +var remixLib = require('remix-lib') + var helper = require('../../lib/helper') +var styles = require('../ui/styles-guide/theme-chooser').chooser() -var css = require('./styles/tabbed-menu-styles') +var EventManager = remixLib.EventManager -class TabbedMenu { +module.exports = class TabbedMenu { constructor (api = {}, events = {}, opts = {}) { - var self = this - var tabView = document.createElement('ul') - this.tabView = tabView - this.events = events - this.tabs = {} - this.contents = {} - + const self = this + self.event = new EventManager() + self._opts = opts + self._api = api + self._events = events + self._view = { el: null, viewport: null, tabs: {}, contents: {} } events.app.register('debuggingRequested', () => { - self.selectTab(tabView.querySelector('li.debugView')) - }) - - events.rhp.register('switchTab', tabName => { - self.selectTab(tabView.querySelector(`li.${tabName}`)) + self.selectTabByTitle('Debugger') }) } - render () { return this.tabView } + render () { + const self = this + if (self._view.el) return self._view.el + self._view.el = yo`` + return self._view.el + } + renderViewport () { + const self = this + if (self._view.viewport) return self._view.viewport + self._view.viewport = yo` +
+ ${Object.values(self._view.contents)} +
` + return self._view.viewport + } + addTab (title, cssClass, content) { + const self = this + if (helper.checkSpecialChars(title)) return + if (self._view.contents[title] || self._view.tabs[title]) throw new Error('tab already exists') + self._view.contents[title] = content + self._view.tabs[title] = yo`
  • ${title}
  • ` + if (self._view.el) self._view.el.appendChild(self._view.tabs[title]) + if (self._view.viewport) self._view.viewport.appendChild(self._view.contents[title]) + } selectTabByTitle (title) { - this.selectTab(this.tabs[title]) + const self = this + self.selectTab(self._view.tabs[title]) + } + selectTabByClassName (tabClass) { + const self = this + self.selectTab(self._view.el.querySelector(`li.${tabClass}`)) } - selectTab (el) { + const self = this if (!el.classList.contains(css.active)) { - var nodes = el.parentNode.querySelectorAll('li') + var nodes = Object.values(self._view.tabs) for (var i = 0; i < nodes.length; ++i) { nodes[i].classList.remove(css.active) - this.contents[nodes[i].getAttribute('title')].style.display = 'none' + self._view.contents[nodes[i].getAttribute('title')].style.display = 'none' } } var title = el.getAttribute('title') - this.contents[el.getAttribute('title')].style.display = 'block' + self._view.contents[el.getAttribute('title')].style.display = 'block' el.classList.add(css.active) - this.events.app.trigger('tabChanged', [title]) - } - - addTab (title, cssClass, content) { - var self = this - if (!helper.checkSpecialChars(title)) { - this.contents[title] = content - this.tabs[title] = yo`
  • ${title}
  • ` - this.tabView.appendChild(this.tabs[title]) - } + self._events.app.trigger('tabChanged', [title]) } } -module.exports = TabbedMenu +const css = csjs` + li.active { + background-color: ${styles.rightPanel.backgroundColor_Tab}; + color: ${styles.appProperties.mainText_Color} + } + .options { + float: left; + padding-top: 0.7em; + min-width: 60px; + font-size: 0.9em; + cursor: pointer; + font-size: 1em; + text-align: center; + } + .opts { + display: flex; + list-style: none; + margin: 0; + padding: 0; + } + .opts_li { + display: block; + font-weight: bold; + color: ${styles.rightPanel.text_Teriary} + } + .opts_li.active { + color: ${styles.rightPanel.text_Primary} + } + .opts_li:hover { + color: ${styles.rightPanel.icon_HoverColor_TogglePanel} + } +` diff --git a/team-best-practices.md b/team-best-practices.md new file mode 100644 index 0000000000..b9a2ae081c --- /dev/null +++ b/team-best-practices.md @@ -0,0 +1,227 @@ + +# Team best practices + +This document aims to address contibutors best practices of the following repositories: + - remix-ide https://github.com/ethereum/remix-ide + - remix https://github.com/ethereum/remix + - remix-tests https://github.com/ethereum/remix-tests + +This document is not in its final version, **a team meeting which aim to address new/old best practices, feedback, workflows, all kind of issues related to how the team work together occurs every 2 weeks.** +This document link to other specialised best practices (like coding best practices). + +Related links: + - Remix live: remix.ethereum.org + - Remix alpha live: remix-alpha.ethereum.org + - Remix-ide NPM module: https://www.npmjs.com/package/remix-ide + - Remix-core NPM module: https://www.npmjs.com/package/remix-core + - Remix-lib NPM module: https://www.npmjs.com/package/remix-lib + - Remix-solidity NPM module: https://www.npmjs.com/package/remix-solidity + - Remix-debug NPM module: https://www.npmjs.com/package/remix-debug + - Remix documentation: http://remix.readthedocs.io/en/latest/ + - General gitter channel: https://gitter.im/ethereum/remix + - Dev gitter channel: https://gitter.im/ethereum/remix-dev + - Huboard (task management tool): https://huboard.com/ethereum/remix-ide + +--- + +# Team communication + + ### 1) Team meetings: + + - A regular standup - each Tuesday 4pm CET - which aim to + - Update every contributor on what others are doing. + - Update the prioritised issues / PRs list. + - Address little issues (possibly related to the current ongoing milestone). + - High level demo, explanation about specific points of the codebase or Ethereum related things. + + - A milestone standup - scheduled before the beginning of each milestone, roughly on a monthly basis - which aim to define what will be included in the **next milestone** and who will work on what. This standup also help to set a clear long term vision. + + - A retrospective standup - every 2 weeks - which aim to talk about **best practices in general**: what is good, what is bad, how we can improve workflows. + + - A tour standup - on a monthly basis and just after a milestone finished - which aim to demo, **explain in details** features, bug fixes or any part of the codebase. + + + ### 2) Group meetings: + + - When a story / bug fix is divided in parts, there should be a kickstart meeting with all the developers involved, so that all the devs have an good overview / understanding on: + - How the story fits into the Ethereum tech. + - How the backend (if any) works / will work (could be a smart contract). + - How the frontend works / will work. + - What is the general vision of the UX design for this particular story. + Later progress and discussion is updated directly on the issue or pull request (Github). + + +--- + +# Prerequisites: + +Before starting coding, we should ensure all devs / contributors are aware of: +- Where the codebase is. +- How to setup and get started (always up to date). +- How to run tests. +- Where to find documentation. +- How to reach us through the communication channels - https://gitter.im/ethereum/remix, https://gitter.im/ethereum/remix-dev. +- The following best practices: + +--- + +# Story / Bug fix + +- Prioritised list of PRs / issues are tracked in the Remix huboard. +- Every story can be executed by a single developer or a group of 2 or more developers (depending on the size and complexity) +- Each dev should take the part he/she feels the most confortable with. +- Later progress and discussion is updated directly on the issue or pull request (github). +- When a developer or team decides on the story they want to work on (at the start of milestone for instance), they assign themselves to the issue. +- The issue whould be moved in Huboard to the column named `working` when the work actually starts. +- Updates of the documentation should be done together with the story. + +--- + +# Pull Requests + + ### 1) PR Creator: + + - It is recommended to use the emoji responses to signal agreement or that you've seen a comment and will address it rather than replying. This reduces github inbox spam. + - Mark unfinished pull requests with the `Work in Progress` label + - Large pull requests (above 200-400 lines of code changed) cannot be effectively reviewed and should be split into smaller pieces. + - Code should comply to the `JavaScript standard style` - https://www.npmjs.com/package/standard + - You should not expect complete review on a pull request which is not passing CI. + - You can obviously ask for feedback on your approach. + - You should assign a reviewer. + - Pull requests should be used as a reference to update coding best practices whenever it is needed. + + ### 2) Review: + + - Everyone is free to review any pull request. + - You should add the label "change requested" or "accepted". + - When reviewing people's code consider the following two comments. + > I don't like the name of this function. + + vs. + + > What do you think about changing the name of this function to .... + + Your feedback will often be better received if you pose it in the form of a question. + + - Pull request should be reviewed to comply to coding best practices. + - You should take the responsability of the PR you are reviewing. + - You should make sure the app is viable after the PR is being merged. + - Ideally You should have enough knowledge to be able to fix related bugs. + + ### 3) Merge: + + - Merging is possible after Review and Tests are ok and when the PR is approved. + - If possible the build of the dev branch (master) should be triggered in the Travis CI. + - After a merge and master being built in Travis, it is highly recommended to check the new code in `remix-alpha.ethereum.org` + +--- + +# Milestone + + - A milestone is small and contains **only** items we are sure to finish. + - The end of a milestone trigger a new release. + - Milestone items and duration should take in account time spent in bugs fixing and support. + - The team should commit to the milestone duration. + - If a dev finish early he/she can help other to push remaining tasks. + - If a dev finish early he/she can work on specifying / integrating the next milestone. + - A milestone duration is fixed at the start of the milestone (but should not exceed 1 month). + - Progress and issues regarding a milestone are discussed on regular standups. + +--- + +# Releases + + ### 1) Process: + - Should be documented and updated. + - A new release is triggered: + - after an important bug fix + - at the end of a milestone + - Pushing `remix-alpha.ethereum.org` should be done very frequently (if possible after each feature / bug fix completion. + - We can release an `m.m.m-alpha.x` (whenever we need to release and for whatever reasons) being in between a feature / bug fix completion. + - We release an `m.m.x` whenever there is a bug fix. + - We release an `m.x.0` whenever there is a new feature. + - We release an `x.0.0` after each milestone we consider being an important progress. + - We release an `x.0.0` if there's an API breaking change in one of our libraries. + - After a new release we should stay in alert for possible regression and better not release Friday at 5pm :) + + ### 2) Community: + - Before the official release, we should select a group of power users and invite them to test and give feedbacks. + - Users need to know upfront a new release is coming and we should prepare them for it by showcasing some new features they can expect and when it will happen (fixed date, published at least 1 week in advance). + - Whenever we have a new release we have to communicate this efficiently (twitter, reddit, ...). + +--- + +# Maintenance + + +### 1) Bugs: +- A critical bug should get the label `Blocker`, and every effort should be put to fix it. +- Addressing a non critical and non planned bug can be done: +  - After having notified in the `remix-dev` channel if the bug does not involves UX or public API changes. + - After a dev meeting (e.g the regular standup) if the bug involves any UX or public API changes. + +### 2) Support: + +- We should all keep an eye on the public non dev channel and file user feedback. + +### 3) Documentation: + +- The documentation is done / updated just after the feature / release in a team effort. +- Documentation work is filable as a github issue. +- It is encouraged to find and link associated doc produced by the community (blog posts, videos, tutorials, ...) + +--- + +# Coding best practices + + - https://github.com/ethereum/remix-ide/blob/master/best-practices.md + +--- + + +## Best practices to address later + +### meeting: + - Find a good calendar we can use to schedule meetings. + - Retrospective meeting: Someone can be responsible to record the findings (of the retrospective meeting) so we can review them in the following meeting and see if they were addressed or not, and if not discuss why and take new actions. If the issue was addressed then it can be discarded. + - pair programming meetings + +### merge process: + - All the contributors of the feature should be able to merge. + - Review should have 3 phases (1. code should work, 2. code should fit with current best practices, 3. update documentation) + - We should have a dedicated person to only do browser frontend tests and make it easy for others to run them + +### release process: + + - We release an `x.0.0` if there's a fundamental change in our UX design, which means users will need to readapt the way they use the app + - after a week finishes, we publish/release a new version as **remix-beta.ethereum.org** and inform users so early adopters can test. after another week, when then next finished work is released as **remix-beta.ethereum.org**, the previous one becomes **remix.ethereum.org** and all users can start using it + - a bot to automatically notify users about upcoming features on all channels whenever **remix-beta.ethereum.org** is updated + - in case it's a major version increase - this announcement should be specially marked so ppl can check early instead of being confronted with drastic changes when **remix.ethereum.org** updates +### maintenance: + - Setting up a "bug" time where we each take a bug for which: + - We feel confortable to deal with + or + - We don't feel confortable but interested in fixing it - that will need the help of another dev +### documentation: + - We set up a special day where we address all the necessary documentation work in a team effort. + - Change to markdown or gitbook + +### support: + - Remix channel - we rotate and each day one or two are responsible for support (It would also be important to know for those of us who are contracted, how this can be billed.). If they don't know the answer they ping team member who they think could answer. That team member checks the support chat that day only if she/he is mentioned. + - We should have a FAQ where basic answer are written down so we can drop the link regularly in the channel + - People should be pointed to the appropriate `best practice.md` files by team members + +### code best practices: + - for code quality: use codeclimate and address issues + - defining all global variables on top of the page + - 80-10 characters per line + - alphabetically list dependencies and separate npm from local for better readability + - Use code documentation tool + - Write modular code. +### community + - This should be a Remix team work, from time to time (maybe once every 6 months) we could also invite other EF members for a focus group. And every 6 months we could also organize a focus group of selected users from Remix channel. +### security + - https://github.com/pipermerriam/ethereum-dev-tactical-manual/blob/master/opsec.md +### bug bounty program + - https://github.com/pipermerriam/ethereum-dev-tactical-manual/blob/master/bug-bounty-program.md +