This branching strategy is a way to manage the development, testing, and deployment of software applications in a coordinated and organized manner. It is particularly well-suited for medium to large-sized applications that have multiple concurrent developers working on them. It can be implemented on any continuous integration and continuous deployment (CICD) platform and cloud provider. The strategy is also intended to work with any issue tracking system.
Our strategy proposes the following three stable environments to achieve a fully-automated CICD flow:
- develop: feature development environment.
- sit: integration and testing (manual or automated) environment.
- master: productive environment.
This allows for a clear separation of concerns, with the develop
environment serving as a sandbox for developers to
build and test new features, the sit
environment serving as a staging ground for integrating and testing those features
before they go live, and the master
environment representing the version of the software that is currently in production
and being used by end users.
In addition to these stable environments, the strategy also proposes the use of several temporal branches which will eventually be merged to their proper parent environment and their complete name should be given by the ticket number in the issue tracking system describing what needs to be achieved:
- feature/**: to develop new features branched off sit environment, which is less prone to bugs.
- bugfix/**: to fix bugs found on sit environment.
- hotfix/**: to fix bugs found on productive environment.
These temporal branches allow developers to focus on specific tasks and then merge their work back into the appropriate stable environment when they are finished.
Finally, the strategy suggests the use of an environment-less amd stable branch:
- release: for bundling features and fixes together before they are merged into
master
branch. Generates a new tag for each finished Sprint that includes all the new content from that Sprint.
Overall, this branching strategy provides a structured and organized approach for managing the development, testing, and deployment of software applications. It allows for a clear separation of concerns and encourages a focus on specific tasks, while also providing mechanisms for testing and integrating changes before they go live. By using this strategy, organizations can improve the quality and reliability of their software, and better meet the needs of their users.
Based on environment's branch interacting with, developers will have less permissions as they get closer to production.
-
Sprint's
feature/**
branches will be promoted to a testing environment in an isolated fashion as soon as their implementation is finished so tests can be executed properly.-
Once testing has finished successfully, a QA team member will merge the branch to
release
using a Pull-Request. -
When merged to
release
, those branches will reach end-of-life and will be deleted. -
Finally, they will be held at
release
creating a bundle and waiting to be promoted tomaster
branch via Pull-Request once Sprint's finished.
-
-
release
branch will be promoted tomaster
via Pull-Request when Sprint's over, creating a new semver tag.
As unrestricted as possible. Permissions for everybody. No need for reviewers. CommitHashId+Timestamp tagging.
Create a Pull-Request from temporal branch feature/**
against develop
branch to trigger its test pipeline.
On pipe failure fix errors/bugs and restart process. Merge won't be available.
On pipe success approve and merge Pull-Request without approval to speed-up integration process.
The merge will trigger develop
's deploy pipeline:
- On pipe failure, a rollback to the previous version (if any) will be automatically performed and the pipeline logs must be checked to discover what went wrong and solve it.
- On pipe success, new development version will be deployed to the environment.
develop
branch tagging will be automated.
A bit more restricted. Permissions for everybody. Only reviewers can approve a Pull-Request. Semver tagging.
Create a Pull-Request from temporal branch feature/**
against sit
branch to trigger its pipeline.
On pipe failure, fix error/bugs and restart process. Merge won't be available.
On pipe success, assign a reviewer and wait for the PR to be approved and merged.
.
Create a Pull-Request from temporal branch bugfix/**
against sit
branch to trigger its pipeline.
On pipe failure, fix error/bugs and restart process. Merge won't be available.
On pipe success, assign a reviewer and wait for the PR to be approved and merged.
- Downstream push of
bugfix/**
todevelop
branch will be automated and no pipe will be triggered.
.
Any merge will trigger sit
's deploy pipeline:
- On pipe failure, a rollback to the previous version (if any) will be automatically performed and pipe's logs must be checked to discover what went wrong and solve it.
- On pipe success, new testing version will be deployed to the environment.
sit
branch tagging will be automated.
Not an environment. It's a bundling branch used to create a release candidate per sprint.
As restrictive as possible. Permissions only for QA role. Semver tagging.
As soon as a feature's testing has been finished, QA member creates a Pull-Request from temporal branch feature/**
or bugfix/**
or hotfix/**
against release
branch to trigger it's unique testing pipeline.
On pipe failure, fix error/bugs and restart process. Merge won't be available.
On pipe success, assign a reviewer and wait for the PR to be approved and merged.
Any merge will trigger release
's tagging pipeline:
- A new release candidate tag following semver convention with the
-rc
suffix will be automatically generated.
As restrictive as possible. Permissions only for Team Leader or DevOps role. Semver tagging.
Create a Pull-Request from release candidate against master
branch to trigger its pipeline.
On pipe failure, fix error/bugs and restart process. Merge won't be available.
On pipe success, assign a reviewer and wait for the PR to be approved and merged.
.
Create a Pull-Request from temporal branch hotfix/**
against master
branch to trigger its pipeline.
On pipe failure, fix error/bugs and restart process. Merge won't be available.
On pipe success, assign a reviewer and wait for the PR to be approved and merged.
- Downstream push of
bugfix/**
torelease
branch will be automated and no pipe will be triggered. - Downstream push of
bugfix/**
tosit
branch will be automated and no pipe will be triggered. - Downstream push of
bugfix/**
todevelop
branch will be automated and no pipe will be triggered.
Any merge will trigger master
's deploy pipeline:
- On pipe failure, a rollback to the previous version (if any) will be automatically performed and pipe's logs must be checked to discover what went wrong and solve it.
- On pipe success, new testing version will be deployed to the environment.
master
branch semver tagging will be automated.
Below is a diagram of how this strategy would work in every different situation.
Pay attention on where branches reach end-of-life as well as to when is release
branch merged against master
.
-
All four stable branches -
develop
,sit
,release
&master
- will be protected against write access. -
The only way to modify these branches will be via Pull-Requests as explained above.
-
Pull-Requests against
develop
branch will be mergeable only when:- Pipeline's execution has been successful.
-
Pull-Requests against
sit
andmaster
branches will be mergeable only when:- Pipeline's execution been successful.
- Its proper reviewer has approved it.
If there's a merge conflict, follow this steps:
- Create a locally temporal branch, branched off the highest possible stable environment.
- Locally, merge to that new branch the content of the branch that generated the conflict.
- Push the branch with the solved conflict to the remote git repository.
- Open a new Pull-Request against same environment using the conflict-solver branch.
[0] - GitOps and GitFlow and GitHub Flow
[1] - GitOps
[2] - Gitflow
[3] - GitHub flow
[4] - Trunk-based development