Auto Syncing To GitHub From TeamCity

Auto Syncing To GitHub From TeamCity

This was kind of painful to set up so I figured it might be useful for others as a tutorial.  This describes how to configure TeamCity to deploy to GitHub daily from a local git repo (in my case, running on GitLab) which is considered the record of authority.

The project itself is a CMake project within CLion, so there are some idiosyncrasies specific to CMake projects included.

First I configured a build configuration for the project, this will be variable based on your specific project and isn’t the subject of this post, so I’ll assume you already have this build configuration set up and it’s simply called Build.  In my case this does both a debug and release build while deploying the artifacts to a local FTP server for testing.

The first build step within the GitHub deployment is pretty straightforward, it just sets permissions on a script which cleans things up to avoid cluttering the public GitHub repository with unnecessary files, artifacts, etc and consists of a Command Line build step with the following content:

chmod 0777 ./github_prep.sh
./github_prep.sh

The github_prep.sh script contents look like the following, the last line might need to be changed per your configuration, in my case configuration.hpp is built from a file named configuration.hpp.in based on the CMakeLists.txt configuration.  This exists as a file in the root of the local git repo for the sake of ease of maintenance:

#!/bin/sh

rm build -Rf
rm CMakeFiles -Rf
rm CMakeCache.txt -f
rm Makefile -f
rm cmake_install.cmake -f
rm configuration.hpp -f

The second build step is where the actual deployment to GitHub happens, along with some more cleanup like stripping out the .gitignore and the aforementioned github_prep.sh script:

rm .gitignore -f
rm github_prep.sh -f
git config --global user.name USER_NAME
git add .
git rm github_prep.sh -f
git rm .gitignore -f
git commit -m "Auto Commit"
git remote add github git@github.com:ORGANIZATION/PROJECT_NAME.git
git remote -v
git push -f github master

In the above lines USER_NAME is a GitHub user I created specifically for the TeamCity server to use, while ORGANIZATION is the GitHub organization containing the repo.  In your case USER_NAME and ORGANIZATION might just be the same username, or the ORGANIZATION might map to another user.  In any event USER_NAME must have access to push to ORGANIZATION/PROJECT_NAME.git.

Additionally, TeamCity doesn’t like interactive git commands, so the above url is using SSL instead of https.  To configure TeamCity for access to the GitHub account you will first need to run:

sudo su teamcity

Or whatever your teamcity agent is executing as, and then execute the following commands:

cd ~
ssh-keygen -t rsa -b 4096 -C "YOUR_GITHUB_EMAIL_ADDRESS"
ssh-add ~/.ssh/id_rsa
cat ~/.ssh/*.pub

This will ultimately spit out the public key you’ve just created.  You will then need to copy your public key to the GitHub SSH key for the USER_NAME used above, currently this is under the icon at the top-right, then Settings, and “SSH and GPG keys” on the left, from there you just click New SSH Key and paste it in along with a title.

You will then need to adjust the trigger in TeamCity for your new build configuration to happen daily at some time and check off the box labeled “Trigger only if watched build changes” then set the dropdowns below it to point at your original build configuration.

Some potential issues with this:

  • I’m not sure how it will work (if at all) with commits coming in from other GitHub users.  My expectation would be that this is only really good for deploying code for public view while maintaining the version history.
  • Currently GitHub seems to be linking most of the users in the development team to their GitHub accounts, but there doesn’t seem to be any rhyme or reason as to why it is picking up some but not all of the developers in the organization (emails are the same between GitLab and GitHub but usernames or not, so I would have expected it to be all or nothing.)  I’ve asked GitHub about the logic going into this linking to see if I can pinpoint the issue and will possibly update this post in the future with additional steps if it turns out to be a time consuming issue to solve.

About the Author