Posts in  teamcity

4.17.2014

Video: The Value of Consistently Formatted Code

Tabs or Spaces, the age old debate that will likely never be settled! Fortunately, at the end of the day consistent formatting is more valuable than the rules we follow because consistency significantly improves readability and maintainability.

10.17.2013

TeamCity - Automatic Testing of Feature Branch Merging

Risk of Conflict

One of the drawbacks of Feature Branching is the likelihood of merge conflicts as time moves forward. Even with the best of intentions we all get busy and forget to merge our integration branch into our feature branch or vice verse. A mechanism to let us know when conflict occurs would be helpful.

Mitigating Conflict with Continuous Integration

Continuous Integration can help mitigate this risk by automatically merging changes in a feature branch with the integration branch and testing the result. Conflict may arise from the merge itself, or from compilation, testing and other stages of a deployment pipeline.

Leveraging TeamCity

Scenario

  • git for VCS
  • master is the integration branch
  • feature branches start with feature_
  • windows, so the script below uses batch file syntax

Setup

  • Add a new Build Configuration

    • General Settings
      • Name: Automatically Merge and Test Feature Branches
    • Click "Version Control Settings"
      • Choose "Create and attach new VCS root"
        • Type of VCS: Git
        • Fetch URL: set based on your project
        • Default branch: master
          • Or if you have a "primary" feature branch you can use that instead
        • Branch specification: +:refs/heads/(feature_*)
          • This will automatically monitor all branches that start with feature_, even new ones!
          • ()s denote what to show in the TeamCity UI, ie: refs/heads/feature_one will show as feature_one
          • See Working with Feature Branches for more
        • Authentication: set based on your project
        • Save the VCS root
      • Back on the Version Control Settings page
        • VCS checkout mode: Automatically on agent (if supported by VCS roots)
          • This ensures the agent has a copy of the git repository, not just the contents of the last commit
        • Clean all files before build: checked
          • This forces the build directory to be cleaned before each build, otherwise the git repository and files from the last merge would remain and your script would need to be able to handle both the first build as well as subsequent builds. I prefer to work from the assumption of a clean environment at the start of each run.
    • Click "Add Build Step"

      • Runner type: Command Line
      • Name: Merge
      • Run: Custom script
      • Custom script:

        "%env.TEAMCITY_GIT_PATH%" fetch origin
        "%env.TEAMCITY_GIT_PATH%" checkout -b master origin/master
        "%env.TEAMCITY_GIT_PATH%" config --local user.email "automerge@merge.com"
        "%env.TEAMCITY_GIT_PATH%" config --local user.name "Auto Merge"
        "%env.TEAMCITY_GIT_PATH%" merge --no-commit %teamcity.build.branch%
        
      • The script above is crude to demonstrate the process, feel free to modify it to fit your needs

        • First, fetch everything
        • Then, checkout the master branch
        • Next, set user & email
          • git requires this even with --no-commit on a merge
        • Finally, merge the feature branch into master
      • Save the Build Step
    • Go to "Build Triggers"
      • Choose "Add new trigger"
      • Choose "VCS Trigger"
      • If you used master as the default branch in your VCS root, you want to exclude it in the branch filter as it doesn't need to be merged with itself :)
        • -:refs/heads/master
      • Save the trigger

Things to try

  • Run your new build configuration
  • Try committing in a feature branch that results in a merge conflict
    • Wait for notification
  • Try fixing the merge conflict in the feature branch
    • Wait for notification
  • Add subsequent Build Steps for
    • Compilation
    • Testing
  • Consider creating your own Build Step via a template to re-use this script across projects
    • or Consider checking this script into your repository so it can be version-ed with the rest of your project
  • Modify the script to handle other feature branching and integration branching setups

On auto pushing "successful" merges

Some teams like the idea of pushing if the merge succeeds and tests pass. I guess that depends on your particular team and how you work together. That said here are my thoughts:

  • A merge is a change and should require human review.
  • Tests (if they exist), aren't guaranteed to cover the merged features.
  • The bang for the buck is notifying us when merge conflicts begin.

If auto pushing is of value, here's how you can modify the above to accomplish that:

  • Drop the --no-commit on the merge
  • Set real user name & email you want on the merge commit
  • Add a push command to the end of the script
  • And probably want to detect if there's even a need for a merge commit before pushing or this could turn into a never ending loop :)

Wrap Up

Obviously this can't mitigate all forms of conflict. As Martin Fowler points out, semantic conflict will be very difficult to detect, especially if there isn't much test coverage.

Nonetheless, checking the basics can help us catch issues faster and remind us to keep the flow of information between integration and feature branches open.