Are you developing a hotfix?
Are you developing a feature?
- Create a
feature/<domain>/<name>
branch - Make awesome stuff
- Push final code to your branch
- Go to github and create a pull request (PR) into the
develop
branch
We keep three separate notions of branches:
- The deployment branches master and develop
- The hotfix and release branch
- Feature branches
All commits should be pushed to either the hotfix branch, or a feature branch, and then PRed into the develop branch.
The develop branch contains the latest deployed test version of the system, and will automatically re-deploy.
The master branch contains the production stable release of the system, and should not be touched by anything but final releases. The master branch will not automatically re-deploy.
The release branch should be used before merging into master. The features will be frozen, i.e. new featuers into develop will not be merged into the release branch for this release.
The hotfix branch should be used when pushing commits that fixes critical bugs. After pushing, a PR into develop (and then master) should be made.
Check out this guide on how to create a new PR on github. Our policy on PRs is that you should let someone else than yourself confirm it. The purpose is to ensure the code is reviewed before it disappears into the system.
There are no ubiquitous rules here, but we follow the following patterns:
- Has develop or the feature branch you're working on changed while you've made new commits which aren't yet pushed? Rebase.
- Has develop or the feature branch you're working on changed, but you haven't done anything? fast-forward merge (
merge --ff-only
). - Most other cases: merge without fast-forward (
merge --no-ff
).
All feature branches must be prefixed with feature/
, e.g. feature/upgrade-database
. Feature branches should contain at least two levels of nested information; the first signifying in which domain the change/addition is being made, and the second what the change/adition is. Examples:
feature/database/add-optimization-indices
feature/user/homepage
feature/economy/innskudd
feature/frontend/update-landingpage
Note that if you have the base branch locally, e.g. feature/economy
, you cannot name a new branch feature/economy/something
. In that scenario you should name it feature/economy_something
.
Updates which are too broad to fall within one particular domain can avoid such nesting, e.g:
feature/security
feature/general-code-cleanup
Features that are large should have nested feature branches. Say we are developing a new large module called cryptonite
, which will require tens if not hundred of commits to finish. A sensible way to structure the development of this module would be to have one branch feature/cryptonite
, in which PRs with incremental development are being made. For example:
feature/cryptonite
|-- feature/cryptonite_add-superman
|-- feature/cryptonite_remove-lex-luthor
|-- feature/cryptonite_optimize
When all sub-branches are merged into the main feature branch, a PR can be made into develop.
Feature branches may be deleted after merging. Later updates/fixes/additions to the feature may be put in the same branch later on.
Hotfixes should be pushed directly to the hotfix branch. Hotfixes should be tested thoroughly locally before being pushed.
After pushing a commit, do the following: 1. Create a PR into develop. 2. When the PR is accepted, test the deployed fixes on the test-system. 3. Create a PR to master.
The develop branch is automatically deployed to when a CI-passing commit is pushed to it. Thus one should refrain from pushing anything directly to this branch, but rather create a PR from a feature branch.
When a new deployment to master is to be made, the following must occur:
- develop is merged into release
- A PR is created from release into master
- Code should be reviewed, and bugs should be fixed.
- Merge into master, and merge bug fixes back into develop
There are some general requirements to the code.
- For python we use pep8. With the exceptions listed here, it should be followed slavishly.
- For javascript, follow the included eslintrc file in the repository.
- We aim for having roughly 80% test coverage. This means that any new feature should be submitted with the appropriate amount of testing. Even so-called trivial code should be tested.
- Everything should be documented. Specifically, every method and class should have a docstring associated with it. We use the reST docstring format(this is the one Pycharm uses by default). Also, every non-trivial line of code should contain a preceding comment clarifying what the line does.
Commits should generally speaking be as atomic as possible. We favor many commits over few. Some recommend squashing feature branches into a single commit before merging. We do not do this.
If your style of development is to program continuously without committing until your desired feature works, you are recommended to install a visual tool for staging partial files. Pycharm has this included, as well as Visual Studio Code (Recommended). You can also use the CLI to do this. You can then break up your changes into single atomic commits. You may also in such a scenario considering squashing your commits.
A commit should generally speaking only touch the domain in which the feature branch is specified. If you come across a shortcoming in a feature you depend on, it must be adressed in a separate branch and merged before continuing.
Commit messages must contain a subject title. The title should be structured as follows:
<verb in baseform> <file, files, or module affected> <short description>
The subject title should be no more than 75 characters.
The commit should contain a description of the commit. The description should give some clear indications as to what the commit does, and how it does it. If the commit fixes a bug, the description must contain information pointing either to a bug report on github, or a description of why the bug occured. It should also contain information regarding how the bug has been fixed. This is not required if the fix is obvious.
Examples:
Add economy/util.py
Added a utility file for the economy module. Populated the file with a single
method 'sendAllMyMoneyToTormod'.
Update frontend/login.py, fixes issue #24
The login_user method did previously not take into account authorization through
the HTTP_AUTHORIZATION header, making all secret-key logins not work.
Add groups module
Initialized the groups module.
Fix bug in economy.utils.sendTransaction
The bug occured due to a failure to take into account a potential change of currency.
Examples of (very) bad commit messages:
Fix stuff
Whops forgot to commit a file
A lot of different changes
More small changes
Every change in a model will generate a new migration file, when python manage.py makemigrations
is run. The model-change with the migration should be commited together in a single atomic commit.
For every new feature implemented, at least one automated test utilizing this feature should be included as well. How many tests that are needed per feature is a highly subjective question, and is hard to generalize about.
Most tests should aim for testing that the feature is working as intended. Feel free to write tests that intentionally fail, as long as they do not complement other tests.
If fixing a bug, a regression test should be made. It is critical to ensure that this test fails before your bug fix, and then passes after your changes have been implemented.
Writing tests should follow this naming convention: test_PART_TO_TEST__INITIAL_STATE_OR_INPUTS__EXPECTED_OUTCOME
Example of a good test name:
test_add_commission_to_user__existing_commission__status_ok
Example of a bad test name:
test_add_commission
Do not be afraid to include all relevant info in the test names themselves. Long test names are encouraged when testing complex issues.
We use Travis for continuous integration.
We use semantic versioning for versioning the system. We use the following rules for incrementing the system version:
- Everytime a new module is merged, we increase the MINOR version.
- Everytime one or more modules receives an improvement in form of more functionality, we increase the MINOR version.
- Everytime a module receives a minor change or bug fix, we increase the PATCH version.
- (If we ever get this far) API-breaking changes or complete restructuring of the app will increase the MAJOR version.
The official release of the web page will be version 1.0.0.
Stuck on something or just don't know where to start? Here are some helpful tutorials:
- Writing your first django app (learning-by-doing django tutorial)
- The simple way to understand Django models