MS Release Management and Release Paths - continuous-integration

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.

Related

General question on semantic versioning releases using CI / CD pipeline

I have yet to find clear guidance on semantically versioning software releases using Azure DevOps (Server) CI/CD.
My basic understanding is that I would set up a CI pipeline for our team so that we get the benefits of build failure notifications, test execution, code coverage, static code analysis and even more goodies.
The CD pipeline picks up on the CI pipeline, rolling out the artifacts on the different environments upon their completion.
Using this approach seems to not make sense to me. What about builds that fail because a dev didn't pay attention or that the team wants to discard? Such builds won't find their way into production but might use up version numbers, leading to gaps in our versioning scheme.
What is your experience or approach for semantically versioning software releases using CI/CD pipelines? Do you cherry-pick builds? Do you have a separate build pipeline for building releases?
Builds that fail don't get deployed. For builds that succeed but fail QA or integration testing when deployed to lower environments, you can put approval gates so that someone has to approve the release before it proceeds to higher environments.
If you build version 1.0.1 of your application and deploy it to dev and it's no good, that doesn't mean that version 1.0.1 doesn't exist. It exists. It was comprised of specific code assets. It was bad, and your users will never see it, but that's fine. If the users see version 1.0.1 jump to 1.0.94, why does it matter?

Pull request communication strategy needed

Doing trunk based development to achieve continuous deployment. And this is our branching strategy.
master > whats live in production
release > test passed and release point created by CI server
dev > daily merges from the development team.
If we consider doing the pull request from release to master stage.
What are the pros and cons to that approach? How can we communicate this with the development team where they want to do PR at dev branch?
I don't really have an answer, but think the context of the question is worth further discussion.
If you're doing Continuous Deployment, then I'm not sure of the purpose of the Release branch. It seems to be duplicating the purpose of either:
'master': code being deployed/released
'develop' integrated feature
branches, but not ready release
Or, are you using it to group milestones or planned major releases (i.e. Release/1.0, Release/2.0), like a mini-master branch.
I would not consider this Continuous Delivery (deployment, maybe), but it is certainly a valid pattern if your project requires staged releases rather than Continuous Delivery.
It's also important to also consider your CI setup and how it integrates with your branches. It isn't source code that is deployed to Production, but the build artifacts from your CI system. Thinking about this might simplify your branching model.
If you want to rollback, you don't want to rebuild the application from source, you want to re-deploy the pre-built artifacts of the previous version. Likewise, if you have a build that has passed all your tests and is ready to ship - hopefully is already running on your pre-production environments - you don't want to merge it to a different branch, rebuild it and then deploy the new build - you use the build that was tested.
The next consideration is that every additional branch adds time & complexity for the developers. Merging, pull requests, waiting for CI to run, etc. are not free so reducing the complexity of the branching strategy to the minimum you require is a good goal.
To answer your question about where to PR to/from, do you consider "Develop" as the mainline and attempt to keep it stable and working at all times?
If so, then the PRs from feature-to-develop are the key integration. Develop is then built, tested, and deployed to your test environments.
Branching from develop at that point (i.e. to create a Release branch) is then known to be good.
Promoting that artifact from your test environment to production, without re-building, might remove the need for one of your branches.

Octopus - multiple phase paths in the same lifecycle?

Is there a way to set up an Octopus lifecycle with options like this:
You can deploy to DEV, but you can't promote the build from DEV
You can deploy to QA and then promote to PROD
Have you looked into channels?
From documentation:
Which Lifecycle to use for promoting Releases: for example, feature releases may be promoted through the testing environments, while hot-fix releases may go directly to production.
I think you can create two different projects one for deployment in Dev environment and another for QA-Prod. In our octopus setup we have two branches in TFS- Dev and main branch. A code check in into dev branch does an automatic CI release deployment into INt environment. When developers do merge from dev to main branch , an automatic release gets deployed to qa which can be later promoted to prod. Of course another way can be Channel which Alex suggested.

TeamCity best practice setup for multiple branches

I'm looking for advice on the best approach to setup TeamCity/Octopus.
Currently I have multiple branches in TFS2015 - dev, main and release (currently we create a release branch for each release).
Our procedure is to develop in dev and deploy to dev environment. When we are ready for testing we merge from dev to main and deploy to test from main. When happy we create a release branch and deploy to live from the release branch. This is a manual process.
Hotfixes are done on the release branch and deployed to live. We then merge back to main/dev.
I'm totally new to this and so far in a VM playground I've setup TFS2015, TeamCity and Octopus and can check-in to TFS, build/create package on TeamCity and deploy this pack from Octopus. But...
I'm unsure how I should setup TeamCity and Octopus to work with multiple branches? Multiple projects for each branch and generate different artifacts?
When I do this for real I have a TFS VM, I plan on installing TeamCity and Octopus on this along with the build agent. Is this a bad idea? Should I create a new VM just for TM and Octopus?
Any advice or best practice would be appreciated.
Although your question is good in scope, but a good answer must cover many details to be complete.
Let me try to point out the main areas that you will need to further investigate and configure.
TeamCity
A VCS root can be configured to listen to multiple branches via a branch specification
A VCS root can contain multiple projects/solutions and these can be built in multiple steps within TeamCity.
Given that Team City does not support conditional build steps, you will need a different strategy to allow you to vary build steps (and parameters) per release channels / environments.
My recommend approach is to split up the builds into a build definition per release channel (target environment).
Dev and Feature branches could share a single build definition.
Master and Hotfix branches can share a single build definition since they both publish to staging/production environments.
Release branches will need a separate build definition and publish to QA/Testing environment.
This gives you fine grained control over parameter and configurations of each release channel. build a debug version of your app from Dev branch for example at major version 3, while build a release version from Master branch with major version 2.
Every build definition will have a step to publish its artefacts/packages to Octopus Deploy, and specify the channel of which the artifacts belong to.
Octopus Deploy
In Octopus Deploy, define the channels to reflect the release channels, that also reflect your branching model.
Develop, Test, Release are my standard goto channels
Each channel can enforce a different Lifecycle to limit the environments that a channel can deploy to and how an application progresses through your overall ALM cycle.
I know this is not a complete answer. but it is a good start that I hope can help you refine your question to more specific technical details.
We're having somewhat similar CI setup requirements except TFS. In our case workflow for most projects is: GitHub -> TeamCity -> Octopus Deploy.
So I'm not sure about multi-branch setup with TFS, but in case with GitHub repos it's pretty easy to configure in TeamCity. You just have to specify branch-related settings in your VCS root (see Branch configuration). When you have configured that, TeamCity will let you run build's for every specified branch separately and will display build statuses for every branch nicely.
In Octopus we use Channels feature to split workflows of releases coming from different branches. That means we have channel-per-branch convention for the projects, so that TeamCity is pushing packaged releases from particular branch (in our case it's develop and master) into it's respective channel in Octopus (see Channels in Octopus).
Probably you can setup all the services on single machine but imho it's not the best practice to do performance-wise and scalability-wise.
Off course I don't know you code etc but I think you should step away from merging from dev to test and then creating a version from test. That way you essentially are building a different application compared to the one you were having on dev. Once you merge from test to production and build your application from there, you are releasing a build you haven't been testing.
You should strive for a flow in which you build once and deploy multiple times. So, build one package which you promote from dev to test to production.
Off course you can have a production branch on which you could fix bugs etc. The Channels feature in Octopus works great for scenario's like that.
So answering my own question (sorry), the approach I ended up taking was to simplify my branches and configure TeamCity/Octopus like so...
Branching Strategy
I've moved from
--dev
--main
--release
----release1
----release2
to
--master
--release
----release1
----release2
Master is where most of the devs do their work, when we are ready for a release we have a cut-off point and merge master into a new release branch.
The release branch is deployed to test and any fixes from testing are made on the release branch.
When testing is complete we deploy to live/production from this branch.
This means that the binaries we have tested are exactly the same as the ones we deploy to live/production.
Teamcity
In TeamCity master is automatically built each time a check-in occurs. Then the package is pushed to Octopus. Octopus acts as a repository in this case. TeamCity also creates the release on Octopus. So it should be checkin->build->create release->deploy.
To do this, I have one VCS Root and have a build configuration called Build-Master. This uses the checkout rules to ensure I'm only using the master branch. I use the Ocotpus packaging to build the package then use the OctopusDeploy runner in TeamCity to create a release automatically and deploy to the dev servers.
Release is different. I want to deploy to the test servers manually rather than each time a check-in occurs. When happy promote this to the live production servers.
Any fixes from test will be made to the release branch and deployed to test.
When testing is complete we promote to live and any hotfixes are made on the release branch. Obviously all fixes/hotfixes are merged down to master.
So, in TeamCity to achieve this I have a build configuration called Build-Release. Again, I use the checkout rules to ensure I'm dealing with the correct release branch.
The build creates a package using OctoPack, however this time it's not pushed to Octopus.
Octopus
Octopus has a project specifically for deploying master to our dev servers, for example projectnamehere-dev.
In Octopus, I have a separate project for Test/Prod. I've setup an external feed which points at TeamCity so I can pickup the package created in TeamCity. This is setup in Library->External Feeds.
So, to deploy to test. I create the release branch in TFS and give it a version number, 1,2,3 etc. I then change the Build-Release build config to point at this new branch. Change the version number.
Then in Octopus, I create a release, select this package and deploy to test. Any fixes from testing are made on this release branch. I just build the package again and create a new release and choose the new package.
When testing is complete, in Octopus I just promote the last release to the live production servers.
Channels in Octopus are used on the two projects because they have different life cycles. I also created two new life cycles, the default is dev/test/prod. I created just a dev and then test/prod.
Hope this helps.
In the version control settings -> vcs -> Branch Specifications: "*" ("This will do all branch, filter as needs be" e.g. +:refs/heads/master +:refs/heads/develop)
enter image description here
Octopus doesn't handle branches, it only deploys, you can however use their rest api, so for example, if test pass in develop then call the octopus rest api to create a new release and deploy.

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.

Resources