The recommended approach is to leverage lifecycles and channels.
To start, we will need 5 environments listed in the question.
With those environments, we will create four lifecycles:
Before proceeding, let’s pause to discuss the use cases for each lifecycle
- Sprint Lifecycle: to be used during a sprint (or while work is being done for a release). Developer does a PR from a feature branch, it gets approved, and the build server deploys to Development. The majority of the time, the deployments only go to development.
- Test to Prod Lifecycle: to be used after a sprint when QA is verifying the code. A release branch is created. The build server sees that and deploys right to Test. Ideally the final build from this branch is pushed through all environments to Production.
- UAT to Prod Lifecycle: to be used when a release is held up in UAT. The build server will need a bit of smarts to see this release should go to UAT first and not to Test. If a release is held up in UAT it will need a path to production once all concerns are addressed.
- Hotfix Lifecycle: to be used when a production bug is found. When the code is checked in for the hotfix it should be deployed directly to staging to be verified prior to production.
Now that we have our lifecycles, we will need to create channels for each project following this branching strategy.
As an extra layer of protection, each channel will have version rules. Default is using the sprint lifecycle, and it has the latest and greatest code, so releases from the 2020.3.x release is allowed. QA only allows releases in the 2020.2.x releases. UAT only allows releases in 2020.1.x. Meanwhile production has 2019.12.x releases.
The version rules aren’t required. They are there to help prevent code from being deployed via the wrong channel. Having them does add a bit of complexity as you will have to update the version rules after each release branch is created.
The question now becomes, how does a build server know which channel select when creating the release? That will depend entirely on your business rules. What I would recommend is using the Octopus API to check the last release number for each environment. Here is an example on how to do that. Once you know the release number per environment you can infer which channel you need to deploy to.
If you would like to see this sample in action, please go to: https://samples.octopus.app/app#/Spaces-25 and sign in as a guest.