CONTRIBUTING.mdView |
---|
1 | 1 | # Contributor docs |
2 | 2 | |
3 | | - |
4 | 3 | ## Installation and dev setup |
5 | 4 | |
6 | 5 | This project uses React Native, Android SDK, Node.js and NPM. |
7 | 6 | |
56 | 55 | npm run lib |
57 | 56 | ``` |
58 | 57 | |
59 | 58 | `2`: Propagate replacement modules throughout all dependencies using [propagate-replacement-fields](https://github.com/staltz/propagate-replacement-fields): |
| 59 | + |
60 | 60 | ``` |
61 | 61 | npm run propagate-replacements |
62 | 62 | ``` |
63 | 63 | |
127 | 127 | |
128 | 128 | - **Type** indicates what audience the issue is relevant to |
129 | 129 | - `dx` means "developer experience" so these are issues that are related to refactoring, improving build system, tests, etc |
130 | 130 | - `ux` means "user experience" and can be either `ux: feature` or `ux: bug fix` to indicate to the user what kind of improvement this was |
131 | | - - Every git commit message starts with either `ux: ` or `dx: `, and the changelog is generated from the commit history, where only `ux` commit messages are shown. This means the commit messages are literally the changelog that appears to users when they update the app |
| 131 | + - Every git commit message starts with either `ux:` or `dx:`, and the changelog is generated from the commit history, where only `ux` commit messages are shown. This means the commit messages are literally the changelog that appears to users when they update the app |
132 | 132 | - **Scope** indicates what part of the codebase this issue is about. So far the codebase has only two relevant "places": |
133 | 133 | - `scope: backend` refers to the background Node.js project running the SSB server |
134 | 134 | - `scope: frontend` refers to the UI code in React Native and Cycle.js |
135 | 135 | - In the future there should be `scope: android` and `scope: ios` and maybe `scope: desktop` |
142 | 142 | There's also a rule for `priority` labeling: `must < should < could < maybe`. In other words, the number of `must` issues has to be less than the number of `should` issues, which has to be less than the number of `could` issues, etc. This gives a funnel shape to the kanban board, [see here](https://gitlab.com/staltz/manyverse/boards). |
143 | 143 | |
144 | 144 | Ideally, in a team of N developers working on Manyverse, there are N issues marked **work in progress**. In the "must" column, there are usually 2~4 issues per developer, which means at any time I choose the next work to do, I only have to pick one issue out of three, approximately. I try to keep a somewhat golden ratio progression (i.e. more than 1x, less than 2x multiplication) to the shape of the funnel, but it doesn't need to be so strictly organized. The importance of organizing the issues is also proportional to the priority: |
145 | 145 | |
146 | | -- It's *very* important to keep the "must" column organized and well chosen |
147 | | -- It's *somewhat* important to keep the "should" column organized and well chosen |
| 146 | +- It's _very_ important to keep the "must" column organized and well chosen |
| 147 | +- It's _somewhat_ important to keep the "should" column organized and well chosen |
148 | 148 | - It's not that important to keep the "could" column organized |
149 | 149 | - It's not important to keep the "maybe" column organized |
150 | 150 | |
151 | 151 | Once in a while, as issues get done, we go through the issues in lower priorities and begin promoting them to higher levels. You can think of this funnel as a job interview process with multiple stages of interviews. We try to imagine which of these issues "earns its spot" the best. And usually give priority to fixing bugs, because it's worth building new features after the current user experience is mostly bugless. But every month there should be at least one new feature, even a small feature suffices. |
201 | 201 | ``` |
202 | 202 | |
203 | 203 | Most app development happens in `src/frontend` and thus follows the [Cycle.js](https://cycle.js.org/) architecture, but utilizes React Native components for rendering. It's good to get familiar with the architecture, but here is an explanation of it in a nutshell: |
204 | 204 | |
205 | | -- Each *screen* in the app is a Cycle.js component |
| 205 | +- Each _screen_ in the app is a Cycle.js component |
206 | 206 | - A Cycle.js component is a function with `sources` as input and `sinks` as output |
207 | 207 | - `Sources` is an object with several "source" streams, one stream per "channel" |
208 | 208 | - `Sinks` is an object with several "sink" streams, one stream per channel |
209 | 209 | - A **channel** is a name designated to a certain type of effect, for instance, we have the channels: |
213 | 213 | - `screen`: for sending UI updates to render on the screen, or for listening to UI events |
214 | 214 | - `dialog`: for creating and interacting with UI dialogs overlaying the app |
215 | 215 | - etc |
216 | 216 | - **Drivers** handle interactions with channels, there is typically one **driver** per channel, for instance see `src/frontend/drivers/dialogs.ts` |
217 | | -- In a Cycle.js component, *data flows* from the sources to the sinks, passing through *transformations and combination* steps in between |
| 217 | +- In a Cycle.js component, _data flows_ from the sources to the sinks, passing through _transformations and combination_ steps in between |
218 | 218 | - Transformation and combination of streams is done with **stream operators** from the library [xstream](https://github.com/staltz/xstream/) |
219 | 219 | - Typically, streams are created and transformed in these sections: |
220 | 220 | - `intent`: handles raw streams of UI events and interprets what they mean, creating "action" streams |
221 | 221 | - `model`: take action streams as input and return "reducer" streams as outputs, to change the UI state |
224 | 224 | - etc |
225 | 225 | |
226 | 226 | ## Integration tests |
227 | 227 | |
228 | | -We use Appium and Tape, just plug in a device through USB and run `npm run test-e2e-android`. This will run tests on top of the *release* variant of the app, so it that doesn't exist, you must run `npm run build-android-release` first. See the guide below on how to generate release builds. |
| 228 | +We use Appium and Tape, just plug in a device through USB and run `npm run test-e2e-android`. This will run tests on top of the _release_ variant of the app, so it that doesn't exist, you must run `npm run build-android-release` first. See the guide below on how to generate release builds. |
229 | 229 | |
230 | 230 | ## Releases |
231 | 231 | |
232 | 232 | To build a release APK, follow these instructions: |
293 | 293 | |
294 | 294 | Then make an iOS release: |
295 | 295 | |
296 | 296 | - `git pull origin master` on a computer that can build iOS |
297 | | -- Run `npm run prerelease-ios` |
298 | | -- In Xcode: `Product` > `Archive` |
299 | | -- Once archiving is complete, Upload the app version to App Store |
| 297 | +- Run `npm run release-ios` |
| 298 | +- Once done, it should an _Organizer_ window where you should upload the new version to App Store |
300 | 299 | |
301 | 300 | ### Publish |
302 | 301 | |
303 | 302 | - Publish Android on F-Droid: `git push origin --tags` (F-Droid server pulls our updates) |