Follow a feature branching strategy.
For each contribution to the main branch just follow these steps:
- Create locally a branch off of
mainwith an appropriate prefix:feature/for a new functionality or even just an improvementfix/specifically for bug fixesdocs/to edit documentation only
- Commit and push to the corresponding Github branch, e.g.
/origin/feature/my-feature - Open a PR from your branch to
main - Once reviewed and approved, SQUASH AND MERGE the branch onto
main- squashing creates a single clean commit on
mainreducing the noise and making themainbranch much more readable in the long term
- squashing creates a single clean commit on
Standardizing our releases helps in the long term to have consistent version names and changelogs. This prevents people from reinventing the wheel for each project/repo.
Also we want to consistently hardcode the version number in each component in a way that can be accessible once deployed to make it easy to identify the running version. For example we want the python apps to show the version number in /health/details.
We follow the Semantic Versioning for releases. Therefore there are 3 types of release:
- A Major release when the major version number is bumped up
- e.g. 2.Y.Z -> 3.0.0
- A Minor release when the minor version number is bumped up
- e.g. X.3.Z -> X.4.0
- A Patch release when the patch version number is bumped up
- e.g. X.Y.4 -> X.Y.5
Only tags are deployed to the staging and production environments hence the importance of releases and proper versioning.
Even though the main branch works fine in QA, it is important
to go through the deployment of a tagged version of the code
onto a staging environment similar to production before making a major or minor release.
Just this process can reveal issues previously unseen in the QA environment.
This is the role of the release candidate or candidates.
- Make a Release Candidate (
rc) tag, e.g.1.1.0-rc1prior to the official release- Select "This is a pre-release" if you make a Github release (not required)
- Test the RC on the STG Environment
- If you find an issue, fix it and make another release candidate, e.g.
-rc2, to test the fix
- If you find an issue, fix it and make another release candidate, e.g.
- After verifying the latest
rcis good, make a release.
Note: No need for release candidates for patch releases. We can just bump to the next patch version if an issue is found in the current patch release being tested on staging.
Because making a release is preparing a deployment to production, it is best to follow a standard guaranteeing proper bookkeeping and review process.
The general steps ares:
- Follow a release branching strategy once
mainis ready for a major or minor release - Edit the code to hardcode the version number and get this reviewed
- Create a tag and a Github release
While releases are often straight forward with one tag, no patch version,
on the main branch and with just a couple of devs on the repo, things can get
dicey when one makes a release yet the development continues on main,
bugs are found, and hotfixes and patch releases are issued.
The release branching strategy isolate the code and changes of each major and minor release on top of tagging, preventing to have to figure out what changes happened on the release, and which one was for the next major version.
The basic idea is to create a branch called release/X.Y when you
want to release release/X.Y.0. This branch will follow the evolution
of the release from the release candidates labelled Y.X.Y-rcR but also
all the patch versions of X.Y.
See below for a visual example.
gitGraph
commit
commit
branch release/1.2
checkout release/1.2
branch release/1.2.0-rc1
checkout release/1.2.0-rc1
commit id: "Prepare version 1.2.0-rc1"
checkout release/1.2
merge release/1.2.0-rc1 tag: "1.2.0-rc1"
branch fix/minor-bug
checkout fix/minor-bug
commit id: "replace recieve with receive"
checkout release/1.2
merge fix/minor-bug
branch release/1.2.0-rc2
checkout release/1.2.0-rc2
commit id: "Prepare version 1.2.0-rc2"
checkout main
commit
commit
checkout release/1.2
merge release/1.2.0-rc2 tag: "1.2.0-rc2"
branch release/1.2.0
checkout main
commit
checkout release/1.2.0
commit id: "Prepare version 1.2.0"
checkout release/1.2
merge release/1.2.0 tag: "1.2.0"
checkout main
checkout main
commit
Making releases documents what exact version of the code is pushed live.
To understand the differences between versions it is important to have a
clear changelog and release notes.
Finally storing the version in the appropriate files in each project
can help identify the live version if the code is set to display this
hardcoded version somewhere. (e.g. python apps show it at /health/details)
- Create branch
release/X.Y.Zoff of therelease/X.Ybranch - Change the version in the version files of the projects in the repo
- Run
./set_version X.Y.Z - Or change the files manually:
- For python apps, edit
pyproject.tomland__version__.pyfiles - For themes, edit
/config/settings_schema.jsonand set thetheme_versionfield
- For python apps, edit
- Run
- Commit to git
- Open a PR for other codeowners to review
- Once approved, squash and merge
release/X.Y.Zontorelease/X.Y - Create the release in Github on the branch
release/X.Y- Generate the changelog using Github's automatically generated release notes
- Feel free to reorganize the changelog entries in sections, maybe by project, types of change, team (BE vs FE) or contributor. Up to you.
It depends.
The release/X.Y branch is to isolate code specific to this release and in particular the hardcoding of the version numbers.
So if your are patching a release 1.4.x while main is getting ready to deploy 2.0.0, then it's best to not merge.
However if the main branch is not under active development, then merging WITHOUT SQUASHING the release branch into main is fine.
See below to find out how to handle these two situations.
There are two options for two different use cases:
- If the
mainbranch is not active and the release branch andmainbranch haven't diverged much, or multiple releases are live, then use option 1. - If the
mainbranch has been under significant development and has diverged from the release branch, then use option 2.
In both cases you should go through a pull request because only reviewed commits should be pushed to main, even bug fixes already part of a patch version of a release.
This is rather simple and effective as long as you DO NOT SQUASH. Squashing is really a problem only if you add more patch releases to your release branch but since we do not know the future, never squash a release branch onto master and you'll be safe.
gitGraph
commit
commit
branch release/1.3 order: 2
checkout release/1.3
commit tag: "1.3.0-rc1"
checkout main
commit
checkout release/1.3
commit tag: "1.3.0"
branch release/1.3.1 order: 7
checkout release/1.3.1
commit id: "Prepare version 1.3.1"
checkout main
commit
checkout release/1.3
merge release/1.3.1 tag: "1.3.1"
checkout main
merge release/1.3 id: "DON'T SQUASH 2"
commit
This is more of a fancy approach but it's good to know about it in case multiple releases are live.
To achieve that you need to cherry-pick the commit or commits fixing
the bug or bugs from the release candidate onto a fix/ branch from main.
Then follow the standard review procedure and squash and merge these fixes
into main.
See how the bug fixes for the release 1.3.1 are brought over to main:
gitGraph
commit
commit
branch release/1.3 order: 2
checkout release/1.3
commit tag: "1.3.0-rc1"
checkout main
commit
checkout main
commit
checkout release/1.3
commit tag: "1.3.0"
branch fix/some-issues order: 6
checkout fix/some-issues
commit id: "Fix bug 1"
commit id: "Fix bug 2"
checkout release/1.3
merge fix/some-issues
checkout main
branch fix/port-bug-fixes order: 1
merge release/1.3 id: "Cherry pick bug fixes"
checkout main
merge fix/port-bug-fixes
checkout release/1.3
branch release/1.3.1 order: 7
checkout release/1.3.1
commit id: "Prepare version 1.3.1"
checkout release/1.3
merge release/1.3.1 tag: "1.3.1"
checkout main
commit
This can happen anytime, independently of releases, i.e. you may want to wait
for multiple bugs before porting to main or do it as soon as possible.