Frequently, when compiling applications, we need to update the version number inside some source files, so that the binary ends up with the correct version metadata. This usually means there is a build task that modifies a source file, based on the information passed from the controlling CI system.
This works well when it all happens on the CI server, and any modifications to those files are thrown away at the end of the build. However, this can be a pain when you run the build locally, and you end up with modified files in your working copy. You are able run the same build that happens on the CI server locally, aren’t you?
This can be avoided by skipping this task in your build script if it’s not run under the CI server (for example, if certain environment variables are not present). The downside of this is that the process you test locally is different to the one that runs on the CI server.
Normally, this would be resolved by excluding the file from Git (via the .gitignore file), but that means a fresh clone doesn’t contain this file – not a great experience.
A solution to this problem that we have found works well is to split up the metadata files so that the items that change every build are separate from the static metadata.
To use an example from the .NET world:
AssemblyInfo.AutomaticallyUpdated.cs file contains the version information:
While the standard
AssemblyInfo.cs contains the static metadata:
At this point, we are in a place where our build scripts can be simpler, as they can overwrite the whole (
AssemblyInfo.AutomaticallyUpdated.cs) file, rather than modifying individual values, but we still have the issue around modified files in the working copy.
In the build script (psake in this case), after modifying the file, we can call
git update-index –assume-unchanged <filename> to tell Git to ignore the changes to the file:
This allows us to have the file in Git, but also to have throw-away modifications made to the file. Happy all round.
Hope this helps!