In Octopus Deploy, how to require an approval when a major or minor version is deployed to an environment the first time? - octopus-deploy

Imagine you had five environments, Dev, Test, UAT, Stage and Production.
For those environments you have the following lifecycles:
- Sprint: Dev -> Test
- Test To Prod: Test -> UAT -> Stage -> Prod
- UAT to Prod: UAT -> Stage -> Prod
- Hotfix: Stage -> Prod
The release versioning looks like 2020.1.3. When a new release is cut it will either update the major (2020) or minor (1) in the version number. For example 2020.1.3 goes to 2020.2.1 or 2021.1.1. A bug fix or minor release will update the last number (3).
The concern is if a release is deployed to Test, UAT or Stage at the wrong time or by accident and it stops our testers. For example, QA is in the middle of testing the 2020.1.3 release in Test. A developer accidentally pushes 2020.2 up to Test. That includes new code QA wasn't expecting. While QA is in the middle of testing 2020.1.x they only want to see 2020.1.x releases.
We don't want to use version rules in our channels. Each time a new release is cut the version rules would have to be updated.
Is it possible to require an approval when a major or minor version is deploy to an environment the first time?

Yes, that is possible. To do this, we will use output variables and run conditions.
First, two new steps were added to the start of the process.
Both steps skip development and production because they are not affected by this problem. Having to approve a deployment to dev every time a major/minor version changes will get old really fast. And all production releases must at least go to staging first.
The first step runs this PowerShell script. It will compare the previous release number for this specific environment with the current release number. It will set the output variable "RequiresApproval" to true if either the major or minor version is different.
$releaseNumber = $OctopusParameters["Octopus.Release.Number"]
$releaseNumberArray = $releaseNumber.Split('.')
$lastVersion = $OctopusParameters["Octopus.Release.PreviousForEnvironment.Number"]
$lastVersionArray = $lastVersion.Split('.')
Write-Highlight "The previous version deployed to this environment was $lastVersion"
$requiresApproval = $false
if ($lastVersionArray[0] -ne $releaseNumberArray[0])
{
Write-Highlight "The previous major version $($lastVersionArray[0]) in $lastVersion is different than the one being deployed $($releaseNumberArray[0]) in $releaseNumber, this requires someone to approve"
$requiresApproval = $true
}
elseif ($lastVersionArray[1] -ne $releaseNumberArray[1])
{
Write-Highlight "The previous minor version $($lastVersionArray[1]) in $lastVersion is different than the one being deployed $($releaseNumberArray[1]) in $releaseNumber, this requires someone to approve"
$requiresApproval = $true
}
else
{
Write-Highlight "The previous version's major and minor versions are the same, skipping approval"
}
Set-OctopusVariable -name "RequiresApproval" -value $requiresApproval
Output variables are a little verbose and can be tricky to use. To make that easier, create a project variable to reference it.
In the manual intervention step, set the run condition to that project variable.
Now it is time to test this. UAT currently has 2020.1.2 while Test has 2020.2.3. When 2020.2.4 is deployed to to Test the manual intervention shouldn't appear.
Success, the manual intervention is skipped.
UAT currently has 2020.1.2. 2020.2.4 has a new minor version, a deployment to UAT will prompt the user for a manual intervention.
This YouTube Video shows this in action.

Related

MS Release Management and Release Paths

I have started to dig in to Release Manager. Almost, if not all, examples I've seen uses a release path similar to Dev -> Test -> Production .
Say that I'm working with a web application and the organization is not using Continuous Integration in the real sense. Perhaps they are deploying to Dev many times per day, to Test a couple of times a week and to Production one time a month. (Dev and Test are then effectively different staging environments.)
So with a release path of Dev -> Test -> Production you will get a whole bunch of releases to Dev, but you don't want all Dev releases to go to Test. Therefore you would have to reject most of the releases until you are ready to deploy to Test.
What is the best practice here? Reject releases until you are ready to Test/Production? Create several Release Paths, such as:
Dev
Dev -> Test
Dev -> Test -> Production
...or something else?
In a happy DevOps/continuous delivery world, the way it works is like this:
You push bits to Dev as often as you want. The onus of picking a build to promote to QA is the developers' responsibility -- they should reject the releases they know won't be going anywhere. This is the post-deploy ("Validation") step in the Dev stage.
QA schedules the release to their environment (pre-deploy, "Approval"). They test, and give it their blessing (post-deploy, "Validation"). They reject any releases that fail QA.
Ops schedules the release to prod.
If this is an unlikely scenario because you know that none of your releases are production candidates up until a certain "blessed" build is created, then set your target stage for continuous delivery to "Dev" -- builds won't go beyond the dev environment. When you're ready to build something that's a QA and production candidate, build with a different target stage.

Release Management for Visual Studio - How pipeline works with DEV/QA/Production Branches?

We have separate TFS 2012 branches setup for each environment (DEV/QA/PROD).
Changes are checked-in to DEV branch which triggers a release via RM for Visual Studio 2013 Update 4 to the DEV server.
Current release template has Build Definition from DEV branch selected, but we need to switch to QA/PROD branches when moving to the next stage.
Do we need to create separate templates for each stage, instead of using a single template with all stages included?
RM was built on the idea of binary promotion instead of branching per stage. The idea is to have one set of binaries that you promote from one stage to the next. This makes the release process faster (no extraneous builds are happening) and decreases your QA time -- if you test the functionality of the code in QA, then rebuild for production, you're releasing untested binaries into production. It also helps with repeatability. If a release fails between QA and Prod with a branch-per-environment model, you potentially have extra answers to the question "Why did this work in one environment and not the other?". The only answer to that question should be "because there's a problem with the environment". It should never be "because we botched a merge".
You should reevaluate your branching strategy such that you build and release out of one branch, instead of relying on multiple builds out of multiple branches.
That said, your approach of creating separate release paths and templates for each branch would be the best way to tackle it if you can't mess with your branching strategy at the moment.
I usually do something like this, assuming DEV -> QA -> PROD:
Dev branch goes to a dev environment.
QA branch goes to a QA environment.
Prod branch goes to a QA environment, then to prod.
This lets developers continue working on new features while the previous release is being stabilized. If you take this approach, you'll pretty quickly realize that the QA branch is extraneous -- you build for release, then test the thing that you're intending to release.
Once you hit that point, it's a short path to realizing that it's best to keep dev branches short-lived, relying on frequent merges of new features from dev to trunk. Longer-running changes that aren't ready for public consumption can be isolated behind feature flags, so you can continue to roll out smaller changes that are feature-complete and tested while longer-running development work is still taking place.

In TFS is there an automatic way to increment the minor revision number when creating a new branch?

We'd like to increment the minor version of our application each time we create a new branch for release. So if, for example, the current version is 4.17 the next branch we create would automatically increment the version number to 4.18.
Our scheme is that the code follows the following path:
Dev -> Test -> Staging
so that the testing happens on code we think has the functionality required and only that code that passes testing is available for release.
Then when the time comes for a new release we take a new branch of Staging, so we have the following structure:
Staging
|----> Release 4.1
|----> Release 4.2
...
|----> Release 4.17
There is no cross pollination between the release branches.
So what we need is something that will increment the minor version number when a new branch is taken. We can reset the version number of the application in Dev/Test/Staging to anything that needed for this to work.
Is this possible with TFS/VS 2013 out of the box?
That is a bad smell!
You have to do that on one branch, and no in all... And not change the assembly number in a manual way...
The TFS Versioning could help you to do this.
In the community build tools you will find an activity called TFS Version. This tool can, in its default configuration, strip the version number from the build name. If you name your build for the branch to be mybuild_7.8.0$(.r) the tool can be configured to pick up that version and store it in a variable. You can then use that variable to update the AsemblyInfo.* file versions.
This is the correct way to do what you are asking. Do not check the changes in, and indeed set the checked in numbers to be 0.0.0.0. This way you will be able to identify when a cheeky developer has done a local push and when it came from a build server 😃
https://tfsbuildextensions.codeplex.com/wikipage?title=How%20to%20integrate%20the%20TfsVersion%20build%20activity&referringTitle=Documentation

composer and satis tags for testing and prod

We're using composer, satis and SVN to manage our in-house PHP libraries.
We commit changes to SVN trunk during development, then tag versions (following semantic versioning) when they're ready for testing.
Once a library version is tagged, we can use composer as part of our deployment to the testing environment. Following successful testing, we'd then deploy that same version to production.
The issue here, is that once we've tagged a version for testing, we have to be very careful as the newly tagged version will be picked up by composer when preparing the next prod release.
What I'm imagining, is that we'd tag a version as a beta or RC, (eg v1.1RC1) and somehow configure our deployment process such that it will refuse to deploy an RC or beta to production. If a version is tested successfully, we'd re-tag that version as a released version (v1.1RC1 -> v1.1) and release that.
Can this be achieved?
From what you are saying, I understand that you are actually afraid of tagging a new version of a library because that code could actually be used and break that other application, right?
One approach would be to do good testing. I don't see it should be a problem to tag a version of a library. If the tests are all green, there should be no reason not to tag it. This would work even if the tests are basically only "let's see if it works, manually".
Now the second step is to integrate that new version into the application: Run composer update and see if the application is still running, i.e. start all the tests and wait for green.
I guess it might be a good idea to have a separate area where you check out the application, intentionally run composer update to fetch all the newest libraries, run all the tests and report that a) there are updates and b) they work. A developer should then confirm the update, i.e. do it again manually and commit the resulting composer.lock file, or grab the resulting lock file from that update test.
I don't think there is benefit in using non-production release versions. You have to deal with the next version anyways - constantly toggling the minimum stability setting or adding #RC or #beta flags to the version requirements of the library don't really help.

How to stage a Maven release without creating scm tag?

Our current SDLC goes something like this:
Develop code & unit tests
Release to QA for system testing
Repeat steps 1 & 2 as required until QA is passed
Promote to UAT
Repeat steps 1 to 5 as required until UAT is passed
Deploy to production
We are using the maven-release-plugin to manage the releases, but want to maintain the same build number throughout the cycle. Currently each time we build, the artifact release version increases. e.g. 1.2.3 released to QA, fix errors and rebuild becomes 1.2.4, etc.
We have looked at using the release:stage goal, however the first use creates a tag in SCM, and each subsequent use of release:stage builds from this SCM tag, and does not include any code added after this tag is created. We've tried using release:rollback after release:stage to remove the scm tag, but this does not work.
Is there a way to perform this type of release cycle?
Thanks.
For our project, we uses snapshot for CI, beta for the step 1-5 cycle.

Resources