/ continuous integration

Build scripts instead of build steps in CI tools

Many popular CI tools like TeamCity or Team Foundation Server (TFS) provide an easy way to configure the build steps via their web interface:


While this is certainly a very convinient way to configure your CI pipeline, it might not be the best approach in the long run. Let's take a closer look why this is the case and why using scripting tools like Cake or PSake is a much better alternative.

Reasons to avoid configuring build pipeline as steps in a CI tool

ThoughtWorks summarized it very well in their recommendation to avoid Programming in your CI/CD tool. But let me reiterate and expand a little on those reasons:

1. Configuration is not in source control

Build pipeline is effectively a script even if it is defined visually via a web interface. Most of the build steps have a long list of arguments and settings that you enter into the configuration tool. This script, like any source code, can benefit greatly from version control.

Additionally, build configuration is normally coupled to the source code of your project. It knows where the things that need to be build are located, what version of the compiler needs to be used, what arguments need to be passed to the compiler, and so on. This means that when something changes in your source code that requires the change in the build configuration (e.g. upgrade to a new version of a framework or adding a new project), the build configuration needs to be changed together with the source code of the project.

2. Lack of portability and vendor lock-in

Putting all your eggs in one basket is never a good idea. "Hardcoding" all the build steps inside a specific CI vendor like TeamCity makes it very difficult to extract it and move to another tool.

3. Not possible to run on a developer's machine

Related to the previous point about lack of portability, having all the configuration inside the CI tool makes it impossible to run the CI build a developer's machine. Here we have two scenarios:

  • During day to day work developers cannot easily test their changes by running the CI build locally on their machines.
  • When making changes to the build pipeline itself the only way to test it is to run a test build on the build server. This might be difficult if your build servers are busy and the build queue is full. And if there is a mistake in the configuration everybody on the team will be affected.

The Alternative

The alternative is to use a scripting engine to write a single script that is stored together with your source code under source control and can be run anywhere, not just on the build server.

Which scripting engine to use depends on your environment, your skills and preferences. For example, .NET/C# developers might like Cake (or Fake), Ruby devs probably will use Rake, and so on.

The Role of a CI tool

When you have your build steps as a script in your source control the role of the CI tool is still important but limited to:

  • Triggers
    Decide when to run your script (e.g. on check-in or nightly).
  • Manage Build Artifacts
    If the build produces artifacts that can be downloaded by testers or deployed automatically by a continuous deployment pipeline.
  • Notifications
    Notify the team about build status.
  • Gatekeeping
    Prevent the code from getting into the main branch of your source control unless the build succeeds.

In other words, the CI tool is responsible for all the surrounding workflow, but the build steps part must contain only one step: the call to your build script.


Here are a few other excellent resources on this topic:

Pavlo Glazkov

Pavlo Glazkov

Programmer. Full stack, with a focus on UI. JavaScript/TypeScript, Angular, Node.js, .NET

Read More