I have a similar workflow that builds multiple Docker images from a monorepo. The solution I’ve come up with is to wrap that logic in a shell script which exits 0 if either the image is built or its not built because the relevant files did not change based on git diff.
The approach was to create a logical_changes.sh
which parses the git refs in CIRCLE_COMPARE_URL
to determine the appropriate git diff ref1 ref2 --name-only
command to run. Then, for each logical change, which equates to a need to build a Docker image, that script exports values like CI_IMAGE_A_CHANGED
or CI_IMAGE_B_CHANGED
.
FInally, I have shell scripts for each docker build which source logical_changes.sh
, test the value of the relevant CI_IMAGE_*_CHANGED
then either exit 0 early or run the docker build.
Each Docker build in my workflow ends up looking something like:
build_and_push_foo_release:
working_directory: /root/project
docker:
- image: foo/circleci-builder
steps:
- attach_workspace:
at: /root/project
- setup_remote_docker:
version: 17.05.0-ce
- run:
name: Build Foo Docker Image
command: |
cd /root/project/
TAG=$CIRCLE_BRANCH-$CIRCLE_SHA1
ci/build_foo_docker_image.sh ecom/ $TAG
So, in cases where no build and push is necessary, those builds take about 60-90 seconds to setup_remote_docker
, then exit when the script recognizes it need not build an image.
However, like you I recognize that ideally we could short-circuit earlier potentially using a when
condition on the steps in a build that could test the value of an environment variable.