GitHub has an awesome feature that allows us to build on the potential merge result of a pull request.
This allows us to run unit and UI tests against the result of a merge, so we know with certainty that it works, before we merge the code.
To get this working with TeamCity is a pain in the ass though.
Lets look at a basic workflow with this:
First we will look at two active pull request, and we are about to merge
Pull request 2 advertises the /head (actual branch) and /merge (result “if we merged”)
TeamCity say you should tie your builds to the /merge for CI, this will build the merge result, and I agree.
However lets look at what happens in GitHub when we merge in Feature 1.
The new code goes into master, which will recalculate the merge result on Pull request 2. TeamCity correctly builds the merge reference and validates that the Pull Request will succeed.
However if we look in GitHub we will see the below
It now blocks you and prompts you to updates your branch.
After you click this, the /head and /merge refs will update, as it adds a commit to your branch and recalculates the merge result again, then you need wait for another build to validate the new commit on your branch.
This now triggers a second build.And when it completes you can merge.
The issues here is we are double building. There is two solutions as I see it,
- GitHub should allow you top merge without updating your branch
- TeamCity should allow you to trigger from one ref and build on a different one
I was able to implement the second result using a build configuration that calls the TeamCity API to trigger a build. However my preference would be number 1 as this is more automated.
Inside it looks like this
Below is example powershell that is used in the trigger build, we had an issue with the SSL cert (even though it wasn’t self signed) so had to disable the check for it to work.
add-type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy $buildBranch ="%teamcity.build.branch%" Write-Host $buildBranch $buildBranch = $buildBranch.Replace("/head","/merge") $postbody = "<build branchName='$buildBranch'> <buildType id='%TargetBuildType%'/> </build>" Write-Host $postbody $user = '%TeamCityUser%' $pass = '%TeamCityPassword%' $secpasswd = ConvertTo-SecureString $pass -AsPlainText -Force $credential = New-Object System.Management.Automation.PSCredential($user, $secpasswd) Invoke-RestMethod https://teamcity/httpAuth/app/rest/buildQueue -Method POST -Body $postbody -Credential $credential -Headers @{"accept"="application/xml";"Content-Type"="application/xml"}
You will see that we replace the branch name head with merge, so we trigger after someone clicks the update branch button only.
Also don’t forget to add a VCS trigger for file changes “+:.”, so that it will only run builds when there are changes.
We are running with this solution this week and I am going to put a request into GitHub support about option 1.
This is a really big issues for us as we have 30-40 open pull requests on our repo, so double building creates a LOT of traffic.
If anyone has a better solution please leave some comments.
Here is the reply from github
This is after I mentioned that the merge reference is recommended by teamcity, Travis, and appveyor
—–
The ref/pull/$id/merge reference is an undocumented implementation detail of the “Merge pull request” button. We make no guarantees that this will not be changed or even exist in the future, which is why we do not recommend relying on it, along with the caveats that I mentioned in my last reply.
I realize the merge ref is convenient, but for your purposes it’s inaccurate and could lead to your test builds not matching what is actually merged into your production branch. It’s also not guaranteed to exist at the exact moment when code is pushed, but is regenerated asynchronously. This is an issue that the CI services have to deal with as well. While we have some active discussions around improving this experience, there’s no timetable for the change.
LikeLiked by 1 person
interesting…
LikeLike