diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 6205d76e9..de1af9b71 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -24,33 +24,59 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v3 + # Need fetch-depth 0 to fetch tags, see https://github.com/actions/checkout/issues/701 + with: + fetch-depth: 0 + + - name: Gather context + id: ctx + run: | + echo is_release=${{ contains(github.ref, 'refs/tags/') }} | tee -a $GITHUB_OUTPUT + echo is_dev=${{ ! contains(github.ref, 'refs/tags/') }} | tee -a $GITHUB_OUTPUT + echo version=$(git describe --always --tags) | tee -a $GITHUB_OUTPUT + + # QEMU is used to set up VMs for building non-x86_64 images. + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + with: + platforms: "arm,arm64" + + # This is required to build multi-arch images. + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 - name: Log in to registry - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and push container image - run: | - # Image name may contain only lowercase letters - IMAGE_ID=$(echo ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | tr '[A-Z]' '[a-z]') - - # Strip git ref prefix from version - VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') - # If not tag, then use `develop` as image tag - [ "$VERSION" == main ] && VERSION=develop - - echo IMAGE_ID=$IMAGE_ID - echo VERSION=$VERSION - - docker build . --file container/Dockerfile \ - --build-arg "CREATED=$(date --rfc-3339=seconds)" \ - --build-arg "VERSION=$(git describe --always)" \ - --build-arg "COMMIT=$(git rev-parse -q --verify HEAD^{commit})" \ - --tag $IMAGE_ID:$VERSION - - docker push $IMAGE_ID:$VERSION - - if [[ "${{ github.ref }}" == "refs/tags/"* ]]; - then - docker tag $IMAGE_ID:$VERSION $IMAGE_ID:latest - docker push $IMAGE_ID:latest - fi + - name: Configure metadata + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + # Configure to use `latest` and the PEP440 version from a tag name for + # releases, and `develop` for non-release main builds. + tags: | + type=pep440,pattern={{ version }},enable=${{ steps.ctx.outputs.is_release }} + type=raw,value=latest,enable=${{ steps.ctx.outputs.is_release }} + type=raw,value=develop,enable=${{ steps.ctx.outputs.is_dev }} + labels: | + org.opencontainers.image.authors=opensource@aiven.io + org.opencontainers.image.url=https://karapace.io + org.opencontainers.image.documentation=https://github.com/aiven/karapace/ + org.opencontainers.image.vendor=Aiven + org.opencontainers.image.licenses=Apache-2.0 + + - uses: docker/build-push-action@v4 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + KARAPACE_VERSION=${{ steps.ctx.outputs.version }} + file: container/Dockerfile + platforms: "linux/amd64,linux/arm64" diff --git a/container/Dockerfile b/container/Dockerfile index 10b7702fb..2e314273a 100644 --- a/container/Dockerfile +++ b/container/Dockerfile @@ -2,12 +2,7 @@ # generate wheel files. FROM debian:stable-slim AS builder -LABEL org.opencontainers.image.authors=opensource@aiven.io \ - org.opencontainers.image.url=https://karapace.io \ - org.opencontainers.image.documentation=https://github.com/aiven/karapace/ \ - org.opencontainers.image.source=https://github.com/aiven/karapace/ \ - org.opencontainers.image.vendor=Aiven \ - org.opencontainers.image.licenses=Apache-2.0 +ARG KARAPACE_VERSION # Build dependencies that need to be installed: # - git: Used to install dependencies directly from their public repos (release @@ -39,14 +34,6 @@ RUN pip3 wheel --no-deps /build/karapace-repo --wheel-dir /build/karapace-wheel # Karapace image. FROM debian:stable-slim AS karapace -# Labels must be redefined beucase the base image is debian -LABEL org.opencontainers.image.authors=opensource@aiven.io \ - org.opencontainers.image.url=https://karapace.io \ - org.opencontainers.image.documentation=https://github.com/aiven/karapace/ \ - org.opencontainers.image.source=https://github.com/aiven/karapace/ \ - org.opencontainers.image.vendor=Aiven \ - org.opencontainers.image.licenses=Apache-2.0 - RUN groupadd --system karapace && \ useradd --system --gid karapace karapace && \ mkdir /opt/karapace /opt/karapace/runtime /var/log/karapace && \ @@ -70,12 +57,5 @@ COPY ./container/healthcheck.py /opt/karapace WORKDIR /opt/karapace USER karapace -ARG CREATED -ARG VERSION -ARG COMMIT -LABEL org.opencontainers.image.created=$CREATED \ - org.opencontainers.image.version=$VERSION \ - org.opencontainers.image.revision=$COMMIT - HEALTHCHECK --interval=10s --timeout=30s --retries=3 --start-period=60s \ CMD python3 healthcheck.py http://localhost:$KARAPACE_PORT/_health || exit 1 diff --git a/container/build_image.sh b/container/build_image.sh deleted file mode 100755 index 7c5261950..000000000 --- a/container/build_image.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash -set -Eeuo pipefail - -# Helper script to generate a karapace image. -# -# Notes: -# - The script will always create a fresh temporary directory to run from. This -# has a few benefits: -# - Ensures a clean state for copying files into the docker image. This is -# important specially important for the generate version.py file. -# - Makes sure the code in the container is not from a dirty working tree, so -# the commit in the project's version is the real code. -# - Prevents errors with concurrent changes, e.g. if you're generating a image -# while coding, and unintentionally save a file. -# - Effective uses of the caching layers. -# -# If for some reason you want to include the dirty state in the container just -# call docker build directly. - -ARG_COMMIT=$1 -ARG_TAG_NAME=${2:-$1} - -COMMIT=$(git rev-parse -q --verify "${ARG_COMMIT}^{commit}") -# replaces every occurence of / with - -# this is useful if the commit is qualified with the repo name, e.g. aiven/master -TAG_NAME=${ARG_TAG_NAME////-} - -if [[ -z ${COMMIT} ]]; then - echo "Invalid commit provided '${ARG_COMMIT}'" - echo "" - echo "$0 [:tag]" - exit 1 -fi - -code_checkout=$(mktemp --directory --suffix=-karapace-image) -trap 'rm -rf "$code_checkout"' EXIT - -git clone "$(dirname "$0")"/.. "${code_checkout}" - -pushd "${code_checkout}" -git checkout "$COMMIT" - -created=$(date --rfc-3339=seconds) -version=$(git describe --always) - -sudo docker build \ - --build-arg "CREATED=$created" \ - --build-arg "VERSION=$version" \ - --build-arg "COMMIT=$COMMIT" \ - --tag "karapace:${TAG_NAME}" \ - --file container/Dockerfile \ - "${code_checkout}" diff --git a/container/publish_image.sh b/container/publish_image.sh deleted file mode 100755 index 64d56152c..000000000 --- a/container/publish_image.sh +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env bash -set -Eeuo pipefail -# -# Helper script to publish an existing image to hub.docker.com -# - -COLOR_RED=$(tput setaf 1) -COLOR_RESET=$(tput setaf reset) - -function die() { - msg=$1 - echo "${COLOR_RED}${msg}${COLOR_RESET}" - exit 1 -} - -function error() { - msg=$1 - echo "${COLOR_RED}${msg}${COLOR_RESET}" -} - -function usage() { - echo "${0} " - exit 1 -} - -if [[ $# -ne 1 ]]; then - usage -fi - -IMAGE_TAG=$1 -IMAGE_NAME=karapace -HUB_USER=aivenoy -HUB_REPO=karapace -DRY_RUN_FLAG=0 - -if [[ $DRY_RUN_FLAG -eq 1 ]]; then - DRY_RUN='echo' -else - DRY_RUN=sudo -fi - -object_type=$(git cat-file -t "$IMAGE_TAG") -if [[ ${object_type} == commit ]]; then - # make sure we are using the full commit - IMAGE_TAG=$(git rev-parse --verify "${IMAGE_TAG}") -elif [[ ${object_type} == tag ]]; then - git verify-tag "${IMAGE_TAG}" || die "The git tag '${IMAGE_TAG}' is not signed or the signature could not be validated" -else - # Only release from commit or tags - error "Input should be a commit or tag" - echo - usage -fi - -IMAGE_NAME_TAG="${IMAGE_NAME}:${IMAGE_TAG}" -HUB_USER_REPO="${HUB_USER}/${HUB_REPO}" -HUB_IMAGE_LATEST="${HUB_USER_REPO}:latest" -HUB_IMAGE="${HUB_USER_REPO}:${IMAGE_TAG}" - -sudo docker pull ${HUB_USER_REPO} - -sudo docker image inspect "${IMAGE_NAME_TAG}" &>/dev/null || die "image '${IMAGE_NAME_TAG}' doesn't exist." -$DRY_RUN docker tag "${IMAGE_NAME_TAG}" "${HUB_IMAGE}" || die "retagging '${IMAGE_NAME_TAG}' to '${HUB_IMAGE}' failed" - -FIRST_IMAGE=0 -sudo docker image inspect "${HUB_IMAGE_LATEST}" &>/dev/null || FIRST_IMAGE=1 - -if [[ $FIRST_IMAGE -eq 1 ]]; then - PUSH_LATEST=1 - $DRY_RUN docker tag "${IMAGE_NAME_TAG}" "${HUB_IMAGE_LATEST}" || die "retagging '${IMAGE_NAME_TAG}' to '${HUB_IMAGE_LATEST}' failed" -else - # Check if the new image should be tagged as latest too - # - If for some reason an older commit should be tagged as latest, it - # will need to be done manually. - # - This is useful to publish missing releases - latest_published_commit=$(sudo docker image inspect "${HUB_IMAGE_LATEST}" | jq -r '.[].ContainerConfig.Labels["org.opencontainers.image.version"]') - - # List the commits that are in $IMAGE_TAG but not in $latest_published_commit - extra_commits_local=$(git rev-list "${latest_published_commit}..${IMAGE_TAG}" | wc --lines) - # the opposite - extra_commits_remote=$(git rev-list "${IMAGE_TAG}..${latest_published_commit}" | wc --lines) - - if [[ $extra_commits_local -gt 0 && $extra_commits_remote -gt 0 ]]; then - error "The published '${HUB_IMAGE_LATEST}' image and the new image are from different branches." - echo - error "'${HUB_IMAGE_LATEST}' is based on '${latest_published_commit}'" - error "it has ${extra_commits_remote} additional commits" - echo - error "'${TAG_NAME}' is based on '${latest_published_commit}'" - error "it has ${extra_commits_local} additional commits" - echo - die "aborting" - fi - - # The local image has new commits, so it is the latest - if [[ $extra_commits_local -gt 0 && $extra_commits_remote -eq 0 ]]; then - PUSH_LATEST=1 - fi -fi - -$DRY_RUN docker push "${HUB_IMAGE}" -if [[ $PUSH_LATEST -eq 1 ]]; then - $DRY_RUN docker push "${HUB_IMAGE_LATEST}" -fi