From d9dfe0c0486dc00be1eb51cdeec873793021870c Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Tue, 22 Sep 2020 13:30:00 +0100 Subject: [PATCH] chore: push docker tags from ci Adds script and ci config to push to docker hub when - the master or main branch changes - semver like tags are pushed to the repo Pushing a semver like tag pushes a docker image with the same tag. The docker latest tag points to the last semver version tag Pushing changes to main or master gets you a docker tag of the form -- e.g main-2020-f435621. a -latest docker tag is provided as a convenince if you really want the bleeding edge. The branch name is included in the docker tag name to make that clearer. This is a tweak on what I set up for go-ipfs in https://github.com/ipfs/go-ipfs/pull/6949 License: MIT Signed-off-by: Oli Evans --- .circleci/config.yml | 52 ++++++++++++++++++++++++++-- hooks/post_checkout | 5 --- scripts/push-docker-tags.sh | 68 +++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 8 deletions(-) delete mode 100644 hooks/post_checkout create mode 100755 scripts/push-docker-tags.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index a640d0f8d..42806440c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,6 +4,11 @@ executors: golang: docker: - image: cimg/go:1.15.2 + dockerizer: + docker: + - image: cimg/go:1.15.2 + environment: + IMAGE_NAME: filecoin/sentinel-visor jobs: test: @@ -17,7 +22,7 @@ jobs: - run: make testshort docker-build: - executor: golang + executor: dockerizer steps: - checkout - setup_remote_docker: @@ -25,11 +30,52 @@ jobs: - run: name: Build Docker image command: | - docker build -t filecoin/sentinel-visor . + docker build -t $IMAGE_NAME . + - run: + name: Archive Docker image + command: docker save -o docker-image.tar $IMAGE_NAME + - persist_to_workspace: + root: . + paths: + - ./docker-image.tar + + docker-push: + executor: dockerizer + steps: + - checkout + - setup_remote_docker: + version: "18.09.3" + - attach_workspace: + at: /tmp/workspace + - run: + name: Load archived Docker image + command: docker load -i /tmp/workspace/docker-image.tar + - run: + name: Publish Docker Image to Docker Hub + command: | + echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin + ./scripts/push-docker-tags.sh "$IMAGE_NAME" "$CIRCLE_SHA1" "$CIRCLE_BRANCH" "$CIRCLE_TAG" workflows: version: 2 check: + # `test` runs for all branches + # `docker-build` runs for all branches and tags that look like semver + # `docker-push` runs master or main branches and tags that look like semver + # see: https://circleci.com/docs/2.0/workflows/#executing-workflows-for-a-git-tag jobs: - test - - docker-build + - docker-build: + filters: + tags: + only: /^v[0-9].*/ + - docker-push: + requires: + - docker-build + filters: + branches: + only: + - master + - main + tags: + only: /^v[0-9].*/ diff --git a/hooks/post_checkout b/hooks/post_checkout deleted file mode 100644 index 9bd7e3ab5..000000000 --- a/hooks/post_checkout +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -# Docker hub does a recursive clone, then checks the branch out, -# so when a PR adds a submodule (or updates it), it fails. -# See: https://stackoverflow.com/questions/58690455/how-to-correctly-initialize-git-submodules-in-dockerfile-for-docker-cloud -git submodule update --init diff --git a/scripts/push-docker-tags.sh b/scripts/push-docker-tags.sh new file mode 100755 index 000000000..acdcfc735 --- /dev/null +++ b/scripts/push-docker-tags.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +# push-docker-tags.sh +# +# Run from ci to tag images based on the current branch or tag name. +# Like dockerhub autobuild config, but somewhere we can version control it. +# +# The `docker-push` job in .circleci/config.yml runs this script to decide +# what tag, if any, to push to dockerhub. +# +# Usage: +# ./push-docker-tags.sh [git tag name] [dry run] +# +# Example: +# # dry run. pass a 5th arg to have it print what it would do rather than do it. +# ./push-docker-tags.sh myiamge testingsha master "" dryrun +# +# # push tag for commit on the main branch +# ./push-docker-tags.sh myimage testingsha main +# +# # push tag for a new release tag +# ./push-docker-tags.sh myimage testingsha release v0.5.0 +# +# # serving suggestion in circle ci - https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables +# ./push-docker-tags.sh filecoin/sentinel-visor $CIRCLE_SHA1 $CIRCLE_BRANCH $CIRCLE_TAG +# +set -euo pipefail + +if [[ $# -lt 3 ]] ; then + echo 'At least 3 args required. Pass 5 args for a dry run.' + echo 'Usage:' + echo './push-docker-tags.sh [git tag name] [dry run]' + exit 1 +fi + +IMAGE_NAME=$1 +GIT_SHA1=$2 +GIT_SHA1_SHORT=$(echo "$GIT_SHA1" | cut -c 1-7) +GIT_BRANCH=$3 +GIT_TAG=${4:-""} +DRY_RUN=${5:-false} +DATE_SHORT=$(date -u +%F) + +pushTag () { + local IMAGE_TAG=$1 + if [ "$DRY_RUN" != false ]; then + echo "DRY RUN!" + echo docker tag "$IMAGE_NAME" "$IMAGE_NAME:$IMAGE_TAG" + echo docker push "$IMAGE_NAME:$IMAGE_TAG" + else + echo "Tagging $IMAGE_NAME:$IMAGE_TAG and pushing to dockerhub" + docker tag "$IMAGE_NAME" "$IMAGE_NAME:$IMAGE_TAG" + docker push "$IMAGE_NAME:$IMAGE_TAG" + fi +} + +if [[ $GIT_TAG =~ ^v[0-9]+ ]]; then + pushTag "$GIT_TAG" + pushTag "latest" + +elif [[ $GIT_BRANCH =~ ^(master|main)$ ]]; then + pushTag "$GIT_BRANCH-${DATE_SHORT}-${GIT_SHA1_SHORT}" + pushTag "$GIT_BRANCH-latest" + +else + echo "Nothing to do for branch: $GIT_BRANCH, tag: $GIT_TAG" + +fi