git ssb

1+

Daan Patchwork / manyverse



Tree: 59144b239d42fc08b00c84c0b0eb71dac3d39a26

Files: 59144b239d42fc08b00c84c0b0eb71dac3d39a26 / CONTRIBUTING.md

21850 bytesRaw

Contributor docs

Thank you for your interest in contributing code to Manyverse! Follow this guide rigorously, as it contains a lot of important details. The compilation of the app may not work with other settings.

In the explanations below, we will constantly refer to "development" and "target" operating systems.

๐Ÿ’ป "Development OS" means the operating system of the computer you are using to develop and compile the app.

๐Ÿ“ฑ "Target OS" means the operating system of the devices that you wish Manyverse to run on once you compile the app.

๐Ÿ’ป Setting up your development computer

Development OS

macOS specifics

If you are developing on a macOS computer, then you might need realpath, install it through coreutils:

brew update
brew install coreutils

Node.js

Use node ^10.13.0 and npm ~6.4.1. To manage versions of node easily, we recommend nvm.

React Native

Install the React Native CLI:

npm install --global react-native-cli

and follow the official React Native docs, choose "React Native CLI Quickstart", and then choose the Development OS and Target OS to match your use case.

Android SDK

If your target OS is Android, you need Android Studio and a recent Android SDK (installable through Android Studio).

You may need to open your app's /android folder in Android Studio, so that it detects, downloads and cofigures requirements that might be missing, like the NDK and CMake to build the native code part of the project. OR download those via the sdkmanager $ANDROID_HOME/tools/bin/sdkmanager 'ndk-bundle' 'cmake;3.6.4111459'.

You can also set the environment variable ANDROID_NDK_HOME, as in this example:

export ANDROID_NDK_HOME=/Users/username/Library/Android/sdk/ndk-bundle

Also check out nodejs-mobile docs for the additional Android SDK requirements on your computer.

This app only supports Android 5.0 and above.

iOS SDK

If your target OS is iOS, you need to install Xcode (preferably version 11 or higher, we are not sure if the app can build on lower versions of Xcode). You can find Xcode from the macOS App Store. The iOS SDK must be version 11 or higher.

See also nodejs-mobile docs for additional details.

๐Ÿ“ฑ Setting up you target device

Android

โš ๏ธ Emulators are not supported! You must have a real device (smartphone or tablet) available, and a USB cable to connect it with your development computer.

The reason why emulators are not supported is because we use nodejs-mobile for the backend thread in the app, and this only supports ARM architectures. Most emulators are x86 architectures. There may be ARM-supporting emulators that are compatible with Manyverse, but we don't promise that it will work correctly there.

Enable developer mode. Before developing, you need to set up the Android device, following these steps:

iOS

โš ๏ธ Simulators are not supported! You must have a real device (iPhone or iPad) available, and a USB cable to connect it with your development computer.

The reason why simulators are not supported is because we use nodejs-mobile for the backend thread in the app, and this only supports ARM architectures. iOS simulators run on your development computer, and use the x86 architecture.

It might be necessary to have an Apple's developer account, and your devices must be registered for development under that account. Take a look at React Native's Running on device page, select target "iOS" and "Development OS: macOS".

Setting up the Manyverse project

Git clone this repository to your computer, and then cd into the folder and run:

npm install

When targeting Android

There is nothing else you need to install at this point.

When targeting iOS

You need to also install the Cocoapods:

cd ios && pod install

Build and run in development

When targeting Android

You can run npm run android-dev which will run all the necessary scripts in order. Or you can run each step manually:

1: Compile TypeScript files

npm run lib

2: Propagate replacement modules throughout all dependencies using propagate-replacement-fields:

npm run propagate-replacements

3: Build the "backend" Node.js project (which runs ssb-server):

npm run build-backend-android

4: Build and run the Android app:

react-native run-android --variant=indieDebug

During step 4, another terminal may spawn with the React Native Metro bundler. The app should be installed automatically, if you have a device connected by USB. You can see the logs with react-native log-android or adb logcat.

In step 3, if you want to see more logs, then run npm run build-backend-android -- --verbose.

When targeting iOS

You can do it in Xcode or in the terminal. In Xcode, open the Manyverse project located in ./ios/Manyverse.xcworkspace, and then press the "play" button.

In the terminal, you can run npm run ios-dev which will run all the necessary scripts in order. Or you can run each step manually:

1: Compile TypeScript files

npm run lib

2: Propagate replacement modules throughout all dependencies using propagate-replacement-fields:

npm run propagate-replacements

3: Build the "backend" Node.js project (which runs ssb-server):

npm run build-backend-ios

4: Build and run the iOS app:

react-native run-ios --device

During step 4, another terminal may spawn with the React Native Metro bundler. The app should be installed automatically, if you have a device connected by USB.

In step 3, if you want to see more logs, then run npm run build-backend-ios -- --verbose.

Continuous compilation

To watch source code files and continuously compile them, use three terminals:

For Android, to "refresh" the app after editing frontend TypeScript code, run the following (it refreshes the JS and re-opens the app):

adb shell input text "RR" && sleep 5 && adb shell am force-stop se.manyver && adb shell monkey -p se.manyver 1

There is no support for continuously compiling the backend Node.js project.

Troubleshooting

On Android applications, the react-native build process is sometimes unable to rebuild assets. If you are getting errors while building the application using react-native run-android --variant=indieDebug, then the command npm run full-clean can help you do a clean rebuild of the project. Then, reinstall with npm i and rebuild.

app:installDebug FAILED - Could not find build of variant which supports .. an ABI in x86

ManyVerse only supports ARM architectures, but most virtual device emulators use an x86 architecture of the host computer, and are therefore not supported.

Debug your code using a 'real' mobile device connected over USB instead.

NullPointerException on npm run build-backend-android

If you see the error below while running the build-backend-android build script, you should try opening this project's android folder in android studio (using the build.gradle file to tell android studio it is a gradle project.) It should detect missing dependencies and give you the option to install them via the console window (and rebuild) at the bottom of the window.


Building native modules for armeabi-v7a...
Incremental java compilation is an incubating feature.

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':app'.
> Could not resolve all dependencies for configuration ':app:_debugApk'.
   > A problem occurred configuring project ':nodejs-mobile-react-native'.
      > java.lang.NullPointerException (no error message)

Issue labels

For every issue, pick a type, a scope, and a priority:

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.

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:

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.

This funnel shape also works for the Feature roadmap, which is kind of like a backlog, but less actionable, it's basically a backlog of ideas, while the issues are a backlog of tasks to perform as a developer.

Then there are less important issues, that are used just for communication:

Codebase overview

The app is built on these technologies:

There are three important parts to the app, executing in runtime as different threads: frontend thread handles UI logic for the features, backend thread handles local database and peer-to-peer networking capabilities, app thread lightly coordinates the lifecycle of the app and creation of the other two threads.

+---------------------------------+
|         FRONTEND THREAD         |
|                                 |         +----------------------------------+
|   TypeScript  (dev language)    |         |            APP THREAD            |
|   JavaScript  (target language) |         |----------------------------------|
|     Cycle.js  (framework)       |<------->|                                  |
| React Native  (JS runtime env)  |         | Java/ObjectiveC  (language)      |
| src/frontend  (path to src)     |         | Android/iOS SDK  (framework)     |
|        8000+  (lines of code)   |         |    React Native  (framework)     |
+---------------------------------+         | android/app/src  (path to src)   |
                                            |   ios/Manyverse  (path to src)   |
                                            |            250+  (lines of code) |
+---------------------------------+         |                                  |
|         BACKEND THREAD          |         |                                  |
|                                 |<------->|                                  |
|   TypeScript  (dev language)    |         |                                  |
|   JavaScript  (target language) |         |                                  |
|   ssb-server  (plugin system)   |         +----------------------------------+
|      Node.js  (JS runtime env)  |
|  src/backend  (path to src)     |
|         300+  (lines of code)   |
+---------------------------------+

Most app development happens in src/frontend and thus follows the Cycle.js 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:

Integration tests

Only Android is supported for end-to-end tests at the moment.

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.

Releases

To build a release APK, follow these instructions:

Generating an upload key

You can generate a private signing key using keytool. On Windows keytool must be run from C:\Program Files\Java\jdkx.x.x_x\bin.

$ keytool -genkeypair -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

This command prompts you for passwords for the keystore and key and for the Distinguished Name fields for your key. It then generates the keystore as a file called my-release-key.keystore.

The keystore contains a single key, valid for 10000 days. The alias is a name that you will use later when signing your app, so remember to take note of the alias.

On Mac, if you're not sure where your JDK bin folder is, then perform the following command to find it:

$ /usr/libexec/java_home

It will output the directory of the JDK, which will look something like this:

/Library/Java/JavaVirtualMachines/jdkX.X.X_XXX.jdk/Contents/Home

Navigate to that directory by using the command $ cd /your/jdk/path and use the keytool command with sudo permission as shown below.

$ sudo keytool -genkey -v -keystore my-upload-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

Note: Remember to keep the keystore file private. In case you've lost upload key or it's been compromised you should follow these instructions.

Setting up Gradle variables

  1. Place the my-release-key.keystore file under the android/app/ directory in your Manyverse project folder.
  2. Edit the file ~/.gradle/gradle.properties or android/gradle.properties, and add the following (replace ***** with the correct keystore password, alias and key password),
MYAPP_RELEASE_STORE_FILE=my-upload-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=*****
MYAPP_RELEASE_KEY_PASSWORD=*****

These are going to be global Gradle variables, which we can later use in our Gradle config to sign our app.

Note about security: If you are not keen on storing your passwords in plaintext, and you are running OSX, you can also store your credentials in the Keychain Access app. Then you can skip the two last rows in ~/.gradle/gradle.properties.

Generating the release APK

Run cd android && ./gradlew assembleRelease (just builds the APK).

Deploying new versions

Follow this guideline strictly.

Android

First make an Android release, then an iOS release.

iOS

Then make an iOS release:

Publish

Built with git-ssb-web