If your issue appears to be a bug, and hasn't been reported, open a new issue.
Every bug should be triaged in approved/needs info in a given time.
Thanks for wanting to contribute source code to Nextcloud. That's great!
New contributions are added under GPL version 3+.
We are all about quality while not sacrificing speed so we use a very pragmatic workflow.
master
branchmaster
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
)Our formatter setup is rather simple:
Settings
→ Editor
→ Code Style
→ Right margin(columns)
: 120)Settings
→ Editor
→ Auto Import
→ Optimize imports on the fly
)There are three build variants
Nextcloud doesn't require a CLA (Contributor License Agreement). The copyright belongs to all the individual contributors. Therefore we recommend that every contributor adds following line to the header of a file, if they changed it substantially:
Copyright (c) <year> <your name> <your email address>
See section Adding new files for templates which can be used in new files.
We use the Developer Certificate of Origin (DCO) as a additional safeguard for the Nextcloud project. This is a well established and widely used mechanism to assure contributors have confirmed their right to license their contribution under the project's license. Please read [developer-certificate-of-origin][dcofile]. If you can certify it, then just add a line to every git commit message:
Signed-off-by: Random J Developer <random@developer.example.org>
Use your real name (sorry, no pseudonyms or anonymous contributions).
If you set your user.name
and user.email
git configs, you can sign your commit automatically with git commit -s
.
You can also use git aliases like git config --global alias.ci 'commit -s'
.
Now you can commit with git ci
and the commit will be signed.
We provide git hooks to make development process easier for both the developer and the reviewers. To install them, just run:
./gradlew installGitHooks
Contribute your code targeting/based-on the branch master
.
It will give us a better chance to test your code before merging it with stable code.
git commit -a
git push
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 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
/*
along with this program. If not, see http://www.gnu.org/licenses/. */
XML (layout) file:
xml
```
The file naming patterns are inspired and based on Ribot's Android Project And Code Guidelines.
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
.
We manage translations via Transifex. 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.
This section contains some general guidelines for new contributors, based on common issues flagged during code review.
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 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.
TL;DR Avoid calling constructors inside constructors.
In effort to modernize the codebase we are applying Dependency Injection whenever possible. We use 2 approaches: automatic and manual.
We are using Dagger 2 to inject dependencies into major Android components only:
Activity
Fragment
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.
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:
At the moment we are releasing the app in two app stores:
We do differentiate between three different kinds of releases:
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.
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 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.
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 the change (feature or bugfix).
For stable and release candidate the version name follows the semantic versioning schema and the version number has several digits reserved to parts of the versioning schema inspired by the jayway version numbering, where:
Examples for different versions:
version name|version code
---|---
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.
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
Stable releases are based on the git stable-*.
stable-Mayor.Minor.Hotfix
(e.g. stable-1.2.0) naming the version number following the semantic versioning schemaRelease Candidate releases are based on the git stable-* and are before publishing stable releases.
rc-Mayor.Minor.Hotfix-betaIncrement
(e.g. rc-1.2.0-12) naming the version number following the semantic versioning schemaRelease Candidate releases are based on the git master and are done between stable releases.
rc-Mayor.Minor.Hotfix-betaIncrement
(e.g. rc-1.2.0-12) naming the version number following the semantic versioning schema