From 59c6cfc77491db1c500d313c32f5fc85bda18269 Mon Sep 17 00:00:00 2001 From: Nicholas McDonnell <50747025+mcdonnnj@users.noreply.github.com> Date: Sun, 5 Jan 2025 07:15:43 -0500 Subject: [PATCH 1/4] Ensure the `bump-version` script can bump prereleases Currently there is a bug in the script's logic that prevents you from running `./bump-version prerelease` to bump _just_ the prerelease. This is due to faulty checking logic to ensure expected behavior when combining bump commands. --- bump-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bump-version b/bump-version index 414552a..324fea9 100755 --- a/bump-version +++ b/bump-version @@ -125,7 +125,7 @@ if [ -n "$label" ] && [ "$with_prerelease" = false ] && [[ ! " ${commands_with_l invalid_option "Setting the label is only allowed for the following commands: ${commands_with_label[*]}" fi -if [ "$with_prerelease" = true ] && [[ ! " ${commands_with_prerelease[*]} " =~ [[:space:]]${bump_part}[[:space:]] ]]; then +if [ "$with_prerelease" = true ] && [ -n "$bump_part" ] && [[ ! " ${commands_with_prerelease[*]} " =~ [[:space:]]${bump_part}[[:space:]] ]]; then invalid_option "Changing the prerelease is only allowed in conjunction with the following commands: ${commands_with_prerelease[*]}" fi From bb998ddafd75f789eb723d086eb5fdab3226d2da Mon Sep 17 00:00:00 2001 From: Nicholas McDonnell <50747025+mcdonnnj@users.noreply.github.com> Date: Sun, 5 Jan 2025 06:53:13 -0500 Subject: [PATCH 2/4] Stop using an environment variable to store platforms Instead of using the CSV style in an environment variable we can instead use a newline delimited list directly for the `platforms` input. Since the environment variable is only used to provide a value for the `platforms` input there should be no issue with this change. --- .github/workflows/build.yml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 612806d..f14bae0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,8 +40,6 @@ env: BUILDX_CACHE_DIR: ~/.cache/buildx IMAGE_NAME: cisagov/example PIP_CACHE_DIR: ~/.cache/pip - PLATFORMS: "linux/amd64,linux/arm/v6,linux/arm/v7,\ - linux/arm64,linux/ppc64le,linux/s390x" PRE_COMMIT_CACHE_DIR: ~/.cache/pre-commit RUN_TMATE: ${{ secrets.RUN_TMATE }} TERRAFORM_DOCS_REPO_BRANCH_NAME: improvement/support_atx_closed_markdown_headers @@ -452,12 +450,12 @@ jobs: uses: mxschmitt/action-tmate@v3 if: env.RUN_TMATE build-push-all: - # Builds the final set of images for each of the platforms listed in - # PLATFORMS environment variable. These images are tagged with the Docker - # tags calculated in the "prepare" job and pushed to Docker Hub and the - # GitHub Container Registry. The contents of README.md are pushed as the - # image's description to Docker Hub. This job is skipped when the - # triggering event is a pull request. + # Builds the final set of images for each of the platforms specified in the + # "platforms" input for the docker/build-push-action Action. These images + # are tagged with the Docker tags calculated in the "prepare" job and + # pushed to Docker Hub and the GitHub Container Registry. The contents of + # README.md are pushed as the image's description to Docker Hub. This job + # is skipped when the triggering event is a pull request. if: github.event_name != 'pull_request' name: Build and push all platforms needs: @@ -541,7 +539,13 @@ jobs: org.opencontainers.image.version=${{ needs.prepare.outputs.source_version }}" - platforms: ${{ env.PLATFORMS }} + platforms: | + linux/amd64 + linux/arm/v6 + linux/arm/v7 + linux/arm64 + linux/ppc64le + linux/s390x # Uncomment the following option if you are building an image for use # on Google Cloud Run or AWS Lambda. The current default image output # is unable to run on either. Please see the following issue for more From ec3b18edebef063f7534c4002d44a4521d8c9725 Mon Sep 17 00:00:00 2001 From: Nicholas McDonnell <50747025+mcdonnnj@users.noreply.github.com> Date: Wed, 8 Jan 2025 14:21:10 -0500 Subject: [PATCH 3/4] Use the docker/metadata-action Action to generate metadata Switch to using the docker/metadata-action GitHub Action to generate Docker image metadata. This replaces manually specifying the labels and calculating appropriate tags. This approach will both be easier as well as eliminate some of the issues we've had with manually calculating the image tags. --- .github/dependabot.yml | 2 +- .github/workflows/build.yml | 158 +++++------------------------------- 2 files changed, 23 insertions(+), 137 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d01227a..1128608 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -29,10 +29,10 @@ updates: - dependency-name: step-security/harden-runner # Managed by cisagov/skeleton-docker # - dependency-name: actions/download-artifact - # - dependency-name: actions/github-script # - dependency-name: actions/upload-artifact # - dependency-name: docker/build-push-action # - dependency-name: docker/login-action + # - dependency-name: docker/metadata-action # - dependency-name: docker/setup-buildx-action # - dependency-name: docker/setup-qemu-action # - dependency-name: github/codeql-action diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f14bae0..f15ba5e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -191,54 +191,13 @@ jobs: uses: mxschmitt/action-tmate@v3 if: env.RUN_TMATE prepare: - # Calculates and publishes outputs that are used by other jobs. - # - # Outputs: - # created: - # The current date-time in RFC3339 format. - # repometa: - # The json metadata describing this repository. - # source_version: - # The source version as reported by the `bump-version show` command. - # tags: - # A comma separated list of Docker tags to be applied to the images on - # Docker Hub. The tags will vary depending on: - # - The event that triggered the build. - # - The branch the build is based upon. - # - The git tag the build is based upon. - # - # When a build is based on a git tag of the form `v*.*.*` the image will - # be tagged on Docker Hub with multiple levels of version specificity. - # For example, a git tag of `v1.2.3+a` will generate Docker tags of - # `:1.2.3_a`, `:1.2.3`, `:1.2`, `:1`, and `:latest`. - # - # Builds targeting the default branch will be tagged with `:edge`. - # - # Builds from other branches will be tagged with the branch name. Solidi - # (`/` characters - commonly known as slashes) in branch names are - # replaced with hyphen-minuses (`-` characters) in the Docker tag. For - # more information about the solidus see these links: - # * https://www.compart.com/en/unicode/U+002F - # * https://en.wikipedia.org/wiki/Slash_(punctuation)#Encoding - # - # Builds triggered by a push event are tagged with a short hash in the - # form: sha-12345678 - # - # Builds triggered by a pull request are tagged with the pull request - # number in the form pr-123. - # - # Builds triggered using the GitHub GUI (workflow_dispatch) are tagged - # with the value specified by the user. - # - # Scheduled builds are tagged with `:nightly`. + # Generate Docker image metadata using the docker/metadata-action GitHub Action. name: Prepare build variables needs: - diagnostics outputs: - created: ${{ steps.prep.outputs.created }} - repometa: ${{ steps.repo.outputs.result }} - source_version: ${{ steps.prep.outputs.source_version }} - tags: ${{ steps.prep.outputs.tags }} + labels: ${{ steps.generate-metadata.outputs.labels }} + tags: ${{ steps.generate-metadata.outputs.tags }} permissions: # actions/checkout needs this to fetch code contents: read @@ -254,53 +213,24 @@ jobs: with: egress-policy: audit - uses: actions/checkout@v4 - - name: Gather repository metadata - id: repo - uses: actions/github-script@v7 + - id: generate-metadata + name: Generate Docker image metadata + uses: docker/metadata-action@v5 with: - script: | - const repo = await github.rest.repos.get(context.repo) - return repo.data - - name: Calculate output values - id: prep - run: | - VERSION=noop - SEMVER="^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*))?(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?$" - if [ "${{ github.event_name }}" = "schedule" ]; then - VERSION=nightly - elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - VERSION=${{ github.event.inputs.image-tag }} - elif [[ $GITHUB_REF == refs/tags/* ]]; then - VERSION=${GITHUB_REF#refs/tags/} - elif [[ $GITHUB_REF == refs/heads/* ]]; then - VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g') - if [ "${{ github.event.repository.default_branch }}" = "$VERSION" ]; - then - VERSION=edge - fi - elif [[ $GITHUB_REF == refs/pull/* ]]; then - VERSION=pr-${{ github.event.number }} - fi - if [[ $VERSION =~ $SEMVER ]]; then - VERSION_NO_V=${VERSION#v} - MAJOR="${BASH_REMATCH[1]}" - MINOR="${BASH_REMATCH[2]}" - PATCH="${BASH_REMATCH[3]}" - TAGS="${IMAGE_NAME}:${VERSION_NO_V//+/_},${IMAGE_NAME}:${MAJOR}.${MINOR}.${PATCH},${IMAGE_NAME}:${MAJOR}.${MINOR},${IMAGE_NAME}:${MAJOR},${IMAGE_NAME}:latest" - else - TAGS="${IMAGE_NAME}:${VERSION}" - fi - if [ "${{ github.event_name }}" = "push" ]; then - TAGS="${TAGS},${IMAGE_NAME}:sha-${GITHUB_SHA::8}" - fi - for i in ${TAGS//,/ } - do - TAGS="${TAGS},ghcr.io/${i}" - done - echo "created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT - echo "source_version=$(./bump-version show)" >> $GITHUB_OUTPUT - echo "tags=${TAGS}" >> $GITHUB_OUTPUT - echo tags=${TAGS} + images: | + ${{ env.IMAGE_NAME }} + ghcr.io/${{ env.IMAGE_NAME }} + tags: | + type=edge + type=raw,event=workflow_dispatch,value=${{ github.event.inputs.image-tag }} + type=ref,event=branch + type=ref,event=pr + type=ref,event=tag + type=schedule + type=semver,pattern={{major}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{version}} + type=sha - name: Setup tmate debug session uses: mxschmitt/action-tmate@v3 if: github.event.inputs.remote-shell == 'true' || env.RUN_TMATE @@ -350,29 +280,7 @@ jobs: cache-to: type=local,dest=${{ env.BUILDX_CACHE_DIR }} context: . file: ./Dockerfile - labels: "\ - org.opencontainers.image.created=${{ - needs.prepare.outputs.created }} - - org.opencontainers.image.description=${{ - fromJson(needs.prepare.outputs.repometa).description }} - - org.opencontainers.image.licenses=${{ - fromJson(needs.prepare.outputs.repometa).license.spdx_id }} - - org.opencontainers.image.revision=${{ github.sha }} - - org.opencontainers.image.source=${{ - fromJson(needs.prepare.outputs.repometa).clone_url }} - - org.opencontainers.image.title=${{ - fromJson(needs.prepare.outputs.repometa).name }} - - org.opencontainers.image.url=${{ - fromJson(needs.prepare.outputs.repometa).html_url }} - - org.opencontainers.image.version=${{ - needs.prepare.outputs.source_version }}" + labels: ${{ needs.prepare.outputs.labels }} outputs: type=docker,dest=dist/image.tar # Uncomment the following option if you are building an image for use # on Google Cloud Run or AWS Lambda. The current default image output @@ -516,29 +424,7 @@ jobs: cache-to: type=local,dest=${{ env.BUILDX_CACHE_DIR }} context: . file: ./Dockerfile-x - labels: "\ - org.opencontainers.image.created=${{ - needs.prepare.outputs.created }} - - org.opencontainers.image.description=${{ - fromJson(needs.prepare.outputs.repometa).description }} - - org.opencontainers.image.licenses=${{ - fromJson(needs.prepare.outputs.repometa).license.spdx_id }} - - org.opencontainers.image.revision=${{ github.sha }} - - org.opencontainers.image.source=${{ - fromJson(needs.prepare.outputs.repometa).clone_url }} - - org.opencontainers.image.title=${{ - fromJson(needs.prepare.outputs.repometa).name }} - - org.opencontainers.image.url=${{ - fromJson(needs.prepare.outputs.repometa).html_url }} - - org.opencontainers.image.version=${{ - needs.prepare.outputs.source_version }}" + labels: ${{ needs.prepare.outputs.labels }} platforms: | linux/amd64 linux/arm/v6 From 5698c1713675d8a650864a65eb9a05d7bc0a6593 Mon Sep 17 00:00:00 2001 From: Nicholas McDonnell <50747025+mcdonnnj@users.noreply.github.com> Date: Fri, 10 Jan 2025 06:05:24 -0500 Subject: [PATCH 4/4] Only check the version label on releases Update the test configuration to only check the org.opencontainers.image.version label on releases. We must make this change because the docker/metadata-action will only populate the label with an appropriate value on a release. Otherwise it will be the branch that is sourced when building the image. --- tests/container_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/container_test.py b/tests/container_test.py index bddee4b..449c117 100644 --- a/tests/container_test.py +++ b/tests/container_test.py @@ -77,6 +77,9 @@ def test_log_version(dockerc, project_version, version_container): ), f"Container version output to log does not match project version file {VERSION_FILE}" +@pytest.mark.skipif( + RELEASE_TAG in [None, ""], reason="this is not a release (RELEASE_TAG not set)" +) def test_container_version_label_matches(project_version, version_container): """Verify the container version label is the correct version.""" assert (