|
9 | 9 | default: ""
|
10 | 10 |
|
11 | 11 | jobs:
|
12 |
| - build: |
13 |
| - strategy: |
14 |
| - fail-fast: false |
15 |
| - matrix: |
16 |
| - include: |
17 |
| - - os: [self-hosted, Linux, X64] |
18 |
| - platform: linux/amd64 |
19 |
| - - os: [self-hosted, macOS, ARM64] |
20 |
| - platform: linux/arm64 |
21 |
| - runs-on: ${{ matrix.os }} |
22 |
| - |
| 12 | + build-amd64: |
| 13 | + runs-on: [self-hosted, Linux, X64] |
23 | 14 | permissions:
|
24 | 15 | contents: read
|
25 | 16 | packages: write
|
26 |
| - |
27 | 17 | outputs:
|
28 | 18 | sha_tag: ${{ steps.meta.outputs.sha_tag }}
|
29 | 19 | date_tag: ${{ steps.meta.outputs.date_tag }}
|
30 | 20 | user_tag: ${{ steps.meta.outputs.user_tag }}
|
31 | 21 | image_name: ${{ steps.name.outputs.image_name }}
|
32 |
| - |
33 | 22 | steps:
|
34 | 23 | - name: Checkout
|
35 | 24 | uses: actions/checkout@v4
|
36 |
| - |
37 | 25 | - name: Set up Docker Buildx
|
38 | 26 | uses: docker/setup-buildx-action@v3
|
39 |
| - |
40 | 27 | - name: Log in to GHCR
|
41 | 28 | uses: docker/login-action@v3
|
42 | 29 | with:
|
43 | 30 | registry: ghcr.io
|
44 | 31 | username: ${{ github.repository_owner }}
|
45 | 32 | password: ${{ secrets.GITHUB_TOKEN }}
|
46 |
| - |
47 | 33 | - name: Set lowercase image name
|
48 | 34 | id: name
|
49 | 35 | run: |
|
50 | 36 | IMAGE_NAME_LOWERCASE=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')/rsafd-docker
|
51 | 37 | echo "image_name=$IMAGE_NAME_LOWERCASE" >> $GITHUB_OUTPUT
|
52 |
| -
|
53 | 38 | - name: Compute tags
|
54 | 39 | id: meta
|
55 | 40 | run: |
|
56 | 41 | DATE_TAG=$(date +'%Y%m%d')
|
57 |
| - SHA_TAG=${GITHUB_SHA::12} |
58 |
| - USER_TAG="${{ github.event.inputs.tag }}" |
59 |
| -
|
60 |
| - echo "sha_tag=$SHA_TAG" >> $GITHUB_OUTPUT |
61 |
| - echo "date_tag=$DATE_TAG" >> $GITHUB_OUTPUT |
62 |
| - echo "user_tag=$USER_TAG" >> $GITHUB_OUTPUT |
63 |
| - echo "tags=ghcr.io/${{ steps.name.outputs.image_name }}:${SHA_TAG}" >> $GITHUB_OUTPUT |
| 42 | + SHA_TAG=${GITHUB_SHA::12} |
| 43 | + USER_TAG="${{ github.event.inputs.tag }}" |
| 44 | + echo "sha_tag=$SHA_TAG" >> $GITHUB_OUTPUT |
| 45 | + echo "date_tag=$DATE_TAG" >> $GITHUB_OUTPUT |
| 46 | + echo "user_tag=$USER_TAG" >> $GITHUB_OUTPUT |
| 47 | + - name: Build & Push (amd64) |
| 48 | + uses: docker/build-push-action@v5 |
| 49 | + with: |
| 50 | + context: . |
| 51 | + # Rely on native host arch (amd64) |
| 52 | + tags: ghcr.io/${{ steps.name.outputs.image_name }}:${{ steps.meta.outputs.sha_tag }}-amd64 |
| 53 | + push: true |
| 54 | + provenance: false |
| 55 | + sbom: false |
| 56 | + build-args: | |
| 57 | + GH_OWNER=${{ github.repository_owner }} |
64 | 58 |
|
65 |
| - - name: Build & Push |
| 59 | + build-arm64: |
| 60 | + runs-on: [self-hosted, macOS, ARM64] |
| 61 | + permissions: |
| 62 | + contents: read |
| 63 | + packages: write |
| 64 | + outputs: |
| 65 | + sha_tag: ${{ steps.meta.outputs.sha_tag }} |
| 66 | + date_tag: ${{ steps.meta.outputs.date_tag }} |
| 67 | + user_tag: ${{ steps.meta.outputs.user_tag }} |
| 68 | + image_name: ${{ steps.name.outputs.image_name }} |
| 69 | + steps: |
| 70 | + - name: Checkout |
| 71 | + uses: actions/checkout@v4 |
| 72 | + - name: Set up Docker Buildx |
| 73 | + uses: docker/setup-buildx-action@v3 |
| 74 | + - name: Log in to GHCR |
| 75 | + uses: docker/login-action@v3 |
| 76 | + with: |
| 77 | + registry: ghcr.io |
| 78 | + username: ${{ github.repository_owner }} |
| 79 | + password: ${{ secrets.GITHUB_TOKEN }} |
| 80 | + - name: Set lowercase image name |
| 81 | + id: name |
| 82 | + run: | |
| 83 | + IMAGE_NAME_LOWERCASE=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')/rsafd-docker |
| 84 | + echo "image_name=$IMAGE_NAME_LOWERCASE" >> $GITHUB_OUTPUT |
| 85 | + - name: Compute tags |
| 86 | + id: meta |
| 87 | + run: | |
| 88 | + DATE_TAG=$(date +'%Y%m%d') |
| 89 | + SHA_TAG=${GITHUB_SHA::12} |
| 90 | + USER_TAG="${{ github.event.inputs.tag }}" |
| 91 | + echo "sha_tag=$SHA_TAG" >> $GITHUB_OUTPUT |
| 92 | + echo "date_tag=$DATE_TAG" >> $GITHUB_OUTPUT |
| 93 | + echo "user_tag=$USER_TAG" >> $GITHUB_OUTPUT |
| 94 | + - name: Build & Push (arm64) |
66 | 95 | uses: docker/build-push-action@v5
|
67 | 96 | with:
|
68 | 97 | context: .
|
69 |
| - platforms: ${{ matrix.platform }} |
70 |
| - tags: ${{ steps.meta.outputs.tags }} |
| 98 | + # Native arm64 host build |
| 99 | + tags: ghcr.io/${{ steps.name.outputs.image_name }}:${{ steps.meta.outputs.sha_tag }}-arm64 |
71 | 100 | push: true
|
72 | 101 | provenance: false
|
73 | 102 | sbom: false
|
74 | 103 | build-args: |
|
75 | 104 | GH_OWNER=${{ github.repository_owner }}
|
76 | 105 |
|
77 |
| - create-manifest: |
| 106 | + manifest: |
78 | 107 | runs-on: ubuntu-latest
|
79 |
| - needs: build |
| 108 | + needs: [build-amd64, build-arm64] |
80 | 109 | permissions:
|
81 | 110 | contents: read
|
82 | 111 | packages: write
|
83 |
| - |
84 | 112 | steps:
|
85 | 113 | - name: Log in to GHCR
|
86 | 114 | uses: docker/login-action@v3
|
87 | 115 | with:
|
88 | 116 | registry: ghcr.io
|
89 | 117 | username: ${{ github.repository_owner }}
|
90 | 118 | password: ${{ secrets.GITHUB_TOKEN }}
|
91 |
| - |
92 |
| - - name: Create and push manifest list |
| 119 | + - name: Create multi-arch manifest tags |
93 | 120 | run: |
|
94 | 121 | set -euo pipefail
|
95 |
| - IMAGE=ghcr.io/${{ needs.build.outputs.image_name }} |
96 |
| - SHA_TAG=${{ needs.build.outputs.sha_tag }} |
97 |
| - DATE_TAG=${{ needs.build.outputs.date_tag }} |
98 |
| - USER_TAG=${{ needs.build.outputs.user_tag }} |
99 |
| -
|
100 |
| - # Re-tag the already-built image/manifest (single-arch or multi-arch) using imagetools. |
101 |
| - # This avoids attempting to create a manifest from an existing manifest list (which caused the failure). |
102 |
| - ARGS=(-t "$IMAGE:$DATE_TAG" -t "$IMAGE:latest") |
103 |
| - if [ -n "$USER_TAG" ]; then |
104 |
| - ARGS+=( -t "$IMAGE:$USER_TAG" ) |
105 |
| - fi |
106 |
| - # Create new tags pointing to the same digest/manifest |
107 |
| - docker buildx imagetools create "${ARGS[@]}" "$IMAGE:$SHA_TAG" |
108 |
| -
|
109 |
| - echo "Retagged $IMAGE:$SHA_TAG as: $IMAGE:$DATE_TAG, $IMAGE:latest${USER_TAG:+, $IMAGE:$USER_TAG}" |
110 |
| -
|
| 122 | + IMAGE=ghcr.io/${{ needs.build-amd64.outputs.image_name }} |
| 123 | + SHA_TAG=${{ needs.build-amd64.outputs.sha_tag }} |
| 124 | + DATE_TAG=${{ needs.build-amd64.outputs.date_tag }} |
| 125 | + USER_TAG=${{ needs.build-amd64.outputs.user_tag }} |
| 126 | + SRC_AMD64=$IMAGE:${SHA_TAG}-amd64 |
| 127 | + SRC_ARM64=$IMAGE:${SHA_TAG}-arm64 |
| 128 | + if ! docker buildx imagetools inspect $SRC_AMD64 >/dev/null 2>&1; then echo "Missing $SRC_AMD64"; exit 1; fi |
| 129 | + if ! docker buildx imagetools inspect $SRC_ARM64 >/dev/null 2>&1; then echo "Missing $SRC_ARM64"; exit 1; fi |
| 130 | + ARGS=(-t $IMAGE:$SHA_TAG -t $IMAGE:$DATE_TAG -t $IMAGE:latest) |
| 131 | + if [ -n "$USER_TAG" ]; then ARGS+=( -t $IMAGE:$USER_TAG ); fi |
| 132 | + docker buildx imagetools create "${ARGS[@]}" $SRC_AMD64 $SRC_ARM64 |
| 133 | + docker buildx imagetools inspect $IMAGE:$SHA_TAG |
111 | 134 | - name: Summary
|
112 | 135 | run: |
|
113 |
| - IMAGE=ghcr.io/${{ needs.build.outputs.image_name }} |
114 |
| - echo "Pushed manifests for:" >> $GITHUB_STEP_SUMMARY |
115 |
| - echo "$IMAGE:${{ needs.build.outputs.sha_tag }}" >> $GITHUB_STEP_SUMMARY |
| 136 | + IMAGE=ghcr.io/${{ needs.build-amd64.outputs.image_name }} |
| 137 | + echo "Published multi-arch tags:" >> $GITHUB_STEP_SUMMARY |
| 138 | + echo "$IMAGE:${{ needs.build-amd64.outputs.sha_tag }}" >> $GITHUB_STEP_SUMMARY |
| 139 | + echo "$IMAGE:${{ needs.build-amd64.outputs.date_tag }}" >> $GITHUB_STEP_SUMMARY |
116 | 140 | echo "$IMAGE:latest" >> $GITHUB_STEP_SUMMARY
|
117 |
| - echo "$IMAGE:${{ needs.build.outputs.date_tag }}" >> $GITHUB_STEP_SUMMARY |
118 |
| - if [ -n "${{ needs.build.outputs.user_tag }}" ]; then |
119 |
| - echo "$IMAGE:${{ needs.build.outputs.user_tag }}" >> $GITHUB_STEP_SUMMARY |
| 141 | + if [ -n "${{ needs.build-amd64.outputs.user_tag }}" ]; then |
| 142 | + echo "$IMAGE:${{ needs.build-amd64.outputs.user_tag }}" >> $GITHUB_STEP_SUMMARY |
120 | 143 | fi
|
0 commit comments