| 
 | 1 | +# ======================================================================  | 
 | 2 | +# 🐳  Docker Release Workflow - Tag and Push on GitHub Release  | 
 | 3 | +# ======================================================================  | 
 | 4 | +#  | 
 | 5 | +# This workflow re-tags a Docker image (built by a previous workflow)  | 
 | 6 | +# when a GitHub Release is published, giving it a semantic version tag  | 
 | 7 | +# like `v0.1.0`. It assumes the CI build has already pushed an image  | 
 | 8 | +# tagged with the commit SHA, and that all checks on that commit passed.  | 
 | 9 | +#  | 
 | 10 | +# ➤ Trigger: Release published (e.g. from GitHub UI or `gh release` CLI)  | 
 | 11 | +# ➤ Assumes: Existing image tagged with the commit SHA is available  | 
 | 12 | +# ➤ Result: Image re-tagged as `ghcr.io/OWNER/REPO:v0.1.0`  | 
 | 13 | +#  | 
 | 14 | +# ======================================================================  | 
 | 15 | + | 
 | 16 | +name: "Docker image - release tag"  | 
 | 17 | + | 
 | 18 | +# ----------------------------------------------------------------------------  | 
 | 19 | +# Trigger: When a release is published (NOT draft or prerelease)  | 
 | 20 | +# ----------------------------------------------------------------------------  | 
 | 21 | +on:  | 
 | 22 | +  release:  | 
 | 23 | +    types: [published]  | 
 | 24 | + | 
 | 25 | +jobs:  | 
 | 26 | +  tag-and-push:  | 
 | 27 | +    # ------------------------------------------------------------------------  | 
 | 28 | +    # Only run if the release tag starts with 'v', and is not a draft/prerelease  | 
 | 29 | +    # ------------------------------------------------------------------------  | 
 | 30 | +    if: |  | 
 | 31 | +      startsWith(github.event.release.tag_name, 'v') &&  | 
 | 32 | +      github.event.release.draft == false &&  | 
 | 33 | +      github.event.release.prerelease == false  | 
 | 34 | +
  | 
 | 35 | +    runs-on: ubuntu-latest  | 
 | 36 | + | 
 | 37 | +    permissions:  | 
 | 38 | +      contents: read      # read repository info  | 
 | 39 | +      packages: write     # push Docker image  | 
 | 40 | +      statuses: read      # check status API to ensure commit checks passed  | 
 | 41 | + | 
 | 42 | +    steps:  | 
 | 43 | +      # ----------------------------------------------------------------------  | 
 | 44 | +      # Step 1: Capture release tag and resolve the commit SHA it points to  | 
 | 45 | +      # ----------------------------------------------------------------------  | 
 | 46 | +      - name: 🏷️  Extract tag & commit SHA  | 
 | 47 | +        id: meta  | 
 | 48 | +        run: |  | 
 | 49 | +          TAG="${{ github.event.release.tag_name }}"  | 
 | 50 | +          echo "tag=$TAG" >> "$GITHUB_OUTPUT"  | 
 | 51 | +
  | 
 | 52 | +          # Fetch the commit SHA for this tag  | 
 | 53 | +          git init -q  | 
 | 54 | +          git remote add origin "https://github.com/${{ github.repository }}"  | 
 | 55 | +          git fetch --depth=1 origin "refs/tags/$TAG"  | 
 | 56 | +          SHA=$(git rev-list -n 1 "$TAG")  | 
 | 57 | +          echo "sha=$SHA" >> "$GITHUB_OUTPUT"  | 
 | 58 | +
  | 
 | 59 | +      # ----------------------------------------------------------------------  | 
 | 60 | +      # Step 2: Confirm all checks on that commit were successful  | 
 | 61 | +      # ----------------------------------------------------------------------  | 
 | 62 | +      - name: ✅  Verify commit checks passed  | 
 | 63 | +        env:  | 
 | 64 | +          SHA: ${{ steps.meta.outputs.sha }}  | 
 | 65 | +          REPO: ${{ github.repository }}  | 
 | 66 | +        run: |  | 
 | 67 | +          set -euo pipefail  | 
 | 68 | +          STATUS=$(curl -sSL \  | 
 | 69 | +            -H "Accept: application/vnd.github+json" \  | 
 | 70 | +            -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \  | 
 | 71 | +            "https://api.github.com/repos/$REPO/commits/$SHA/status" \  | 
 | 72 | +            | jq -r '.state')  | 
 | 73 | +          echo "Combined status: $STATUS"  | 
 | 74 | +          if [ "$STATUS" != "success" ]; then  | 
 | 75 | +            echo "Required workflows have not all succeeded - aborting." >&2  | 
 | 76 | +            exit 1  | 
 | 77 | +          fi  | 
 | 78 | +
  | 
 | 79 | +      # ----------------------------------------------------------------------  | 
 | 80 | +      # Step 3: Authenticate with GitHub Container Registry (GHCR)  | 
 | 81 | +      # ----------------------------------------------------------------------  | 
 | 82 | +      - name: 🔐  Log in to GHCR  | 
 | 83 | +        uses: docker/login-action@v3  | 
 | 84 | +        with:  | 
 | 85 | +          registry: ghcr.io  | 
 | 86 | +          username: ${{ github.actor }}  | 
 | 87 | +          password: ${{ secrets.GITHUB_TOKEN }}  | 
 | 88 | + | 
 | 89 | +      # ----------------------------------------------------------------------  | 
 | 90 | +      # Step 4: Pull the image using the commit SHA tag  | 
 | 91 | +      # ----------------------------------------------------------------------  | 
 | 92 | +      - name: ⬇️  Pull image by commit SHA  | 
 | 93 | +        run: |  | 
 | 94 | +          IMAGE="ghcr.io/$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')"  | 
 | 95 | +          docker pull "$IMAGE:${{ steps.meta.outputs.sha }}"  | 
 | 96 | +
  | 
 | 97 | +      # ----------------------------------------------------------------------  | 
 | 98 | +      # Step 5: Tag the image with the semantic version tag  | 
 | 99 | +      # ----------------------------------------------------------------------  | 
 | 100 | +      - name: 🏷️  Tag image with version  | 
 | 101 | +        run: |  | 
 | 102 | +          IMAGE="ghcr.io/$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')"  | 
 | 103 | +          docker tag "$IMAGE:${{ steps.meta.outputs.sha }}" "$IMAGE:${{ steps.meta.outputs.tag }}"  | 
 | 104 | +
  | 
 | 105 | +      # ----------------------------------------------------------------------  | 
 | 106 | +      # Step 6: Push the new tag to GHCR  | 
 | 107 | +      # ----------------------------------------------------------------------  | 
 | 108 | +      - name: 🚀  Push new version tag  | 
 | 109 | +        run: |  | 
 | 110 | +          IMAGE="ghcr.io/$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')"  | 
 | 111 | +          docker push "$IMAGE:${{ steps.meta.outputs.tag }}"  | 
0 commit comments