BYOT - Bring Your Own Tools

Repetition - time consuming and mind numbing if you have to do something manually. A lot better if you can automate... no argument there.

And yet, there is always room for improvement.

CI/CD State of the Nation

These days we have a plethora of automation and build tools to choose from. We can self host and maintain the build environment ourselves... or we could start treating it like the commodity it is and let others deal with the cost of ownership and heavy lifting. I'm talking of all the SaaS offerings out there...

The usual suspects are CloudBees, CircleCI, Azure Pipelines and AWS CodeBuild, just to mention a few.

Six or half a dozen, they are all very similar. Some have a great UI and offer a good UX... and then some don't. But, they all have the ability to use build spec files and that is the key.

Spec files describe the steps required to complete a build. These steps include downloading and installing build dependencies on the build agents. That is great in principle, but if you consider the ephemeral nature of build agents and that there is no guarantee you'll get the same agent on subsequent builds, it raises the question on how much time is wasted on prepping the agent vs. the time the actual build takes...

Agent Amnesia

"Oh, you wanted a JVM... again?" - The usual response from an agent when it executes your Spring Boot app build for what it thinks is the first time.

"I see you're executing a terraform plan, let me install terraform for you... again" - This should be a request from your spec file. Or, if you are lucky, you can pic a specific agent based on some criteria.

"Wait, what, Helm? - Again your spec file issues a request for a specific tool to be installed.

All the minutes wasted in preparing the agent to finally do what it was asked to do, i.e. build your software or run a chef command or terraform plan, etc. start adding up quickly...

Agent Prepared

Most, if not all SaaS offerings in this space allow you to specify a docker image or at a minimum allow you to run a docker image that has all the tools pre-installed to perform the tasks required.

If you can "bring your own tools", not only can you ensure consistent results between builds by locking in versions of build dependencies but you can also supply your own set of helper scripts.

One major other benefit is that those containers are highly portable and allow developers to use exactly the same image the build agents would be using.

"Here's something we prepared earlier."

We are heavily invested in Infrastructure As Code so we use terraform to maintain our AWS infrastructure. We also use EKS, so we also need kubectl and helm. Most of the time we need all of those tools in the same build, so it makes sense to have an agent that can deliver this combination of tools. Using a pre-baked docker image saves a lot of time, especially considering we run quite the number of builds per day.

As already mentioned above an additional benefit is being able to include helper scripts.

ckemper/t7m-tools contains a little helper script that allows for a fairly opinionated terraform execution.

Here is a snippet of commands without the helper:

$ terraform init -backend-file var/myenv.hcl
$ terraform plan -var-file var/myenv.tfvars
$ terraform apply -var-file var/myenv.tfvars
Here we are initializing a terraform project, then running a plan and finally an apply.

And now for the version with the helper:

$ tf plan -i -e myenv
$ tf apply -e myenv
The same 3 steps executed here in only two terse lines...

You could argue there isn't much gained from doing it this way, but time has shown us that the repetition, especially if devs need to occasionally run this on their local desktops whilst they are preparing terraform scripts, it is far less error prone.


Every dev working on the terraform projects is guaranteed to have the same versions of all the tools without having to install them individually on their desktop machines.

Every agent running a terraform plan/apply only needs to pull a container if it hasn't already been cached and is ready and configured to handle the steps in the build spec, no additional time wasted.