TeamCity Conditional Maven Releases - maven

I am pretty new to TeamCity and was hoping to get some best practice advice. We are using the Maven-Release plugin to do our releases and it works great, however we have a situation where we would like to have releases both off the trunk for test teams and then branch when we feel the codebase is stable enough for a proper release candidate. Ideally I'd like to have a single TeamCity release project, that by default will do a 'test release' off the trunk unless a build parameter is passed (e.g. project.release.type = branch) and then TeamCity will execute a different build configuration which will perform a mvn release:branch instead of a prepare.
Basically, can I conditionally execute TeamCity build configurations & how? Otherwise is there a suggested was to cater for the above scenario other than having multiple TeamCity release projects.
Cheers

Related

Using Maven for Trunk based development

I'm on a project that uses Mulesofts Anypoint studio for API development. Anypoint studio uses Maven to build its projects and handle versioning. Currently we are using a Git-flow branching model without release branches (feature/development/master) and the CI tool is Jenkins. We want to migrate to Azure-DevOps with Trunk-based branching.
The current git-flow CI set-up works as follows:
Merge feature with Dev
Jenkins triggers on Dev and builds a package with Maven
Jenkins deploys the package to D
Test your API on the D, if its good manually trigger Jenkins release pipeline
Jenkins will merge dev with master
Maven creates a release; creating a package (e.g. v0.1) and prepare the next development iteration (v0.2-SNAPSHOT) in master
Jenkins Deploys the package on A and P
Merge master back into Dev
So we have 2 separate pipelines here: dev and release. I'm hoping trunk-based development makes this process simpler by reducing it to one pipeline that is triggered by merges into master. But I don't know how to handle the versioning with Maven here.
This is what I have in mind for the Trunk-based (feature/master) pipeline:
Merge feature with Master
Azure pipelines triggers Maven release
(!) Maven takes the 0.1-SNAPSHOT version and creates a 0.1 release version and puts it..where? in a release branch?
Maven then creates the next working version 0.2-SNAPSHOT on the master branch
(!) this would trigger Azure pipelines again, creating a loop
Anyone have experience with Trunk Based development with Maven solve this? I would actually prefer to do it without a release branch because the released packages are already providing the release-branch functionality.
At first glance this answer seemingly solves my issue, but it just ignores the issue by going around it and just using a hash.

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.

Bamboo Selective Sonar Analysis

We are currently using Bamboo for our build tool and one of our stages contains a task to run Sonar analysis.
It works great except for the fact that results are published for both master and feature branches. Of course this means that if we build a branch then results will override the existing ones.
We have looked into Auto Branch in the Sonar task but we don't want a large number of branch projects in Sonar so this is a no-go for us.
How else can we selectively run Sonar analyses depending on the branch? I heard that using a property in our Maven pom.xml could work, I wonder if anyone has an example of that?
I add the -Dsonar.projectVersion=${bamboo.repository.branch.name} at runtime. That adds the branch as the project version.
I am using sonar-runner to execute the sonar analysis so since you're using maven, your mileage may vary - in other words convert that to whatever the maven version of that argument is.
So when I run the sonar-runner task I include that -D argument on the command line. Even running it with maven you should be able to pass it in on the command line. Whatever branch is building that's the one that will show up on the SonarQube dashboard.

Maven Mercurial based Continuous Release process

I want some "Maven with Mercurial release" knowledgeable opinion.
I already saw this thread and a few others.
We want to be agile and fast. We want to build once. Not one build for testing and one for release.
We have setup a continuous release process where we do the following:
Jenkins checks for SCM changes on "server" repository (every 30 minutes). Also can be triggered manually
Jenkins clones "server" repository
Jenkins increments version in pom (example: 1.0.1 -> 1.0.2). NO Snapshots
Start build, package, automatic deployments and tests
If all is good, commit changed pom, tag and push back to "server" repository (merge if needed)
Release good version to a "releases" system, where it's available for QA for further testing
Developers will pull back changes from "server" repository and get new versiond poms
If a hot fix is needed for a good release
A developer will clone the relevant tag from "server" repository
Do the fix, push back to a "server+fix" repository
Jenkins will build as before
If good, the fix will also be pushed to the main "server" repository
We found this process to be very quick and clean.
I want your opinion on the flow, with ideas to improve. Remember - Fast, Continuous and Build once.
Thanks in advance!
+1 to the no snapshots rule. I think its all good.
Release good version to a "releases" system, where it's available for
QA for further testing
What is the "releases" system. Is it a maven repository? Does a new build automatically get deployed to the QA environment? How does it pull from the respository? You could pull a jar from a maven repo using dependency:get. But if want to make use of infrastructure automation tools like Chef or Puppet for your deployment side, you'd be better off publishing rpms to your maven repository (publish using the maven-rpm-plugin and enable pulls with the nexus-yum-plugin for example) or simply setting up your own yum repository.

Personal build with dependencies

I've started using TeamCity personal builds, via the new Git remote run feature in TeamCity 6.5. Doing a single build works fine; I have a project that compiles from source, and I gave it a Branch Remote Run trigger.
However, it looks like TeamCity only triggers the one project that has the Branch Remote Run trigger applied. I have several unit test projects, set up in a chain with Finish Build triggers, and none of these get run. Furthermore, if I try to start a custom build of one of these unit test projects, I can't use the artifacts from my personal build: I can only pick artifacts from one of the 'official' builds.
Can I get TeamCity personal builds to work with build chains?
With the setup that you have (snapshot dependencies and finish build triggers), you can achieve build chaining by submitted your personal changes to the builds you are looking to trigger. For example, if you have projects A and B where B depends on A - run the remote build against project B and A will be triggered first and B will be added to the queue. Both of these builds will have your personal changes.
If you are using the TeamCity Visual Studio plugin you can select which builds you want to send your changes to and you just need to tick the box for B instead of A.
The finished build trigger won't be fired, but the build chaining means that A must be built first.
More info - http://confluence.jetbrains.net/display/TCD7/Build+Chain
(You have tagged TeamCity 6.5, but 7 has now been released so I have included the documentation for the newer version)
I suppose you should setup your chain not with Finish Build trigger, but with "Snapshot dependencies" feature of TeamCity. And, setup artifacts dependency basing on the snapshots.
Please read about snapshot dependencies in TeamCity here.

Resources