|
| 1 | +# Based on |
| 2 | +# * <https://github.com/NumericalEarth/breeze-docker-images/blob/f06a3da11b2c7edaaf0a8e32c133270eb4103b1c/.github/workflows/DockerPublish.yml> |
| 3 | +# * <https://docs.github.com/en/actions/publishing-packages/publishing-docker-images> |
| 4 | +# * <https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners>. |
| 5 | + |
1 | 6 | name: Publish Docker container |
2 | 7 |
|
3 | 8 | on: |
|
18 | 23 | branches: |
19 | 24 | - master |
20 | 25 |
|
| 26 | +env: |
| 27 | + REGISTRY: ghcr.io |
| 28 | + IMAGE_NAME: ${{ github.repository }} |
| 29 | + |
21 | 30 | jobs: |
22 | | - push_to_registry: |
23 | | - name: Container for ${{ matrix.platform }} - Julia ${{ matrix.julia }} - CUDA ${{ matrix.cuda }} |
| 31 | + build: |
| 32 | + name: Build Container for ${{ matrix.platform }} - Julia ${{ matrix.julia }} - CUDA ${{ matrix.cuda }} |
24 | 33 | permissions: |
25 | 34 | contents: read |
26 | 35 | packages: write |
| 36 | + attestations: write |
| 37 | + # This is used to complete the identity challenge |
| 38 | + # with sigstore/fulcio when running outside of PRs. |
| 39 | + id-token: write |
27 | 40 |
|
28 | 41 | strategy: |
29 | 42 | matrix: |
|
46 | 59 | runs-on: ${{ matrix.os }} |
47 | 60 |
|
48 | 61 | steps: |
| 62 | + # Docker is terrible and doesn't like uppercase image names. |
| 63 | + - name: Lowercase image name |
| 64 | + run: | |
| 65 | + IMAGE_NAME=$(echo ${IMAGE_NAME} | tr A-Z a-z) |
| 66 | + echo "IMAGE_NAME=${IMAGE_NAME}" >> "${GITHUB_ENV}" |
| 67 | +
|
49 | 68 | - name: Check out the repo |
50 | 69 | uses: actions/checkout@v6 |
51 | 70 |
|
@@ -90,37 +109,99 @@ jobs: |
90 | 109 | - name: Log in to registry |
91 | 110 | uses: docker/login-action@v3 |
92 | 111 | with: |
93 | | - registry: ghcr.io |
| 112 | + registry: ${{ env.REGISTRY }} |
94 | 113 | username: ${{ github.actor }} |
95 | 114 | password: ${{ secrets.GITHUB_TOKEN }} |
96 | 115 |
|
97 | | - - name: Extract metadata |
98 | | - id: meta |
99 | | - uses: docker/metadata-action@v5 |
100 | | - with: |
101 | | - images: ghcr.io/${{ github.repository }} |
102 | | - tags: | |
103 | | - type=raw,value=${{ steps.pkg.outputs.name }}-julia${{ matrix.julia }}-cuda${{ steps.cuda.outputs.major }} |
104 | | - type=raw,value=${{ steps.pkg.outputs.name }},enable=${{ matrix.default == true && (github.ref_type == 'tag' || inputs.tag != '') }} |
105 | | - type=raw,value=latest,enable=${{ matrix.default == true && (github.ref_type == 'tag' || (inputs.tag != '' && inputs.mark_as_latest)) }} |
106 | | - type=raw,value=dev,enable=${{ matrix.default == true && github.ref_type == 'branch' && inputs.tag == '' }} |
107 | | - labels: | |
108 | | - org.opencontainers.image.version=${{ steps.pkg.outputs.version }} |
109 | | -
|
110 | 116 | - name: Set up Docker Buildx |
111 | 117 | uses: docker/setup-buildx-action@v3 |
112 | 118 |
|
113 | | - - name: Build and push image |
| 119 | + - name: Build and push |
| 120 | + id: build |
114 | 121 | uses: docker/build-push-action@v6 |
115 | 122 | with: |
116 | 123 | context: . |
117 | 124 | push: true |
118 | 125 | provenance: false # the build fetches the repo again, so provenance tracking is not useful |
119 | 126 | platforms: ${{ matrix.platform }} |
120 | | - tags: ${{ steps.meta.outputs.tags }} |
121 | | - labels: ${{ steps.meta.outputs.labels }} |
| 127 | + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.pkg.outputs.name }}-julia${{ matrix.julia }}-cuda${{ steps.cuda.outputs.major }} |
| 128 | + labels: | |
| 129 | + org.opencontainers.image.version=${{ steps.pkg.outputs.version }} |
122 | 130 | build-args: | |
123 | 131 | JULIA_VERSION=${{ matrix.julia }} |
124 | 132 | CUDA_VERSION=${{ matrix.cuda }} |
125 | 133 | PACKAGE_SPEC=CUDA#${{ steps.pkg.outputs.ref }} |
126 | 134 | JULIA_CPU_TARGET=${{ steps.cpu_target.outputs.target }} |
| 135 | +
|
| 136 | + - name: Export digest |
| 137 | + id: export-digest |
| 138 | + run: | |
| 139 | + mkdir -p /tmp/digests |
| 140 | + digest_name=${{ steps.pkg.outputs.name }}-julia${{ matrix.julia }}-cuda${{ steps.cuda.outputs.major }}-$(echo ${{ matrix.platform }} | tr / -) |
| 141 | + echo "digest_name=${digest_name}" | tee "${GITHUB_OUTPUT}" |
| 142 | + echo "${{ steps.build.outputs.digest }}" > "/tmp/digests/${digest_name}" |
| 143 | +
|
| 144 | + - name: Upload digest |
| 145 | + uses: actions/upload-artifact@v6 |
| 146 | + with: |
| 147 | + name: digests-${{ steps.export-digest.outputs.digest_name }} |
| 148 | + path: /tmp/digests/* |
| 149 | + if-no-files-found: error |
| 150 | + retention-days: 1 |
| 151 | + |
| 152 | + merge: |
| 153 | + needs: build |
| 154 | + runs-on: ubuntu-latest |
| 155 | + permissions: |
| 156 | + contents: read |
| 157 | + packages: write |
| 158 | + attestations: write |
| 159 | + # This is used to complete the identity challenge |
| 160 | + # with sigstore/fulcio when running outside of PRs. |
| 161 | + id-token: write |
| 162 | + if: github.event_name != 'pull_request' |
| 163 | + |
| 164 | + steps: |
| 165 | + # Docker is terrible and doesn't like uppercase image names. |
| 166 | + - name: Lowercase image name |
| 167 | + run: | |
| 168 | + IMAGE_NAME=$(echo ${IMAGE_NAME} | tr A-Z a-z) |
| 169 | + echo "IMAGE_NAME=${IMAGE_NAME}" >> "${GITHUB_ENV}" |
| 170 | +
|
| 171 | + - name: Download digests |
| 172 | + uses: actions/download-artifact@v7 |
| 173 | + with: |
| 174 | + path: /tmp/digests |
| 175 | + pattern: digests-* |
| 176 | + merge-multiple: true |
| 177 | + |
| 178 | + # https://github.com/docker/setup-buildx-action |
| 179 | + - name: Set up Docker Buildx |
| 180 | + uses: docker/setup-buildx-action@v3 |
| 181 | + |
| 182 | + # Log into the registry. |
| 183 | + # https://github.com/docker/login-action |
| 184 | + - name: Log into registry |
| 185 | + uses: docker/login-action@v3 |
| 186 | + with: |
| 187 | + registry: ${{ env.REGISTRY }} |
| 188 | + username: ${{ github.actor }} |
| 189 | + password: ${{ secrets.GITHUB_TOKEN }} |
| 190 | + |
| 191 | + - name: Create manifest lists for each tag |
| 192 | + run: | |
| 193 | + for file in /tmp/digests/*; do |
| 194 | + TAG=${file##*/} # e.g. "dev-julia1.11-cuda11-linux-amd64" |
| 195 | + VARIANT=$(echo ${TAG} | cut -d- -f1-3) # e.g. "dev-julia1.11-cuda11" |
| 196 | + # buildx imagetools needs: -t registry/image:tag and sources |
| 197 | + SOURCES="" |
| 198 | + for f in /tmp/digests/${VARIANT}-*; do |
| 199 | + # each f contains a digest per arch |
| 200 | + DIG=$(cat "${f}") |
| 201 | + PLATFORM=${f##*/} # e.g. "docs-linux-amd64" |
| 202 | + SOURCES="${SOURCES} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${DIG}" |
| 203 | + done |
| 204 | + docker buildx imagetools create \ |
| 205 | + --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VARIANT} \ |
| 206 | + ${SOURCES} |
| 207 | + done |
0 commit comments