From 611204c38246215ec5f6e8681874f7abb9cdb8cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 25 Feb 2020 19:06:49 +0100 Subject: [PATCH] Only build/tag/push images once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- .gitlab-ci.yml | 17 ++++++++++++++--- README.md | 12 ++++++++++++ scripts/build-helpers.sh | 25 +++++++++++++++++++++++++ scripts/custom-docker-build | 27 ++++++++++++++++++++++----- 4 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 scripts/build-helpers.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 40172d2..105bcbe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,13 +6,16 @@ stages: - automation services: -- docker:dind + - docker:19.03.0-dind variables: - DOCKER_DRIVER: overlay + DOCKER_DRIVER: overlay2 + DOCKER_HOST: tcp://docker:2375 + FORCE_BUILD: "false" before_script: - docker login -u "gitlab-ci-token" -p "$CI_JOB_TOKEN" "$CI_REGISTRY" + - source scripts/build-helpers.sh .test_build: &test_build stage: test @@ -23,6 +26,8 @@ before_script: - docker build -f "Dockerfile.$1" . except: - master + tags: + - docker .build_and_deploy: &build_and_deploy stage: build @@ -31,6 +36,8 @@ before_script: - docker push "$CI_REGISTRY_IMAGE:$CI_JOB_NAME" only: - master + tags: + - docker .test_custom: &test_custom stage: test @@ -41,14 +48,18 @@ before_script: - ./scripts/custom-docker-build $1 except: - master + tags: + - docker .build_and_deploy_custom: &build_and_deploy_custom stage: build script: - ./scripts/custom-docker-build $CI_JOB_NAME -t "$CI_REGISTRY_IMAGE:$CI_JOB_NAME" - - docker push "$CI_REGISTRY_IMAGE:$CI_JOB_NAME" + - push_if_needed "$CI_REGISTRY_IMAGE:$CI_JOB_NAME" only: - master + tags: + - docker # Tests diff --git a/README.md b/README.md index 9e2b415..67c534c 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,18 @@ the name would be `ruby-2.4-golang-1.9-git-2.14`. 1. Add a test task: `ruby-2.4-golang-1.9-git-2.14 test: *test_custom` 1. Add a new build task: `ruby-2.4-golang-1.9-git-2.14: *build_and_deploy_custom` +#### Forcing custom images to be rebuilt + +By default, once a custom image is built, tagged and pushed to the registry, it's +not rebuilt to ensure an upstream dependency doesn't end up breaking our images +unexpectedly. + +For reference, this happened in the past: https://gitlab.com/gitlab-org/gitlab/issues/205192 + +In the rare case where the `Dockerfile.custom` file is updated and all custom +images shoulld be rebuild, you can start a new pipeline and set the variable +`FORCE_BUILD` to `true`. + ## Note regarding Google Chrome Google has a policy of yanking older versions of Google Chrome from their PPA diff --git a/scripts/build-helpers.sh b/scripts/build-helpers.sh new file mode 100644 index 0000000..52b25b0 --- /dev/null +++ b/scripts/build-helpers.sh @@ -0,0 +1,25 @@ +function image_already_exists() { + image=$1 + + $(docker pull $image > /dev/null) +} + +function build_if_needed() { + image=$1 + + if ! image_already_exists $image; then + docker build -t "$image" -f "Dockerfile.$image" . + else + echo "$image already exists, skipping build." + fi +} + +function push_if_needed() { + image=$1 + + if ! image_already_exists $image; then + docker push "$image" + else + echo "$image already exists, skipping push." + fi +} diff --git a/scripts/custom-docker-build b/scripts/custom-docker-build index d6a5c05..99e4b0e 100755 --- a/scripts/custom-docker-build +++ b/scripts/custom-docker-build @@ -3,6 +3,8 @@ set -e IFS=$'\n\t' +source scripts/build-helpers.sh + function print_golang_args() { case "$1" in @@ -198,10 +200,10 @@ function parse_arguments() { } function generate_command() { - buildimage_name=$1; shift; + build_image_name=$1; shift; printf -- "docker build " - echo $buildimage_name | tr '-' '\n' | parse_arguments + echo $build_image_name | tr '-' '\n' | parse_arguments for i in "$@" do @@ -210,6 +212,21 @@ function generate_command() { printf -- ".\\n" } -docker_command=$(generate_command $@) -echo "$1: executing $docker_command" -eval $docker_command +function build_custom_if_needed() { + build_image_name=$1 + full_image_name="$CI_REGISTRY_IMAGE:$build_image_name" + + if [[ "$FORCE_BUILD" == "true" ]] || ! image_already_exists $full_image_name; then + docker_command=$(generate_command $@) + if [[ "$FORCE_BUILD" == "true" ]]; then + echo "Force building $build_image_name due to `\$FORCE_BUILD=true` with $docker_command" + else + echo "Building $build_image_name with $docker_command" + fi + eval $docker_command + else + echo "$build_image_name already exists, skipping build." + fi +} + +build_custom_if_needed $@