From 188cf7af626f53fd2829bed760c25577444435ac Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Fri, 21 May 2021 10:50:41 +0200 Subject: [PATCH] Add developer/project infos Signed-off-by: Andy Scherzinger --- CONTRIBUTING.md | 376 ++++++++++++++++++++++++++++++ SETUP.md | 102 ++++++++ docs/branching.png | Bin 0 -> 22626 bytes docs/branching.svg | 187 +++++++++++++++ docs/semantic_versioning_code.png | Bin 0 -> 5433 bytes 5 files changed, 665 insertions(+) create mode 100644 CONTRIBUTING.md create mode 100644 SETUP.md create mode 100644 docs/branching.png create mode 100644 docs/branching.svg create mode 100644 docs/semantic_versioning_code.png diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..3de5e9bc3 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,376 @@ +# [Nextcloud](https://nextcloud.com) Android app + + +# Index +1. [Guidelines](#guidelines) + 1. [Issue reporting](#issue-reporting) + 1. [Labels](#labels) + 1. [Pull request](#pull-request) + 1. [Issue](#issue) + 1. [Bug workflow](#bug-workflow) +1. [Contributing to Source Code](#contributing-to-source-code) + 1. [Developing process](#developing-process) + 1. [Branching model](#branching-model) + 1. [Android Studio formatter setup](#android-studio-formatter-setup) + 1. [Build variants](#build-variants) + 1. [Contribution process](#contribution-process) + 1. [Fork and download android repository](#fork-and-download-android-repository) + 1. [Create pull request](#create-pull-request) + 1. [Create another pull request](#create-another-pull-request) + 1. [Backport pull request](#backport-pull-request) + 1. [Adding new files](#adding-new-files) + 1. [Testing](#testing) + 1. [File naming](#file-naming) + 1. [Menu files](#menu-files) + 1. [Translations](#translations) + 1. [Engineering practices](#engineering-practices) + 1. [Approach to technical debt](#approach-to-technical-debt) + 1. [Dependency injection](#dependency-injection) + 1. [Testing](#testing) +1. [Releases](#releases) + 1. [Types](#types) + 1. [Stable](#stable) + 1. [Release Candidate](#release-candidate) + 1. [Alpha Release](#alpha-release) + 1. [QA Release](#qa-release) + 1. [Version Name and number](#version-name-and-number) + 1. [Stable / Release candidate](#stable--release-candidate) + 1. [Release cycle](#release-cycle) + 1. [Release Process](#release-process) + 1. [Stable Release](#stable-release) + 1. [Release Candidate Release](#release-candidate-release) + 1. [Alpha Release](#alpha-release) + + +# Guidelines + + +## Issue reporting +* [Report the issue](https://github.com/nextcloud/talk-android/issues/new/choose) and choose bug report or feature request. The template includes all the information we need to track down the issue. +* This repository is *only* for issues within the Nextcloud Talk Android app code. Issues in other components should be reported in their own repositories, e.g. [Nextcloud server](https://github.com/nextcloud/server/issues) +* Search the [existing issues](https://github.com/nextcloud/talk-android/issues) first, it's likely that your issue was already reported. +If your issue appears to be a bug, and hasn't been reported, open a new issue. + + +## Labels + + +### Pull request +* 2. developing +* 3. to review + + +### Issue +* nothing +* approved +* PR exists (and then the PR# should be shown in first post) + + +### Bug workflow +Every bug should be triaged in approved/needs info in a given time. +* approved: at least one other is able to reproduce it +* needs info: something unclear, or not able to reproduce + * if no response within 1 months, bug will be closed +* pr exists: if bug is fixed, link to pr + + +# Contributing to Source Code +Thanks for wanting to contribute source code to Nextcloud. That's great! + +New contributions are added under GPL version 3+. + + +## Developing process +We are all about quality while not sacrificing speed so we use a very pragmatic workflow. + +* create an issue with feature request + * discuss it with other developers + * create mockup if necessary + * must be approved --> label approved + * after that no conceptual changes! +* develop code +* create [pull request](https://github.com/nextcloud/talk-android/pulls) +* to assure the quality of the app, any PR gets reviewed, approved and tested before it will be merged to master + + +### Branching model +![branching model](/doc/branching.png "Branching Model") +* All contributions bug fix or feature PRs target the ```master``` branch +* Feature releases will always be based on ```master``` +* Bug fix releases will always be based on their respective feature-release-bug-fix-branches +* Bug fixes relevant for the most recent _and_ released feature (e.g. ```11.0.0```) or bugfix (e.g. ```11.2.1```) release will be backported to the respective bugfix branch (e.g. ```stable-11.0``` or ```stable-11.2```) +* Hot fixes not relevant for an upcoming feature release but the latest release can target the bug fix branch directly + + +### Android Studio formatter setup +Our formatter setup is rather simple: +* Standard Android Studio +* Line length 120 characters (Settings->Editor->Code Style->Right margin(columns): 120) +* Auto optimize imports (Settings->Editor->Auto Import->Optimize imports on the fly) + + +### Build variants +There are three build variants +* generic: no Google Stuff, used for F-Droid +* gplay: with Google Stuff (Push notification), used for Google Play Store +* qa: based on pr and available as direct download within the pr for testing purposes + + +## Contribution process +* Contribute your code in the branch ```master```. It will give us a better chance to test your code before merging it with stable code. +* For your first contribution start a pull request on master. + + +### Fork and download android repository: +* Please follow [SETUP.md](/SETUP.md) to setup Nextcloud Talk Android app work environment. + + +### Create pull request: +* Commit your changes locally: ```git commit -a``` +* Push your changes to your GitHub repo: ```git push``` +* Browse to and issue pull request +* Enter description and send pull request. + + +### Create another pull request: +To make sure your new pull request does not contain commits which are already contained in previous PRs, create a new branch which is a clone of upstream/master. + +* ```git fetch upstream``` +* ```git checkout -b my_new_master_branch upstream/master``` +* If you want to rename that branch later: ```git checkout -b my_new_master_branch_with_new_name``` +* Push branch to server: ```git push -u origin name_of_local_master_branch``` +* Use GitHub to issue PR + + +### Backport pull request: +Use backport-bot via "/backport to stable-version", e.g. "/backport to stable-11.2". +This will automatically add "backport-request" label to PR and bot will create a new PR to targeted branch once the base PR is merged. +If automatic backport fails, it will create a comment. + + +### Adding new files +If you create a new file it needs to contain a license header. We encourage you to use the same license (GPL3+) as we do. +Copyright of Nextcloud GmbH is optional. + + +Source code of app: +```java/kotlin +/* + * Nextcloud Talk application + * + * @author Your Name + * Copyright (C) 2021 Your Name + * Copyright (C) 2021 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + ``` + + XML (layout) file: + ```xml + +``` + + +## File naming + +The file naming patterns are inspired and based on [Ribot's Android Project And Code Guidelines](https://github.com/ribot/android-guidelines/blob/c1d8c9c904eb31bf01fe24aadb963b74281fe79a/project_and_code_guidelines.md). + + +### Menu files + +Similar to layout files, menu files should match the name of the component. For example, if we are defining a menu file that is going to be used in the `UserProfileActivity`, then the name of the file should be `activity_user_profile.xml`. Same pattern applies for menus used in adapter view items, dialogs, etc. + +| Component | Class Name | Menu Name | +| ---------------- | ---------------------- | ----------------------------- | +| Activity | `UserProfileActivity` | `activity_user_profile.xml` | +| Fragment | `SignUpFragment` | `fragment_sign_up.xml` | +| Dialog | `ChangePasswordDialog` | `dialog_change_password.xml` | +| AdapterView item | --- | `item_person.xml` | +| Partial layout | --- | `partial_stats_bar.xml` | + +A good practice is to not include the word `menu` as part of the name because these files are already located in the `menu` directory. In case a component uses several menus in different places (via popup menus) then the resource name would be extended. For example, if the user profile activity has two popup menus for configuring the users settings and one for the handling group assignments then the file names for the menus would be: `activity_user_profile_user_settings.xml` and `activity_user_profile_group_assignments.xml`. + + +## Translations + +We manage translations via [Transifex](https://www.transifex.com/nextcloud/nextcloud/talk-android/). So just request joining the translation team for Android on the site and start translating. All translations will then be automatically pushed to this repository, there is no need for any pull request for translations. + +When submitting PRs with changed translations, please only submit changes to values/strings.xml and not changes to translated files. These will be overwritten by the next merge of transifex-but and would increase PR review efforts. + + +## Engineering practices + +This section contains some general guidelines for new contributors, based on common issues flagged during code review. + + +### Approach to technical debt + +TL;DR Non-Stop Litter Picking Party! + +We recognize the importance of technical debt that can slow down development, make bug fixing difficult and +discourage future contributors. + +We are mindful of the [Broken Windows Theory](https://en.wikipedia.org/wiki/Broken_windows_theory) and we'd like to +actively promote and encourage contributors to apply The Scout's Rule: *"Always leave the campground cleaner than +you found it"*. Simple, little improvements will sum up and will be very appreciated by Nextcloud team. + +We also promise to actively support and mentor contributors that help us to improve code quality, as we understand +that this process is challenging and requires deep understanding of the application codebase. + + +### Dependency injection + +TL;DR Avoid calling constructors inside constructors. + +In effort to modernize the codebase we are applying [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) +whenever possible. We use 2 approaches: automatic and manual. + +We are using [Dagger 2](https://dagger.dev/) to inject dependencies into major Android components only: + + * `Activity` + * `Fragment` + * `Controller` + * `Service` + * `BroadcastReceiver` + * `ContentProvider` + +This process is fairly automatic, with `@Inject` annotation being sufficient to supply properly initialized +objects. Android lifecycle callbacks allow us to do most of the work without effort. + +For other application sub-components we prefer to use constructor injection and manually provide required dependencies. + +This combination allows us to benefit from automation when it provides most value, does not tie the rest of the code +to any specific framework and stimulates continuous code modernization through iterative refactoring of all minor +elements. + + +### Testing + +TL;DR If we can't write a test for it, it's not good. + +Test automation is challenging in mobile applications in general. We try to improve in this area +and thereof we'd ask contributors to be mindful of their code testability: + +1. new code submitted to Nextcloud project should be provided with automatic tests +2. contributions to existing code that is currently not covered by automatic tests + should at least not make future efforts more challenging +3. whenever possible, testability should be improved even if the code is not covered by tests + + +# Releases +At the moment we are releasing the app in two app stores: + +* [Google Play Store](https://play.google.com/store/apps/details?id=com.nextcloud.talk2) +* [f-droid](https://f-droid.org/en/packages/com.nextcloud.talk2/) + + +## Types +We do differentiate between three different kinds of releases: + + +### Stable +Play store and f-droid releases for the masses. +Pull Requests that have been tested and reviewed can go to master. After the last alpha release is out in the wild and no mayor errors get reported (by users or in the developer console) the master branch is ready for the stable release phase. +So when we decide to go for a new release we freeze the master feature wise and a stable branch will be created. + +### Release Candidate +_stable beta_ releases done via the Beta program of the Google Play store. +Whenever a PR is reviewed/approved we put it on master. +Before releasing a new stable version there is at least one release candidate. It is based on the current stable-branch. After a beta testing phase a stable version will be released, which is identical to the latest release candidate. + + +### Alpha Release +_alpha_ releases done via the Alpha program of the Google Play store. +Whenever a PR is reviewed/approved we put it on master. +Alpha releases are based on latest master and and we aim to release a new alpha version on a weekly basis. + + +### QA Release +Done as a standalone app that can be installed in parallel to the stable app. +Any PR gets a QA build so users and reporters are able to easily test a change (feature or bugfix. + + +## Version Name and number +### Stable / Release candidate +For _stable_ and _release candidate_ the version name follows the [semantic versioning schema](http://semver.org/) and the version number has several digits reserved to parts of the versioning schema inspired by the [jayway version numbering](https://www.jayway.com/2015/03/11/automatic-versioncode-generation-in-android-gradle/), where: + +* 2 digits for beta/alpha code as in release candidates starting at '01' (1-50=Alpha / 51-89=RC / 90-99=stable) +* 2 digits for hot fix code +* 3 digits for minor version code +* n digits for mayor version code + +![Version code schema](/docs/semantic_versioning_code.png "Semantic versioning code") + +Examples for different versions: +* 1.0.0 ```10000099``` +* 8.12.2 ```80120290``` +* 9.8.4-Alpha18 ```90080418``` +* 11.2.0-rc1 ```110020051``` + +beware, that beta releases for an upcoming version will always use the minor and hotfix version of the release they are targeting. So to make sure the version code of the upcoming stable release will always be higher stable releases set the 2 beta digits to '90'-'99' as seen above in the examples. For major versions, as we're not a library and thus 'incompatible API changes' is not something that happens, decisions are essentially marketing-based. If we deem a release to be very impactful, we might increase the major version number. + + +## Release cycle +* Releases are planned every ~2 months, with 6 weeks of developing and 2 weeks of stabilising +* after feature freeze a public release candidate on play store and f-droid is released +* ~2 weeks testing, bug fixing +* release final version on f-droid and play store +* Bugfix releases (dot releases, e.g. 3.2.1) are released 4 weeks after stable version from the branch created with first stable release (stable-3.2). + +Hotfixes as well as security fixes are released via bugfix releases (dot releases) but are released on demand in contrast to regular, scheduled bugfix releases. + +To get an idea which PRs and issues will be part of the next release simply check our [milestone plan](https://github.com/nextcloud/talk-android/milestones) + +## Release process + + +### Stable Release +Stable releases are based on the git [stable-*](https://github.com/nextcloud/talk-android). + +1. Bump the version name and version code in the [/app/build.gradle](https://github.com/nextcloud/talk-android/blob/master/app/build.gradle), see chapter 'Version Name and number'. +2. Create a [release/tag](https://github.com/nextcloud/talk-android/releases) in git. Tag name following the naming schema: ```stable-Mayor.Minor.Hotfix``` (e.g. stable-1.2.0) naming the version number following the [semantic versioning schema](http://semver.org/) + + +### Release Candidate Release +Release Candidate releases are based on the git [stable-*](https://github.com/nextcloud/talk-android) and are before publishing stable releases. + +1. Bump the version name and version code in the [/app/build.gradle](https://github.com/nextcloud/talk-android/blob/master/app/build.gradle), see below the version name and code concept. +2. Create a [release/tag](https://github.com/nextcloud/talk-android/releases) in git. Tag name following the naming schema: ```rc-Mayor.Minor.Hotfix-betaIncrement``` (e.g. rc-1.2.0-12) naming the version number following the [semantic versioning schema](http://semver.org/) + + +### Alpha Release +Release Candidate releases are based on the git [master](https://github.com/nextcloud/talk-android) and are done between stable releases. + +1. Bump the version name and version code in the [/app/build.gradle](https://github.com/nextcloud/talk-android/blob/master/app/build.gradle), see below the version name and code concept. +2. Create a [release/tag](https://github.com/nextcloud/talk-android/releases) in git. Tag name following the naming schema: ```rc-Mayor.Minor.Hotfix-betaIncrement``` (e.g. rc-1.2.0-12) naming the version number following the [semantic versioning schema](http://semver.org/) diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 000000000..95f22ec7e --- /dev/null +++ b/SETUP.md @@ -0,0 +1,102 @@ +These instructions will help you to set up your development environment, get the source code of the Nextcloud Talk for Android app and build it by yourself. If you want to help developing the app take a look to the [contribution guidelines][0]. + +Sections 1) and 2) are common for any environment. The rest of the sections describe how to set up a project in different tool environments. Nowadays we recommend to use Android Studio (section 2), but you can also build the app from the command line (section 3). + +If you have any problem, remove the 'talk-android' folder, start again from 1) and work your way down. If something still does not work as described here, please open a new issue describing exactly what you did, what happened, and what should have happened. + + +### 0. Common software dependencies. + +There are some tools needed, no matter what is your specific IDE or build tool of preference. + +[git][1] is used to access to the different versions of the Nextcloud's source code. Download and install the version appropriate for your operating system from [here][2]. Add the full path to the 'bin/' directory from your git installation into the PATH variable of your environment so that it can be used from any location. + +[Android Studio][5] is currently the official Android IDE. Due to this, we recommend it as the IDE to use in your development environment. Follow the installation instructions [here][6]. + +We recommend to use the last version available in the stable channel of Android Studio updates. + +The Android SDK is necessary to build the app. Install it via Android Studio itself: + +```Settings``` → ```Appearance & Behavior``` → ```System Settings``` → ```Android SDK``` + +After installing it, add the full path to the directories 'tools/' and 'platform-tools/' from your Android SDK installation into the PATH variable of your environment. + +Open the Android SDK Manager under Android Studio's settings + +```Settings``` → ```Appearance & Behavior``` → ```System Settings``` → ```Android SDK``` + +To build the Nextcloud for Android app you will need to install at least the next SDK packages: + +* Android SDK Tools and Android SDK Platform-Tools (already installed); upgrade to their last versions is usually a good idea. +* Android SDK Build-Tools 30.0.3. +* Android 11 (API 29), SDK Platform; needed to build the nextcloud app. + +Install any other package you consider interesting, such as emulators. + +After installing it, add the full path to the directories 'tools/' and 'platform-tools/' from your Android SDK installation into the PATH variable of your environment. + + +### 1. Fork and download the nextcloud/android repository. + +You will need [git][1] to access to the different versions of the Nextcloud's source code. The source code is hosted on GitHub and may be read by anybody, without a GitHub account. You will need one if you want to contribute to the development of the app with your own code. + +The next steps will assume you have a GitHub account and that you will get the code from your own fork. + +* In a web browser, go to https://github.com/nextcloud/talk-android, and click the 'Fork' button near the top right corner. +* Open a terminal and go on with the next steps in it. +* Clone your forked repository: ```git clone --recursive https://github.com/YOURGITHUBNAME/talk-android.git```. +* Move to the project folder with ```cd talk-android```. +* Pull any changes from your remote branch 'master': ```git pull origin master``` +* Make official Nextcloud repo known as upstream: ```git remote add upstream https://github.com/nextcloud/talk-android.git``` +* Make sure to get the latest changes from official talk-android/master branch: ```git pull upstream master``` + +At this point you can continue using different tools to build the project. Section 2 and 3 describe the existing alternatives. + + +### 2. Working with Android Studio. + +To set up the project in Android Studio follow the next steps: + +* Open Android Studio and select 'Open an Existing Project'. Browse through your file system to the folder 'talk-android' where the project is located. The file chooser will show an Android face as the folder icon, which you can select to reopen the project. +* Android Studio will try to build the project directly after importing it. To build it manually, just click the 'Play' button in the toolbar to build and run it in a mobile device or an emulator. The resulting APK file will be saved in the 'app/build/outputs/apk/' subdirectory in the project folder and being installed/launched in a configured emulator or if connected your physical device. +* Check Android Studio editor configuration for the project: ```Settings``` → ```Editor``` → ```Code Style``` → ```Scheme: Project``` and ```Enable EditorConfig support``` (should be enabled by default) + + +### 3. Working in a terminal with Gradle: + +[Gradle][7] is the build system used by Android Studio to manage the building operations on Android apps. You do not need to install Gradle in your system, and Google recommends not to do it, but instead trusting on the [Gradle wrapper][8] included in the project. + +* Open a terminal and go to the 'talk-android' directory that contains the repository. +* Run the 'clean' and 'build' tasks using the Gradle wrapper provided + - Windows: ```gradlew.bat clean assembleGplay``` or ```gradlew.bat clean assembleGeneric``` + - Mac OS/Linux: ```./gradlew clean assembleGplay``` or ```./gradlew clean assembleGeneric``` + +The first time the Gradle wrapper is called, the correct Gradle version will be downloaded automatically. This requires a working Internet connection. + +The generated APK file is saved in app/build/outputs/apk as app-generic-debug.apk + + +### 4. App flavours + +The app is currently equipped to be built with three flavours: +* Generic - the regular build, released as Nextcloud Android app on F-Droid +* Gplay - with Google Stuff (Push notification), used for Google Play Store +* Qa - Build per pr for testing + +[0]: https://github.com/nextcloud/talk-android/blob/master/CONTRIBUTING.md +[1]: https://git-scm.com/ +[2]: https://git-scm.com/downloads +[5]: https://developer.android.com/studio +[6]: https://developer.android.com/studio/install +[7]: https://gradle.org/ +[8]: https://docs.gradle.org/current/userguide/gradle_wrapper.html + + +### 5. Troubleshooting + + +#### 1. Compilation fails with "java.lang.OutOfMemoryError: Java heap space" error +The default settings for Gradle is to limit the compilation to 1GB of heap. +You can increase that value by : +- adding `org.gradle.jvmargs=-Xmx4G` to `gradle.properties` +- running gradlew(.bat) with this command line : `GRADLE_OPTS="-Xmx4G" ./gradlew clean build" diff --git a/docs/branching.png b/docs/branching.png new file mode 100644 index 0000000000000000000000000000000000000000..1b5605509dcfefcc1f6b9febe085ed81eca82b3d GIT binary patch literal 22626 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%0D^%g0SW_NYE((|+N|$8{rdX) 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/semantic_versioning_code.png b/docs/semantic_versioning_code.png new file mode 100644 index 0000000000000000000000000000000000000000..a96bccdeec34505c434ec3d72de788fc81fb9bbe GIT binary patch literal 5433 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