Build and Publish Docker Image #1508
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
| name: Build and Publish Docker Image | |
| # This workflow uses actions that are not certified by GitHub. | |
| # They are provided by a third-party and are governed by | |
| # separate terms of service, privacy policy, and support | |
| # documentation. | |
| on: | |
| schedule: | |
| - cron: '0 10 * * *' | |
| # If any commit message in your push or the HEAD commit of your PR contains the strings | |
| # [skip ci], [ci skip], [no ci], [skip actions], or [actions skip] | |
| # workflows triggered on the push or pull_request events will be skipped. | |
| # https://github.blog/changelog/2021-02-08-github-actions-skip-pull-request-and-push-workflows-with-skip-ci/ | |
| push: | |
| branches: [ master ] | |
| # Publish semver tags as releases. | |
| tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] | |
| # If any commit message in your push or the HEAD commit of your PR contains the strings | |
| # [skip ci], [ci skip], [no ci], [skip actions], or [actions skip] | |
| # workflows triggered on the push or pull_request events will be skipped. | |
| # https://github.blog/changelog/2021-02-08-github-actions-skip-pull-request-and-push-workflows-with-skip-ci/ | |
| pull_request: | |
| branches: [ master ] | |
| env: | |
| # https://hub.docker.com/r/athenz/authorization-proxy/tags | |
| DOCKER_REGISTRY_URL: docker.io | |
| DOCKER_REGISTRY_ORG: athenz | |
| DOCKER_REGISTRY_IMAGE: authorization-proxy | |
| # DOCKER_REGISTRY_USER: values for docker login is stored in repository variables | |
| # DOCKER_REGISTRY_TOKEN_NAME: values for docker login is stored in repository variables | |
| TAGS_CONFIG: | | |
| # If branch is master, main or default branch, push the latest tag image: | |
| type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }} | |
| type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'master') }} | |
| type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} | |
| # If the event is a tag release in semver syntax, push the latest tag image: | |
| type=semver,pattern=latest | |
| # If it is PR version, push the pr-<pr-number> tag image: | |
| type=ref,event=pr | |
| type=semver,pattern=v{{version}} | |
| # Any cron builds (scheduled workflows) push the nightly tag image: | |
| type=schedule,pattern=nightly | |
| jobs: | |
| set_matrix: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.set.outputs.matrix }} | |
| suffixes: ${{ steps.set.outputs.suffixes }} | |
| steps: | |
| - id: set | |
| run: | | |
| # We define BUILD_MATRIX so that we have multiple platform supported, | |
| # maybe Windows as well in the future: | |
| MATRIX_JSON='{ | |
| "include": [ | |
| { "platform": "linux/amd64", "runner": "ubuntu-latest", "suffix": "-amd64" }, | |
| { "platform": "linux/arm64", "runner": "ubuntu-24.04-arm", "suffix": "-arm64" } | |
| ] | |
| }' | |
| # Store JSON data: | |
| echo "matrix=$(echo "$MATRIX_JSON" | jq -c .)" >> $GITHUB_OUTPUT | |
| # Store Suffix list: | |
| echo "suffixes=$(echo "$MATRIX_JSON" | jq -r '.include[].suffix' | xargs)" >> $GITHUB_OUTPUT | |
| build: | |
| needs: set_matrix | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJson(needs.set_matrix.outputs.matrix) }} | |
| permissions: | |
| actions: none | |
| checks: none | |
| contents: read | |
| deployments: none | |
| issues: none | |
| discussions: none | |
| packages: write # for ghcr read permission | |
| pull-requests: none | |
| repository-projects: none | |
| security-events: none | |
| statuses: none | |
| steps: | |
| # A GitHub Action to expose useful environment variables. | |
| # https://github.com/FranzDiebold/github-env-vars-action | |
| - | |
| name: GitHub Environment Variables Action | |
| id: env | |
| # uses: https://github.com/FranzDiebold/github-env-vars-action/tags | |
| uses: FranzDiebold/github-env-vars-action@v2 | |
| # This action checks-out your repository under $GITHUB_WORKSPACE, so your workflow can access it. | |
| # https://github.com/actions/checkout | |
| - | |
| name: Checkout repository | |
| id: checkout | |
| # You may pin to the exact commit or the version. | |
| # uses: https://github.com/actions/checkout/tags | |
| uses: actions/checkout@v4 | |
| # This action sets up a go environment for use in actions by: | |
| # - Optionally downloading and caching a version of Go by version and adding to PATH. | |
| # - Registering problem matchers for error output. | |
| # https://github.com/actions/setup-go | |
| - | |
| name: Setup Golang | |
| id: setup-go | |
| # You may pin to the exact commit or the version. | |
| # uses: https://github.com/actions/setup-go/tags | |
| uses: actions/setup-go@v4 | |
| with: | |
| # Fix the following warning: Both go-version and go-version-file inputs are specified, only go-version will be used | |
| go-version: "stable" | |
| # go-version-file: './go.mod' | |
| cache: true | |
| # A GitHub Action for golang tests | |
| - | |
| name: Golang Tests | |
| id: go-tests | |
| run: | | |
| go version | |
| rm -rf example | |
| go test -v -race -covermode=atomic -coverprofile=coverage.out ./... | |
| go tool cover -html=coverage.out -o coverage.html | |
| # https://github.com/apache/skywalking-eyes | |
| # issue: go version hard-coded: https://github.com/apache/skywalking-eyes/blob/5dfa68f93380a5e57259faaf95088b7f133b5778/header/action.yml#L47-L51 | |
| - name: Check License Header | |
| if: matrix.platform == 'linux/amd64' # Only required once for any platform, and will do the most general amd64 | |
| uses: apache/skywalking-eyes/header@main | |
| with: | |
| log: "info" # optional: set the log level. The default value is `info`. | |
| config: ".licenserc.yaml" # optional: set the config file. The default value is `.licenserc.yaml`. | |
| token: "" # optional: the token that license eye uses when it needs to comment on the pull request. Set to empty ("") to disable commenting on pull request. The default value is ${{ github.token }} | |
| mode: "check" # optional: Which mode License-Eye should be run in. Choices are `check` or `fix`. The default value is `check`. | |
| # The Github action runs CIS Dockerfile benchmark against dockerfiles in repository (CIS 4.1, 4.2, 4.3, 4.6, 4.7, 4.9, 4.10) | |
| # https://github.com/sysdiglabs/benchmark-dockerfile | |
| - | |
| name: Sysdig Benchmark Dockerfile | |
| id: sysdig | |
| if: matrix.platform == 'linux/amd64' # Only required once for any platform, and will do the most general amd64 | |
| # You may pin to the exact commit or the version. | |
| # uses: https://github.com/sysdiglabs/benchmark-dockerfile/tags | |
| uses: sysdiglabs/[email protected] | |
| with: | |
| # Directory of dockerfiles (default "./") | |
| directory: "./" | |
| # list of disallowed packages separated by comma (default ") | |
| #disallowedPackages: '' | |
| # list of trusted base images separated by comma (default "", meaning trust any base image) | |
| trustedBaseImages: "" | |
| # The Github action runs CIS Dockerfile benchmark against dockerfiles in repository (CIS 4.1, 4.2, 4.3, 4.6, 4.7, 4.9, 4.10) | |
| # https://github.com/sysdiglabs/benchmark-dockerfile | |
| # TODO: Skipping CIS 4.1 check until https://github.com/yahoojapan/authorization-proxy/pull/95 is fixed. | |
| - | |
| name: Post Sysdig Benchmark Dockerfile | |
| id: postsysdig | |
| if: matrix.platform == 'linux/amd64' # Only required once for any platform, and will do the most general amd64 | |
| run: | | |
| echo ${{ toJSON(steps.sysdig.outputs.violation_report) }} | \ | |
| jq -r . | |
| echo ${{ toJSON(steps.sysdig.outputs.violation_report) }} | \ | |
| jq -r '.cis_docker_benchmark_violation_report[] | select(.rule!="CIS 4.1 Create a user for the container") | .violations[]' | \ | |
| wc -l | \ | |
| xargs -I% test 0 -eq % | |
| # GitHub Action to install QEMU static binaries. | |
| # https://github.com/docker/setup-qemu-action | |
| - | |
| name: Set up QEMU | |
| id: qemu | |
| # You may pin to the exact commit or the version. | |
| # uses: https://github.com/docker/setup-qemu-action/tags | |
| uses: docker/setup-qemu-action@v3 | |
| # GitHub Action to set up Docker Buildx. | |
| # https://github.com/docker/setup-buildx-action | |
| - | |
| name: Set up Docker Buildx | |
| id: buildx | |
| # You may pin to the exact commit or the version. | |
| # uses: https://github.com/docker/setup-buildx-action/tags | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to Temporary Registry (GitHub Container Registry) | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Lowercase image id name to follow the docker name rule | |
| run: | | |
| IMAGE_ID=ghcr.io/${{ github.repository }} | |
| echo "GHCR_IMAGE_ID=$(echo $IMAGE_ID | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV | |
| - name: Build and Push to GHCR (Staging) | |
| uses: docker/build-push-action@v4 | |
| with: | |
| context: . | |
| push: true | |
| # tag i.e) ghcr.io/athenz/authorization-proxy:sha-ck29d1-amd64 | |
| tags: ${{ env.GHCR_IMAGE_ID }}:${{ github.sha }}${{ matrix.suffix }} | |
| platforms: ${{ matrix.platform }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # Test Docker image | |
| - | |
| name: Test Docker image | |
| id: test_docker | |
| run: | | |
| docker run --rm ${{ env.GHCR_IMAGE_ID }}:${{ github.sha }}${{ matrix.suffix }} --version | |
| merge: | |
| if: github.event_name != 'pull_request' # We do not need to push pr images to official registry (Docker.io) | |
| needs: | |
| - set_matrix | |
| - build # Make sure each build of every platform defined in matrix is completed | |
| runs-on: ubuntu-latest | |
| permissions: | |
| packages: write # Give read permission WITHOUT making the registry_visibility=Public | |
| steps: | |
| - name: Login to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Login to Docker registry | |
| uses: docker/login-action@v3 | |
| with: | |
| # Server address of Docker registry. If not set then will default to Docker Hub | |
| registry: ${{ env.DOCKER_REGISTRY_URL }} # optional | |
| # Username used to log against the Docker registry | |
| username: ${{ vars.DOCKER_REGISTRY_USER }} # optional | |
| # Password or personal access token used to log against the Docker registry | |
| password: ${{ secrets[vars.DOCKER_REGISTRY_TOKEN_NAME] }} # optional | |
| # Log out from the Docker registry at the end of a job | |
| logout: true # optional, default is true | |
| - name: Extract Docker metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.DOCKER_REGISTRY_URL }}/${{ env.DOCKER_REGISTRY_ORG }}/${{ env.DOCKER_REGISTRY_IMAGE }} | |
| flavor: | | |
| latest=false | |
| # No suffix defined as this will be the merged one! | |
| tags: ${{ env.TAGS_CONFIG }} | |
| - name: Set GHCR Image Name (Lowercase) | |
| run: | | |
| IMAGE_ID=ghcr.io/${{ github.repository }} | |
| echo "GHCR_IMAGE_ID=$(echo $IMAGE_ID | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV | |
| - name: Create Manifest and Push to Docker Hub | |
| env: | |
| PLATFORM_SUFFIXES: ${{ needs.set_matrix.outputs.suffixes }} | |
| SHA_TAG: ${{ github.sha }} | |
| run: | | |
| echo "${{ steps.meta.outputs.tags }}" | while read -r docker_registry_tag; do | |
| echo "Merging sources into final tag: $docker_registry_tag" | |
| sources="" | |
| for suffix in $PLATFORM_SUFFIXES; do | |
| # i.e) ghcr.io/athenz/authorization-proxy:sha-xxx-amd64 | |
| sources="$sources ${{ env.GHCR_IMAGE_ID }}:${SHA_TAG}${suffix}" | |
| done | |
| docker buildx imagetools create -t "$docker_registry_tag" $sources | |
| done | |
| cleanup: | |
| name: Cleanup Temporary Images from GitHub Container Registry | |
| needs: [set_matrix, build, merge] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| permissions: | |
| packages: write # Permission to delete images from GitHub Container Registry | |
| steps: | |
| - name: Login to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Delete Temporary Images using GitHub API | |
| env: | |
| OWNER: ${{ github.repository_owner }} | |
| PACKAGE_NAME: authorization-proxy | |
| SHA_TAG: ${{ github.sha }} | |
| PLATFORM_SUFFIXES: ${{ needs.set_matrix.outputs.suffixes }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| echo "🧹 Cleanup using GitHub API..." | |
| for suffix in $PLATFORM_SUFFIXES; do | |
| TAG_NAME="${SHA_TAG}${suffix}" | |
| echo "🔍 Finding version ID for tag: $TAG_NAME" | |
| VERSION_ID=$(gh api "/orgs/$OWNER/packages/container/$PACKAGE_NAME/versions" \ | |
| -H "Accept: application/vnd.github+json" \ | |
| --jq ".[] | select(.metadata.container.tags[]? == \"$TAG_NAME\") | .id") | |
| if [ -z "$VERSION_ID" ]; then | |
| echo "⚠️ Tag $TAG_NAME not found (already deleted?)" | |
| continue | |
| fi | |
| echo "🗑️ Deleting Version ID: $VERSION_ID (Tag: $TAG_NAME)" | |
| # Delete based on ID: | |
| gh api -X DELETE "/orgs/$OWNER/packages/container/$PACKAGE_NAME/versions/$VERSION_ID" \ | |
| -H "Accept: application/vnd.github+json" || true | |
| done | |
| echo "✨ Cleanup finished!" |