Merge pull request #89 from Cisco-Talos/dev #339
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| # split build based on https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners | |
| name: "Build container" | |
| "on": | |
| workflow_dispatch: | |
| push: | |
| pull_request: | |
| # Minimal workflow-level permissions: only read code. | |
| # publish-capable permissions are granted at the job level. | |
| permissions: | |
| contents: read | |
| env: | |
| PLATFORM_PAIR: linux_amd64 # this should be overridden later | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| permissions: | |
| packages: write | |
| contents: read | |
| strategy: | |
| fail-fast: true | |
| matrix: | |
| include: | |
| # https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories | |
| - runner: ubuntu-latest | |
| platform: linux/amd64 | |
| # TODO: enable the ARM runner when the repository is public | |
| - runner: ubuntu-latest | |
| platform: linux/arm64 | |
| runs-on: ${{matrix.runner}} | |
| steps: | |
| - name: Prepare | |
| run: | | |
| platform=${{ matrix.platform }} | |
| echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: lowercase repo name | |
| run: | | |
| echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV} | |
| echo "REGISTRY_IMAGE=ghcr.io/${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV} | |
| - name: Docker meta | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY_IMAGE }} | |
| tags: | | |
| # set latest tag for main branch | |
| type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| if: ${{ matrix.platform == 'linux/arm64' }} | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to GitHub Container Registry | |
| # Only log in when we are actually going to push (main branch push events only) | |
| if: ${{ github.event_name == 'push' && github.ref == format('refs/heads/{0}', 'main') }} | |
| # https://github.com/docker/login-action/#github-container-registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build (no push) | |
| # PRs and non-main branches: build only to validate the image, do not push | |
| if: ${{ github.event_name != 'push' || github.ref != format('refs/heads/{0}', 'main') }} | |
| uses: docker/build-push-action@v6 | |
| with: | |
| labels: ${{ steps.meta.outputs.labels }} | |
| platforms: ${{ matrix.platform }} | |
| push: false | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Build and push | |
| # Only push on main branch push events | |
| if: ${{ github.event_name == 'push' && github.ref == format('refs/heads/{0}', 'main') }} | |
| id: build | |
| uses: docker/build-push-action@v6 | |
| with: | |
| labels: ${{ steps.meta.outputs.labels }} | |
| platforms: ${{ matrix.platform }} | |
| outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Export digest | |
| if: ${{ github.event_name == 'push' && github.ref == format('refs/heads/{0}', 'main') }} | |
| run: | | |
| mkdir -p /tmp/digests | |
| digest="${{ steps.build.outputs.digest }}" | |
| touch "/tmp/digests/${digest#sha256:}" | |
| - name: Upload digest | |
| if: ${{ github.event_name == 'push' && github.ref == format('refs/heads/{0}', 'main') }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: digests-${{ env.PLATFORM_PAIR }} | |
| path: /tmp/digests/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| merge: | |
| # Only run the merge/publish job on main branch push events | |
| if: ${{ github.event_name == 'push' && github.ref == format('refs/heads/{0}', 'main') }} | |
| runs-on: ubuntu-latest | |
| needs: | |
| - build | |
| permissions: | |
| packages: write | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Download digests | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: /tmp/digests | |
| pattern: digests-* | |
| merge-multiple: true | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: lowercase repo name | |
| run: | | |
| echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV} | |
| echo "REGISTRY_IMAGE=ghcr.io/${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV} | |
| - name: Docker meta | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY_IMAGE }} | |
| tags: | | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| type=raw,value=${{ github.ref }},enable=true | |
| - name: Login to GitHub Container Registry | |
| # https://github.com/docker/login-action/#github-container-registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Create manifest list and push | |
| # Inline manifest creation: avoids executing a PR-controlled script | |
| # in a job that holds packages:write permission. | |
| working-directory: /tmp/digests | |
| run: | | |
| python3 << 'PYEOF' | |
| import json | |
| import os | |
| import subprocess | |
| import sys | |
| registry_image = os.environ["REGISTRY_IMAGE"] | |
| docker_meta = json.loads(os.environ["DOCKER_METADATA_OUTPUT_JSON"]) | |
| tags = [arg for tag in docker_meta.get("tags", []) for arg in ("-t", tag)] | |
| digests = [ | |
| f"{registry_image}@sha256:{digest}" | |
| for digest in os.listdir(".") | |
| if os.path.isfile(digest) | |
| ] | |
| if not digests: | |
| raise SystemExit("Error: No digest files found in current directory") | |
| if not tags: | |
| raise SystemExit("Error: No tags found in metadata") | |
| subprocess.run( | |
| ["docker", "buildx", "imagetools", "create", *tags, *digests], | |
| check=True, | |
| ) | |
| PYEOF | |
| env: | |
| REGISTRY_IMAGE: ${{ env.REGISTRY_IMAGE }} | |
| DOCKER_METADATA_OUTPUT_JSON: ${{ env.DOCKER_METADATA_OUTPUT_JSON }} | |
| - name: Inspect image | |
| run: | | |
| docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} |