From cee1b5b079054f8e73ee0fda399c40942f844b78 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Wed, 15 Jun 2022 08:22:11 +0200 Subject: [PATCH] Build ARM64 images --- .github/workflows/push.yml | 100 ++++--- .github/workflows/release.yml | 130 +++++---- .yamllint.yaml | 5 + build-functions/docker-functions.sh | 8 - build.sh | 400 +++++++++++++++------------- 5 files changed, 333 insertions(+), 310 deletions(-) create mode 100644 .yamllint.yaml delete mode 100644 build-functions/docker-functions.sh diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 414f3fe..515d4f8 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -1,3 +1,4 @@ +--- name: push on: @@ -13,55 +14,66 @@ jobs: runs-on: ubuntu-latest name: Checks syntax of our code steps: - - uses: actions/checkout@v3 - with: - # Full git history is needed to get a proper list of changed files within `super-linter` - fetch-depth: 0 - - uses: actions/setup-python@v4 - with: - python-version: '3.9' - - name: Lint Code Base - uses: github/super-linter@v4 - env: - DEFAULT_BRANCH: develop - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SUPPRESS_POSSUM: true - LINTER_RULES_PATH: / - VALIDATE_ALL_CODEBASE: false - VALIDATE_DOCKERFILE: false - FILTER_REGEX_EXCLUDE: (.*/)?(LICENSE|configuration/.*) - - EDITORCONFIG_FILE_NAME: .ecrc - DOCKERFILE_HADOLINT_FILE_NAME: .hadolint.yaml - MARKDOWN_CONFIG_FILE: .markdown-lint.yml - PYTHON_BLACK_CONFIG_FILE: pyproject.toml - PYTHON_FLAKE8_CONFIG_FILE: .flake8 - PYTHON_ISORT_CONFIG_FILE: pyproject.toml + - uses: actions/checkout@v3 + with: + # Full git history is needed to get a proper + # list of changed files within `super-linter` + fetch-depth: 0 + - uses: actions/setup-python@v4 + with: + python-version: '3.9' + - name: Lint Code Base + uses: github/super-linter@v4 + env: + DEFAULT_BRANCH: develop + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SUPPRESS_POSSUM: true + LINTER_RULES_PATH: / + VALIDATE_ALL_CODEBASE: false + VALIDATE_DOCKERFILE: false + FILTER_REGEX_EXCLUDE: (.*/)?(LICENSE|configuration/.*) + EDITORCONFIG_FILE_NAME: .ecrc + DOCKERFILE_HADOLINT_FILE_NAME: .hadolint.yaml + MARKDOWN_CONFIG_FILE: .markdown-lint.yml + PYTHON_BLACK_CONFIG_FILE: pyproject.toml + PYTHON_FLAKE8_CONFIG_FILE: .flake8 + PYTHON_ISORT_CONFIG_FILE: pyproject.toml + YAML_CONFIG_FILE: .yamllint.yaml build: - continue-on-error: ${{ matrix.docker_from == 'alpine:edge' }} + continue-on-error: ${{ matrix.build_cmd != './build-latest.sh' }} strategy: matrix: build_cmd: - - ./build-latest.sh - - PRERELEASE=true ./build-latest.sh - - ./build.sh feature - - ./build.sh develop - docker_from: - - '' # use the default of the build script + - ./build-latest.sh + - PRERELEASE=true ./build-latest.sh + - ./build.sh feature + - ./build.sh develop + platform: + - linux/amd64 + - linux/arm64 fail-fast: false + env: + GH_ACTION: enable + IMAGE_NAMES: docker.io/netboxcommunity/netbox runs-on: ubuntu-latest name: Builds new NetBox Docker Images steps: - - id: git-checkout - name: Checkout - uses: actions/checkout@v3 - - id: docker-build - name: Build the image from '${{ matrix.docker_from }}' with '${{ matrix.build_cmd }}' - run: ${{ matrix.build_cmd }} - env: - DOCKER_FROM: ${{ matrix.docker_from }} - GH_ACTION: enable - - id: docker-test - name: Test the image - run: IMAGE="${FINAL_DOCKER_TAG}" ./test.sh - if: steps.docker-build.outputs.skipped != 'true' + - id: git-checkout + name: Checkout + uses: actions/checkout@v3 + - id: qemu-setup + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - id: buildx-setup + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - id: docker-build + name: Build the image for '${{ matrix.platform }}' with '${{ matrix.build_cmd }}' + run: ${{ matrix.build_cmd }} + env: + BUILDX_PLATFORM: ${{ matrix.platform }} + BUILDX_BUILDER_NAME: ${{ steps.buildx-setup.outputs.name }} + - id: docker-test + name: Test the image + run: IMAGE="${FINAL_DOCKER_TAG}" ./test.sh + if: steps.docker-build.outputs.skipped != 'true' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7f448eb..929f705 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,3 +1,4 @@ +--- name: release on: @@ -6,82 +7,77 @@ on: - published schedule: - cron: '45 5 * * *' + workflow_dispatch: jobs: build: strategy: matrix: build_cmd: - - ./build-latest.sh - - PRERELEASE=true ./build-latest.sh - - ./build.sh feature - - ./build.sh develop + - ./build-latest.sh + - PRERELEASE=true ./build-latest.sh + - ./build.sh feature + - ./build.sh develop + platform: + - linux/amd64,linux/arm64 fail-fast: false runs-on: ubuntu-latest name: Builds new NetBox Docker Images env: GH_ACTION: enable + IMAGE_NAMES: docker.io/netboxcommunity/netbox quay.io/netboxcommunity/netbox ghcr.io/netbox-community/netbox steps: - - - name: Checkout - uses: actions/checkout@v3 - - - name: Get Version of NetBox Docker - run: | - echo "::set-output name=version::$(cat VERSION)" - shell: bash - - - id: docker-build - name: Build the image with '${{ matrix.build_cmd }}' - run: ${{ matrix.build_cmd }} - - - name: Test the image - run: IMAGE="${FINAL_DOCKER_TAG}" ./test.sh - if: steps.docker-build.outputs.skipped != 'true' - - # docker.io - - - name: Login to docker.io - uses: docker/login-action@v2 - with: - registry: docker.io - username: ${{ secrets.dockerhub_username }} - password: ${{ secrets.dockerhub_password }} - if: steps.docker-build.outputs.skipped != 'true' - - - name: Push the image to docker.io - run: ${{ matrix.build_cmd }} --push-only - if: steps.docker-build.outputs.skipped != 'true' - - # quay.io - - - name: Login to Quay.io - uses: docker/login-action@v2 - with: - registry: quay.io - username: ${{ secrets.quayio_username }} - password: ${{ secrets.quayio_password }} - if: steps.docker-build.outputs.skipped != 'true' - - - name: Build and push the image with '${{ matrix.build_cmd }}' - run: ${{ matrix.build_cmd }} --push - env: - DOCKER_REGISTRY: quay.io - if: steps.docker-build.outputs.skipped != 'true' - - # ghcr.io - - - name: Login to GitHub Container Registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - if: steps.docker-build.outputs.skipped != 'true' - - - name: Build and push the image with '${{ matrix.build_cmd }}' - run: ${{ matrix.build_cmd }} --push - env: - DOCKER_REGISTRY: ghcr.io - DOCKER_ORG: netbox-community - if: steps.docker-build.outputs.skipped != 'true' + - id: source-checkout + name: Checkout + uses: actions/checkout@v3 + - id: set-netbox-docker-version + name: Get Version of NetBox Docker + run: echo "::set-output name=version::$(cat VERSION)" + shell: bash + - id: qemu-setup + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - id: buildx-setup + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - id: docker-build + name: Build the image with '${{ matrix.build_cmd }}' + run: ${{ matrix.build_cmd }} + - id: test-image + name: Test the image + run: IMAGE="${FINAL_DOCKER_TAG}" ./test.sh + if: steps.docker-build.outputs.skipped != 'true' + # docker.io + - id: docker-io-login + name: Login to docker.io + uses: docker/login-action@v2 + with: + registry: docker.io + username: ${{ secrets.dockerhub_username }} + password: ${{ secrets.dockerhub_password }} + if: steps.docker-build.outputs.skipped != 'true' + # quay.io + - id: quay-io-login + name: Login to Quay.io + uses: docker/login-action@v2 + with: + registry: quay.io + username: ${{ secrets.quayio_username }} + password: ${{ secrets.quayio_password }} + if: steps.docker-build.outputs.skipped != 'true' + # ghcr.io + - id: ghcr-io-login + name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + if: steps.docker-build.outputs.skipped != 'true' + - id: build-and-push + name: Push the image + run: ${{ matrix.build_cmd }} --push + if: steps.docker-build.outputs.skipped != 'true' + env: + BUILDX_PLATFORM: ${{ matrix.platform }} + BUILDX_BUILDER_NAME: ${{ steps.buildx-setup.outputs.name }} diff --git a/.yamllint.yaml b/.yamllint.yaml new file mode 100644 index 0000000..50d6af7 --- /dev/null +++ b/.yamllint.yaml @@ -0,0 +1,5 @@ +--- + +rules: + line-length: + max: 120 diff --git a/build-functions/docker-functions.sh b/build-functions/docker-functions.sh deleted file mode 100644 index 3d947ab..0000000 --- a/build-functions/docker-functions.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -push_image_to_registry() { - local target_tag=$1 - echo "⏫ Pushing '${target_tag}'" - $DRY docker push "${target_tag}" - echo "✅ Finished pushing the Docker image '${target_tag}'." -} diff --git a/build.sh b/build.sh index fbf102d..18a5645 100755 --- a/build.sh +++ b/build.sh @@ -6,10 +6,9 @@ echo "▶️ $0 $*" set -e if [ "${1}x" == "x" ] || [ "${1}" == "--help" ] || [ "${1}" == "-h" ]; then - echo "Usage: ${0} [--push|--push-only]" + echo "Usage: ${0} [--push]" echo " branch The branch or tag to build. Required." echo " --push Pushes the built Docker image to the registry." - echo " --push-only Only pushes the Docker image to the registry, but does not build it." echo "" echo "You can use the following ENV variables to customize the build:" echo " SRC_ORG Which fork of netbox to use (i.e. github.com/\${SRC_ORG}/\${SRC_REPO})." @@ -30,15 +29,10 @@ if [ "${1}x" == "x" ] || [ "${1}" == "--help" ] || [ "${1}" == "-h" ]; then echo " When =master: latest" echo " When =develop: snapshot" echo " Else: same as " - echo " DOCKER_REGISTRY The Docker repository's registry (i.e. '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}'')" + echo " IMAGE_NAMES The names used for the image including the registry" echo " Used for tagging the image." - echo " Default: docker.io" - echo " DOCKER_ORG The Docker repository's organisation (i.e. '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}'')" - echo " Used for tagging the image." - echo " Default: netboxcommunity" - echo " DOCKER_REPO The Docker repository's name (i.e. '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}'')" - echo " Used for tagging the image." - echo " Default: netbox" + echo " Default: docker.io/netboxcommunity/netbox" + echo " Example: 'docker.io/netboxcommunity/netbox quay.io/netboxcommunity/netbox'" echo " DOCKER_TAG The name of the tag which is applied to the image." echo " Useful for pushing into another registry than hub.docker.com." echo " Default: \${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}:\${TAG}" @@ -50,9 +44,24 @@ if [ "${1}x" == "x" ] || [ "${1}" == "--help" ] || [ "${1}" == "-h" ]; then echo " Default: Dockerfile" echo " DOCKER_FROM The base image to use." echo " Default: 'debian:11-slim'" - echo " DOCKER_TARGET A specific target to build." - echo " It's currently not possible to pass multiple targets." - echo " Default: main" + echo " BUILDX_PLATFORMS" + echo " Specifies the platform(s) to build the image for." + echo " Example: 'linux/amd64,linux/arm64'" + echo " Default: 'linux/amd64'" + echo " BUILDX_BUILDER_NAME" + echo " If defined, the image build will be assigned to the given builder." + echo " If you specify this variable, make sure that the builder exists." + echo " If this value is not defined, a new builx builder with the directory name of the" + echo " current directory (i.e. '$(basename "${PWD}")') is created." + echo " Example: 'clever_lovelace'" + echo " Default: undefined" + echo " BUILDX_REMOVE_BUILDER" + echo " If defined (and only if BUILDX_BUILDER_NAME is undefined)," + echo " then the buildx builder created by this script will be removed after use." + echo " This is useful if you build NetBox Docker on an automated system that does" + echo " not manage the builders for you." + echo " Example: 'on'" + echo " Default: undefined" echo " HTTP_PROXY The proxy to use for http requests." echo " Example: http://proxy.domain.tld:3128" echo " Default: undefined" @@ -97,6 +106,9 @@ fi source ./build-functions/gh-functions.sh +IMAGE_NAMES="${IMAGE_NAMES-docker.io/netboxcommunity/netbox}" +IFS=' ' read -ra IMAGE_NAMES <<<"${IMAGE_NAMES}" + ### # Enabling dry-run mode ### @@ -220,188 +232,194 @@ develop) esac ### -# Determine targets to build +# composing the final TARGET_DOCKER_TAG ### -DEFAULT_DOCKER_TARGETS=("main") -DOCKER_TARGETS=("${DOCKER_TARGET:-"${DEFAULT_DOCKER_TARGETS[@]}"}") -echo "🏭 Building the following targets:" "${DOCKER_TARGETS[@]}" +TARGET_DOCKER_TAG="${DOCKER_TAG-${TAG}}" +TARGET_DOCKER_TAG_PROJECT="${TARGET_DOCKER_TAG}-${PROJECT_VERSION}" +### +# composing the additional DOCKER_SHORT_TAG, +# i.e. "v2.6.1" becomes "v2.6", +# which is only relevant for version tags +# Also let "latest" follow the highest version +### +if [[ "${TAG}" =~ ^v([0-9]+)\.([0-9]+)\.[0-9]+$ ]]; then + MAJOR=${BASH_REMATCH[1]} + MINOR=${BASH_REMATCH[2]} + + TARGET_DOCKER_SHORT_TAG="${DOCKER_SHORT_TAG-v${MAJOR}.${MINOR}}" + TARGET_DOCKER_LATEST_TAG="latest" + TARGET_DOCKER_SHORT_TAG_PROJECT="${TARGET_DOCKER_SHORT_TAG}-${PROJECT_VERSION}" + TARGET_DOCKER_LATEST_TAG_PROJECT="${TARGET_DOCKER_LATEST_TAG}-${PROJECT_VERSION}" +fi + +IMAGE_NAME_TAGS=() +for IMAGE_NAME in "${IMAGE_NAMES[@]}"; do + IMAGE_NAME_TAGS+=("${IMAGE_NAME}:${TARGET_DOCKER_TAG}") + IMAGE_NAME_TAGS+=("${IMAGE_NAME}:${TARGET_DOCKER_TAG_PROJECT}") +done +if [ -n "${TARGET_DOCKER_SHORT_TAG}" ]; then + for IMAGE_NAME in "${IMAGE_NAMES[@]}"; do + IMAGE_NAME_TAGS+=("${IMAGE_NAME}:${TARGET_DOCKER_SHORT_TAG}") + IMAGE_NAME_TAGS+=("${IMAGE_NAME}:${TARGET_DOCKER_SHORT_TAG_PROJECT}") + IMAGE_NAME_TAGS+=("${IMAGE_NAME}:${TARGET_DOCKER_LATEST_TAG}") + IMAGE_NAME_TAGS+=("${IMAGE_NAME}:${TARGET_DOCKER_LATEST_TAG_PROJECT}") + done +fi + +gh_env "FINAL_DOCKER_TAG=${IMAGE_NAME_TAGS[0]}" + +### +# Checking if the build is necessary, +# meaning build only if one of those values changed: +# - base image digest +# - netbox git ref (Label: netbox.git-ref) +# - netbox-docker git ref (Label: org.opencontainers.image.revision) +### +# Load information from registry (only for docker.io) +SHOULD_BUILD="false" +BUILD_REASON="" +if [ -z "${GH_ACTION}" ]; then + # Asuming non Github builds should always proceed + SHOULD_BUILD="true" + BUILD_REASON="${BUILD_REASON} interactive" +elif [[ "${IMAGE_NAME_TAGS[0]}" = docker.io* ]]; then + source ./build-functions/get-public-image-config.sh + IFS=':' read -ra DOCKER_FROM_SPLIT <<<"${DOCKER_FROM}" + if ! [[ ${DOCKER_FROM_SPLIT[0]} =~ .*/.* ]]; then + # Need to use "library/..." for images the have no two part name + DOCKER_FROM_SPLIT[0]="library/${DOCKER_FROM_SPLIT[0]}" + fi + IFS='/' read -ra ORG_REPO <<<"${IMAGE_NAMES[0]}" + echo "Checking labels for '${ORG_REPO[1]}' and '${ORG_REPO[2]}'" + BASE_LAST_LAYER=$(get_image_last_layer "${DOCKER_FROM_SPLIT[0]}" "${DOCKER_FROM_SPLIT[1]}") + mapfile -t IMAGES_LAYERS_OLD < <(get_image_layers "${ORG_REPO[1]}"/"${ORG_REPO[2]}" "${TAG}") + NETBOX_GIT_REF_OLD=$(get_image_label netbox.git-ref "${ORG_REPO[1]}"/"${ORG_REPO[2]}" "${TAG}") + GIT_REF_OLD=$(get_image_label org.opencontainers.image.revision "${ORG_REPO[1]}"/"${ORG_REPO[2]}" "${TAG}") + + if ! printf '%s\n' "${IMAGES_LAYERS_OLD[@]}" | grep -q -P "^${BASE_LAST_LAYER}\$"; then + SHOULD_BUILD="true" + BUILD_REASON="${BUILD_REASON} debian" + fi + if [ "${NETBOX_GIT_REF}" != "${NETBOX_GIT_REF_OLD}" ]; then + SHOULD_BUILD="true" + BUILD_REASON="${BUILD_REASON} netbox" + fi + if [ "${GIT_REF}" != "${GIT_REF_OLD}" ]; then + SHOULD_BUILD="true" + BUILD_REASON="${BUILD_REASON} netbox-docker" + fi +else + SHOULD_BUILD="true" + BUILD_REASON="${BUILD_REASON} no-check" +fi + +if [ "${SHOULD_BUILD}" != "true" ]; then + echo "Build skipped because sources didn't change" + echo "::set-output name=skipped::true" + exit 0 # Nothing to do -> exit +else + gh_echo "::set-output name=skipped::false" +fi gh_echo "::endgroup::" ### -# Build each target +# Build the image ### -export DOCKER_BUILDKIT=${DOCKER_BUILDKIT-1} -for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do - gh_echo "::group::🏗 Building the target '${DOCKER_TARGET}'" - echo "🏗 Building the target '${DOCKER_TARGET}'" - - ### - # composing the final TARGET_DOCKER_TAG - ### - TARGET_DOCKER_TAG="${DOCKER_TAG-${DOCKER_REGISTRY}/${DOCKER_ORG}/${DOCKER_REPO}:${TAG}}" - if [ "${DOCKER_TARGET}" != "main" ]; then - TARGET_DOCKER_TAG="${TARGET_DOCKER_TAG}-${DOCKER_TARGET}" - fi - TARGET_DOCKER_TAG_PROJECT="${TARGET_DOCKER_TAG}-${PROJECT_VERSION}" - - gh_env "FINAL_DOCKER_TAG=${TARGET_DOCKER_TAG_PROJECT}" - gh_echo "::set-output name=skipped::false" - - ### - # composing the additional DOCKER_SHORT_TAG, - # i.e. "v2.6.1" becomes "v2.6", - # which is only relevant for version tags - # Also let "latest" follow the highest version - ### - if [[ "${TAG}" =~ ^v([0-9]+)\.([0-9]+)\.[0-9]+$ ]]; then - MAJOR=${BASH_REMATCH[1]} - MINOR=${BASH_REMATCH[2]} - - TARGET_DOCKER_SHORT_TAG="${DOCKER_SHORT_TAG-${DOCKER_REGISTRY}/${DOCKER_ORG}/${DOCKER_REPO}:v${MAJOR}.${MINOR}}" - TARGET_DOCKER_LATEST_TAG="${DOCKER_REGISTRY}/${DOCKER_ORG}/${DOCKER_REPO}:latest" - - if [ "${DOCKER_TARGET}" != "main" ]; then - TARGET_DOCKER_SHORT_TAG="${TARGET_DOCKER_SHORT_TAG}-${DOCKER_TARGET}" - TARGET_DOCKER_LATEST_TAG="${TARGET_DOCKER_LATEST_TAG}-${DOCKER_TARGET}" - fi - - TARGET_DOCKER_SHORT_TAG_PROJECT="${TARGET_DOCKER_SHORT_TAG}-${PROJECT_VERSION}" - TARGET_DOCKER_LATEST_TAG_PROJECT="${TARGET_DOCKER_LATEST_TAG}-${PROJECT_VERSION}" - fi - - ### - # Proceeding to buils stage, except if `--push-only` is passed - ### - if [ "${2}" != "--push-only" ]; then - ### - # Checking if the build is necessary, - # meaning build only if one of those values changed: - # - base image digest - # - netbox git ref (Label: netbox.git-ref) - # - netbox-docker git ref (Label: org.opencontainers.image.revision) - ### - # Load information from registry (only for docker.io) - SHOULD_BUILD="false" - BUILD_REASON="" - if [ -z "${GH_ACTION}" ]; then - # Asuming non Github builds should always proceed - SHOULD_BUILD="true" - BUILD_REASON="${BUILD_REASON} interactive" - elif [ "$DOCKER_REGISTRY" = "docker.io" ]; then - source ./build-functions/get-public-image-config.sh - IFS=':' read -ra DOCKER_FROM_SPLIT <<<"${DOCKER_FROM}" - if ! [[ ${DOCKER_FROM_SPLIT[0]} =~ .*/.* ]]; then - # Need to use "library/..." for images the have no two part name - DOCKER_FROM_SPLIT[0]="library/${DOCKER_FROM_SPLIT[0]}" - fi - BASE_LAST_LAYER=$(get_image_last_layer "${DOCKER_FROM_SPLIT[0]}" "${DOCKER_FROM_SPLIT[1]}") - mapfile -t IMAGES_LAYERS_OLD < <(get_image_layers "${DOCKER_ORG}"/"${DOCKER_REPO}" "${TAG}") - NETBOX_GIT_REF_OLD=$(get_image_label netbox.git-ref "${DOCKER_ORG}"/"${DOCKER_REPO}" "${TAG}") - GIT_REF_OLD=$(get_image_label org.opencontainers.image.revision "${DOCKER_ORG}"/"${DOCKER_REPO}" "${TAG}") - - if ! printf '%s\n' "${IMAGES_LAYERS_OLD[@]}" | grep -q -P "^${BASE_LAST_LAYER}\$"; then - SHOULD_BUILD="true" - BUILD_REASON="${BUILD_REASON} debian" - fi - if [ "${NETBOX_GIT_REF}" != "${NETBOX_GIT_REF_OLD}" ]; then - SHOULD_BUILD="true" - BUILD_REASON="${BUILD_REASON} netbox" - fi - if [ "${GIT_REF}" != "${GIT_REF_OLD}" ]; then - SHOULD_BUILD="true" - BUILD_REASON="${BUILD_REASON} netbox-docker" - fi - else - SHOULD_BUILD="true" - BUILD_REASON="${BUILD_REASON} no-check" - fi - ### - # Composing all arguments for `docker build` - ### - DOCKER_BUILD_ARGS=( - --pull - --target "${DOCKER_TARGET}" - -f "${DOCKERFILE}" - -t "${TARGET_DOCKER_TAG}" - -t "${TARGET_DOCKER_TAG_PROJECT}" - ) - if [ -n "${TARGET_DOCKER_SHORT_TAG}" ]; then - DOCKER_BUILD_ARGS+=(-t "${TARGET_DOCKER_SHORT_TAG}") - DOCKER_BUILD_ARGS+=(-t "${TARGET_DOCKER_SHORT_TAG_PROJECT}") - DOCKER_BUILD_ARGS+=(-t "${TARGET_DOCKER_LATEST_TAG}") - DOCKER_BUILD_ARGS+=(-t "${TARGET_DOCKER_LATEST_TAG_PROJECT}") - fi - - # --label - DOCKER_BUILD_ARGS+=( - --label "netbox.original-tag=${TARGET_DOCKER_TAG_PROJECT}" - --label "org.opencontainers.image.created=${BUILD_DATE}" - --label "org.opencontainers.image.version=${PROJECT_VERSION}" - ) - if [ -d ".git" ]; then - DOCKER_BUILD_ARGS+=( - --label "org.opencontainers.image.revision=${GIT_REF}" - ) - fi - if [ -d "${NETBOX_PATH}/.git" ]; then - DOCKER_BUILD_ARGS+=( - --label "netbox.git-branch=${NETBOX_GIT_BRANCH}" - --label "netbox.git-ref=${NETBOX_GIT_REF}" - --label "netbox.git-url=${NETBOX_GIT_URL}" - ) - fi - if [ -n "${BUILD_REASON}" ]; then - BUILD_REASON=$(sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<<"$BUILD_REASON") - DOCKER_BUILD_ARGS+=(--label "netbox.build-reason=${BUILD_REASON}") - fi - - # --build-arg - DOCKER_BUILD_ARGS+=(--build-arg "NETBOX_PATH=${NETBOX_PATH}") - - if [ -n "${DOCKER_FROM}" ]; then - DOCKER_BUILD_ARGS+=(--build-arg "FROM=${DOCKER_FROM}") - fi - # shellcheck disable=SC2031 - if [ -n "${HTTP_PROXY}" ]; then - DOCKER_BUILD_ARGS+=(--build-arg "http_proxy=${HTTP_PROXY}") - DOCKER_BUILD_ARGS+=(--build-arg "https_proxy=${HTTPS_PROXY}") - fi - if [ -n "${NO_PROXY}" ]; then - DOCKER_BUILD_ARGS+=(--build-arg "no_proxy=${NO_PROXY}") - fi - - ### - # Building the docker image - ### - if [ "${SHOULD_BUILD}" == "true" ]; then - echo "🐳 Building the Docker image '${TARGET_DOCKER_TAG_PROJECT}'." - echo " Build reason set to: ${BUILD_REASON}" - $DRY docker build "${DOCKER_BUILD_ARGS[@]}" . - echo "✅ Finished building the Docker images '${TARGET_DOCKER_TAG_PROJECT}'" - echo "🔎 Inspecting labels on '${TARGET_DOCKER_TAG_PROJECT}'" - $DRY docker inspect "${TARGET_DOCKER_TAG_PROJECT}" --format "{{json .Config.Labels}}" | jq - else - echo "Build skipped because sources didn't change" - echo "::set-output name=skipped::true" - fi - fi - - ### - # Pushing the docker images if either `--push` or `--push-only` are passed - ### - if [ "${2}" == "--push" ] || [ "${2}" == "--push-only" ]; then - source ./build-functions/docker-functions.sh - push_image_to_registry "${TARGET_DOCKER_TAG}" - push_image_to_registry "${TARGET_DOCKER_TAG_PROJECT}" - - if [ -n "${TARGET_DOCKER_SHORT_TAG}" ]; then - push_image_to_registry "${TARGET_DOCKER_SHORT_TAG}" - push_image_to_registry "${TARGET_DOCKER_SHORT_TAG_PROJECT}" - push_image_to_registry "${TARGET_DOCKER_LATEST_TAG}" - push_image_to_registry "${TARGET_DOCKER_LATEST_TAG_PROJECT}" - fi - fi - - gh_echo "::endgroup::" +gh_echo "::group::🏗 Building the image" +### +# Composing all arguments for `docker build` +### +DOCKER_BUILD_ARGS=( + --pull + --target main + -f "${DOCKERFILE}" +) +for IMAGE_NAME in "${IMAGE_NAME_TAGS[@]}"; do + DOCKER_BUILD_ARGS+=(-t "${IMAGE_NAME}") done + +# --label +DOCKER_BUILD_ARGS+=( + --label "netbox.original-tag=${TARGET_DOCKER_TAG_PROJECT}" + --label "org.opencontainers.image.created=${BUILD_DATE}" + --label "org.opencontainers.image.version=${PROJECT_VERSION}" +) +if [ -d ".git" ] && [ -z "${SKIP_GIT}" ]; then + DOCKER_BUILD_ARGS+=( + --label "org.opencontainers.image.revision=${GIT_REF}" + ) +fi +if [ -d "${NETBOX_PATH}/.git" ] && [ -z "${SKIP_GIT}" ]; then + DOCKER_BUILD_ARGS+=( + --label "netbox.git-branch=${NETBOX_GIT_BRANCH}" + --label "netbox.git-ref=${NETBOX_GIT_REF}" + --label "netbox.git-url=${NETBOX_GIT_URL}" + ) +fi +if [ -n "${BUILD_REASON}" ]; then + BUILD_REASON=$(sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<<"$BUILD_REASON") + DOCKER_BUILD_ARGS+=(--label "netbox.build-reason=${BUILD_REASON}") +fi + +# --build-arg +DOCKER_BUILD_ARGS+=(--build-arg "NETBOX_PATH=${NETBOX_PATH}") + +if [ -n "${DOCKER_FROM}" ]; then + DOCKER_BUILD_ARGS+=(--build-arg "FROM=${DOCKER_FROM}") +fi +# shellcheck disable=SC2031 +if [ -n "${HTTP_PROXY}" ]; then + DOCKER_BUILD_ARGS+=(--build-arg "http_proxy=${HTTP_PROXY}") + DOCKER_BUILD_ARGS+=(--build-arg "https_proxy=${HTTPS_PROXY}") +fi +if [ -n "${NO_PROXY}" ]; then + DOCKER_BUILD_ARGS+=(--build-arg "no_proxy=${NO_PROXY}") +fi + +DOCKER_BUILD_ARGS+=(--platform "${BUILDX_PLATFORM-linux/amd64}") +if [ "${2}" == "--push" ]; then + # output type=docker does not work with pushing + DOCKER_BUILD_ARGS+=( + --output=type=image + --push + ) +else + DOCKER_BUILD_ARGS+=( + --output=type=docker + ) +fi + +### +# Building the docker image +### +if [ -z "${BUILDX_BUILDER_NAME}" ]; then + BUILDX_BUILDER_NAME="$(basename "${PWD}")" +fi +if ! docker buildx ls | grep --quiet --word-regexp "${BUILDX_BUILDER_NAME}"; then + echo "👷 Creating new Buildx Builder '${BUILDX_BUILDER_NAME}'" + $DRY docker buildx create --name "${BUILDX_BUILDER_NAME}" + BUILDX_BUILDER_CREATED="yes" +fi + +echo "🐳 Building the Docker image '${TARGET_DOCKER_TAG_PROJECT}'." +echo " Build reason set to: ${BUILD_REASON}" +$DRY docker buildx \ + --builder "${BUILDX_BUILDER_NAME}" \ + build \ + "${DOCKER_BUILD_ARGS[@]}" \ + . +echo "✅ Finished building the Docker images" +gh_echo "::endgroup::" # End group for Build + +gh_echo "::group::🏗 Image Labels" +echo "🔎 Inspecting labels on '${IMAGE_NAME_TAGS[0]}'" +$DRY docker inspect "${IMAGE_NAME_TAGS[0]}" --format "{{json .Config.Labels}}" | jq +gh_echo "::endgroup::" + +gh_echo "::group::🏗 Clean up" +if [ -n "${BUILDX_REMOVE_BUILDER}" ] && [ "${BUILDX_BUILDER_CREATED}" == "yes" ]; then + echo "👷 Removing Buildx Builder '${BUILDX_BUILDER_NAME}'" + $DRY docker buildx rm "${BUILDX_BUILDER_NAME}" +fi +gh_echo "::endgroup::"