In my post yesterday I talked about how Azure DevOps and GitHub needn’t be an either/or decision. This was based on little more than having explored how to make the two work together. Today I’ve spent a whole day working with the two and have a couple more concrete things to say about the experience.
First, it really is as simple to connect the two systems together as I think it is possible for it to be. Once you have authenticated GitHub to Azure DevOps, you are good to go and the level of integration is both deep and subtle.
One of the first things I noticed was a new check mark against each commit in my GitHub repository commit history…
At first I wasn’t sure what this was until I realised the correlation between those check-marks and the state of my Azure DevOps build following each commit and push.
Not only is Azure DevOps aware of the commit and triggering the build, but it then calls back to GitHub to let it know the outcome of that build. Bear in mind that my build pipeline includes running tests so a “bad build” may not necessarily be a broken build in the sense of “does not compile” but may be that I’ve broken some tests.
The next thing I learned was that the Pull Request workflow in GitHub had some strange consequences for Azure DevOps build pipelines.
You may remember that I am using GitVersion to automatically derive a Semantic Version for my builds (and, consequently, releases). This was working smoothly for my Azure hosted repos and pipelines. Builds triggered on my develop branch were tagged with a beta pre-release tag and an incrementing build number (actually, a commit count). Then when I completed a pull request to master, my master build would be given the corresponding release version:
(develop) -> 1.0.0-beta.1 [2 commits] (develop) -> 1.0.0-beta.3 [5 commits] (develop) -> 1.0.0-beta.8 [PR to master] (master) -> 1.0.0
But with the repo hosted in GitHub and starting a PR from there, suddenly I started seeing a new build being triggered which was being tagged with a PullRequest label:
(develop) -> 1.0.0-beta.1 (develop) -> 1.0.0-beta.3 (develop) -> 1.0.0-beta.8 (2) -> 1.0.0-PullRequest.2
More perplexing still, the branch that this build (let’s call it the “PR build“) claimed to have been triggered on was not the master branch, nor develop, but simply “N”, where “N” seemed to correspond to the PR number in the repo (i.e. 1, 2, 3 etc).
Worse, since my PR’s were essentially nominal – assigned to me, reviewed by me and confirmed by me – they were quickly followed by the merge to master when the PR was completed. The build on the master branch that this triggered (let’s call this the “merge build“) for some reason was not queued behind the PR build but ran in parallel and was failing as a result.
Overnight it dawned on me that the explanation for this is that I have two build machines in my pool. On the free pricing tier of Azure DevOps only one parallel job is allowed, but I can have as many build agents as I like. The second job was being sent to my second build machine, but this was not setup for Delphi builds or GitVersion. I had forgotten to include the
demand to my build pipeline which would have stopped this from happening. Of course, if I also set that second machine up for Delphi builds as well it will double my build throughput capacity! [Yes, do that! – Ed]
The default GitVersion configuration is setup to add that PullRequest pre-release tag to PR builds, so that explained where the that was coming from. Fixing this was not my priority. My concern was to stop those PR builds in the first place! Or rather, to have them occur at an appropriate time. With the GitHub workflow, commits occurring as part of a PR are applied on the source branch which in my case was develop and this branch was already setup to trigger builds on any commit.
This is one issue I have with configuration as code. It’s great when you know all the things that can be configured in that plain ol’ text file in front of you, but there’s nothing there to help you identify what can be configured, other than documentation. This places you at the mercy of the documentation authors (often not the same people creating the software itself). If they are not great at making the product discoverable through the documentation then you haven’t got a hope or a prayer! Surely this is at least one reason that the GUI was invented in the first place ? To help guide and assist users through the business of getting value from software. But I digress.
Back to my build pipeline PR triggers. By default (i.e. if not otherwise specified) these are configured to trigger on every PR commit. So all I needed to do was change this (i.e. introduce some additional configuration) to only trigger on the branches that I expected to use for PR’s. Fortunately this was simple enough and simply required me to add a new section to my build pipeline, to supplement the existing triggers:
trigger: - develop* - feature* - master pr: branches: include: - develop* - feature*
This ensures that my builds are now only triggered by PR commits on develop and feature branches. The existing CI triggers take care of direct commits to all branches and merges to master.
Following that diversion I then started to notice another aspect of the integration between the two systems as it related to the PR workflow.
When creating a new PR in GitHub, part of the PR UI provides information on “checks” that are performed to validate the PR. Up to this point in GitHub those checks in my case had been confined to ensuring that the branches involved in the PR could be successfully merged and had no conflicts (with a conflict resolution UX if there were).
A new check now was appearing however:
The icon was the first clue as to what this was… the GitHub PR process had triggered a build and was now awaiting its outcome! Not only are build outcomes for each commit communicated between Azure DevOps and GitHub, but GitHub even knows when those builds are happening!
Incidentally, you don’t have to wait for the builds to complete nor does this check even have to pass for you to proceed with the PR, if you wish.
I am sure I will discover more integrations between Azure DevOps and GitHub as I continue my journey with these two.
Do you use GitHub ? Do you use it in conjunction with Azure DevOps ? What do you like about these two services, separately or combined ?
Let me know in the comments.