From 7f4a7b5b4c4ceb7222673ea75f3e5d53a908d8f2 Mon Sep 17 00:00:00 2001 From: Yulia Gaponenko Date: Fri, 11 Sep 2020 08:56:12 +0200 Subject: [PATCH] add multi-arch image(amd64 and s390x) build and publish for alpine/git image (#23) - build script was extended to build and publish images with arch information in tag (based on TRAVIS_CPU_ARCH env variable value), default is amd64 - in build script NEXT_TAG is generated only for amd64, because container image to get the value is amd64 only - alpine/semver:5.5.0. For s390x this value is stored in Travis workspace (or local file called tag.txt) - git push will work for amd64 only (to avoid push duplicates) - multi-arch-image script was added to create and push multi-arch manifest to dockerhub, joining together separate images for different architectures. At this moment amd64 and s390x are added. - Travis configuration file was extended to have 3 stages: - build amd64 images - build s390x images - generate multi-arch images based on previous stages - workspace usage was added to Travis config to persist NEXT_TAG data, as this value can be received only for amd64 case. s390x is just used it after from workspace tag.txt file Signed-off-by: Yulia Gaponenko --- .travis.yml | 25 ++++++++++++++++++++-- build.sh | 51 ++++++++++++++++++++++++++------------------- multi-arch-image.sh | 42 +++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 24 deletions(-) create mode 100755 multi-arch-image.sh diff --git a/.travis.yml b/.travis.yml index 21dd39a..98906e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,5 +3,26 @@ sudo: required services: - docker -script: - - bash ./build.sh +jobs: + allow_failures: + - if: arch = s390x + include: + - stage: build amd64 + workspaces: + create: + name: ws1 + paths: + - tag.txt + script: + - bash ./build.sh + - stage: build s390x + arch: s390x + workspaces: + use: ws1 + script: + - bash ./build.sh + - stage: make multi-arch images + workspaces: + use: ws1 + script: + - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./multi-arch-image.sh; fi' diff --git a/build.sh b/build.sh index 0940e68..8aca550 100755 --- a/build.sh +++ b/build.sh @@ -10,44 +10,51 @@ set -e image="alpine/git" - +ARCH=${TRAVIS_CPU_ARCH:-"amd64"} LATEST_TAG=$(git ls-remote --tags origin |awk -F \/ '{print $NF}'|grep ^1.0. |sort -Vr|head -1) if [[ -z "${LATEST_TAG}" ]] then NEXT_TAG="1.0.0" else - NEXT_TAG=$(docker run --rm alpine/semver:5.5.0 semver -c -i patch ${LATEST_TAG}) + if [[ "$ARCH" == "amd64" ]] + then + NEXT_TAG=$(docker run --rm alpine/semver:5.5.0 semver -c -i patch ${LATEST_TAG}) + echo ${NEXT_TAG} > tag.txt + else + NEXT_TAG=$(cat tag.txt) + fi fi echo ${NEXT_TAG} -docker build --no-cache -t ${image}:${NEXT_TAG} . -docker tag ${image}:${NEXT_TAG} ${image}:latest +docker build --no-cache -t ${image}:${NEXT_TAG}-${ARCH} . +docker tag ${image}:${NEXT_TAG}-${ARCH} ${image}:latest-${ARCH} # add another tag with git version, with this way, we can check this git image health -VERSION=($(docker run -i --rm ${image}:latest version|awk '{print $NF}')) +VERSION=($(docker run -i --rm ${image}:latest-${ARCH} version|awk '{print $NF}')) echo ${VERSION} -docker tag ${image}:${NEXT_TAG} ${image}:v${VERSION} +docker tag ${image}:${NEXT_TAG}-${ARCH} ${image}:v${VERSION}-${ARCH} if [[ "$TRAVIS_BRANCH" == "master" && "$TRAVIS_PULL_REQUEST" == false ]]; then docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD - docker push ${image}:${NEXT_TAG} - docker push ${image}:latest - docker push ${image}:v${VERSION} - - # push the tag - git remote set-url origin https://${GITHUB_NAME}:${GITHUB_TOKEN}@github.com/alpine-docker/git.git - echo "Set github Username & Email" - git config user.name "ci" - git config user.email "ci" - echo "Create & Push Tag" - git tag ${NEXT_TAG} - git push origin ${NEXT_TAG} + docker push ${image}:${NEXT_TAG}-${ARCH} + docker push ${image}:latest-${ARCH} + docker push ${image}:v${VERSION}-${ARCH} + if [[ "$ARCH" == "amd64" ]]; then + # push the tag + git remote set-url origin https://${GITHUB_NAME}:${GITHUB_TOKEN}@github.com/alpine-docker/git.git + echo "Set github Username & Email" + git config user.name "ci" + git config user.email "ci" + echo "Create & Push Tag" + git tag ${NEXT_TAG} + git push origin ${NEXT_TAG} + fi fi if [[ "$TRAVIS_BRANCH" == "feature/non-root" && "$TRAVIS_PULL_REQUEST" == false ]]; then docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD - docker tag ${image}:v${VERSION} ${image}:user - docker tag ${image}:v${VERSION} ${image}:v${VERSION}-user - docker push ${image}:user - docker push ${image}:v${VERSION}-user + docker tag ${image}:v${VERSION}-${ARCH} ${image}-${ARCH}:user-${ARCH} + docker tag ${image}:v${VERSION}-${ARCH} ${image}-${ARCH}:v${VERSION}-user-${ARCH} + docker push ${image}:user-${ARCH} + docker push ${image}:v${VERSION}-user-${ARCH} fi diff --git a/multi-arch-image.sh b/multi-arch-image.sh new file mode 100755 index 0000000..4ecea56 --- /dev/null +++ b/multi-arch-image.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +# Prerequisite +# Make sure you set secret enviroment variables in Travis CI +# DOCKER_USERNAME +# DOCKER_PASSWORD + +set -e + +function get_arch_images(){ + image=$1; shift || fatal "usage error" + tag=$1; shift || fatal "usage error" + archs="amd64 s390x" + for arch in $archs; do + if [[ "$(docker pull ${image}:${tag}-${arch} >/dev/null 2>&1 ; echo $?)" == 0 ]]; then + echo "${image}:${tag}-${arch} " + fi + done +} + +image="alpine/git" +if [[ "$TRAVIS_BRANCH" == "master" && "$TRAVIS_PULL_REQUEST" == false ]]; then + docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD + NEXT_TAG=$(cat tag.txt) + VERSION=$(docker run -i --rm ${image}:latest-amd64 version|awk '{print $NF}') + #create and push multi-arch 3 images - latest, ${NEXT_TAG} and v${VERSION} + DOCKER_CLI_EXPERIMENTAL="enabled" docker manifest create ${image}:${NEXT_TAG} $(get_arch_images ${image} ${NEXT_TAG}) + DOCKER_CLI_EXPERIMENTAL="enabled" docker manifest push --purge ${image}:${NEXT_TAG} + DOCKER_CLI_EXPERIMENTAL="enabled" docker manifest create ${image}:latest $(get_arch_images ${image} "latest") + DOCKER_CLI_EXPERIMENTAL="enabled" docker manifest push --purge ${image}:latest + DOCKER_CLI_EXPERIMENTAL="enabled" docker manifest create ${image}:v${VERSION} $(get_arch_images ${image} v${VERSION}) + DOCKER_CLI_EXPERIMENTAL="enabled" docker manifest push --purge ${image}:v${VERSION} +fi + +if [[ "$TRAVIS_BRANCH" == "feature/non-root" && "$TRAVIS_PULL_REQUEST" == false ]]; then + docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD + #create and push multi-arch 2 images - user and v${VERSION}-user + DOCKER_CLI_EXPERIMENTAL="enabled" docker manifest create ${image}:user $(get_arch_images ${image} "user") + DOCKER_CLI_EXPERIMENTAL="enabled" docker manifest push --purge ${image}:user + DOCKER_CLI_EXPERIMENTAL="enabled" docker manifest create ${image}:v${VERSION}-user $(get_arch_images ${image} v${VERSION}-user) + DOCKER_CLI_EXPERIMENTAL="enabled" docker manifest push --purge ${image}:v${VERSION}-user +fi