Remove the architecture suffix on CPU version with only one architect… #114
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
| # This requires | |
| # vars.DOCKERHUB_USERNAME for the result image account | |
| # secrets.DOCKERHUB_USERNAME for the account that pushes the image | |
| # secrets.DOCKERHUB_TOKEN for the account password that pushes the image | |
| name: Docker | |
| on: | |
| push: | |
| branches: | |
| - main | |
| # We want to monthly update the base image for security | |
| # TODO Can we avoid building the same image? | |
| schedule: | |
| # min hour dom month dow | |
| - cron: '42 3 2 * *' | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| build: | |
| runs-on: ${{ matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }} | |
| strategy: | |
| matrix: | |
| torch: ['2.9.1'] | |
| python: ['3.14.2', '3.14.2-slim'] | |
| index: [cu126,cpu] | |
| platform: [linux/amd64, linux/arm64] | |
| exclude: | |
| - index: cpu | |
| platform: linux/arm64 | |
| - index: cpu | |
| python: '3.14.2-slim' | |
| permissions: | |
| contents: read | |
| id-token: write # Needed for actions/attest-build-provenance build predicate | |
| attestations: write # Needed for actions/attest-build-provenance attestation upload to repository | |
| artifact-metadata: write # Needed for actions/attest-build-provenance artifact metadata storage records | |
| steps: | |
| - id: created | |
| run: echo "created=$(date --utc +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_OUTPUT | |
| - uses: actions/checkout@v6 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 | |
| if: github.ref == 'refs/heads/main' | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Build Tag | |
| id: build-tag | |
| # Tags have limited set of valid character, '+' not included | |
| # https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pulling-manifests | |
| run: | | |
| echo "tag=$(echo -n "${{ matrix.torch }}${{ matrix.index && format('-{0}', matrix.index) || '' }}-${{ matrix.python }}${PLATFORM+-}${PLATFORM#*/}" | tr -c 'a-zA-Z0-9._-' '[-*]')" >> $GITHUB_OUTPUT | |
| env: | |
| PLATFORM: ${{ matrix.index != 'cpu' && matrix.platform || '' }} | |
| - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 | |
| id: build-push | |
| with: | |
| context: . | |
| push: ${{ github.ref == 'refs/heads/main' }} | |
| build-args: | | |
| CREATED=${{ steps.created.outputs.created }} | |
| SOURCE_COMMIT=${{ github.sha }} | |
| PYTHON=${{ matrix.python }} | |
| TORCH=${{ matrix.torch }} | |
| TORCH_REQUIREMENT=${{ matrix.url || format('torch=={0}', matrix.torch) }} | |
| TORCH_WHEEL_SOURCE=${{ matrix.torch-wheel-tag && format('{0}/torch-wheels:{1}', vars.DOCKERHUB_USERNAME, matrix.torch-wheel-tag) || 'scratch'}} | |
| TORCHVISION_WHEEL_SOURCE=${{ matrix.torchvision && format('{0}/torchvision-wheels:{1}', vars.DOCKERHUB_USERNAME, matrix.torchvision) || 'scratch'}} | |
| EXTRA_INDEX_URL=${{ matrix.extra-index-url || format('https://download.pytorch.org/whl/{0}/', matrix.index) }} | |
| CONSTRAINTS=constraints-${{ matrix.torch }}.txt | |
| # TODO add the latest tag, maybe somehow via docker/metadata-action | |
| tags: | | |
| ${{ vars.DOCKERHUB_USERNAME }}/python-torch:${{ steps.build-tag.outputs.tag }} | |
| # https://docs.docker.com/build/ci/github-actions/cache/ | |
| cache-from: type=gha,scope=${{ matrix.torch }}-${{ matrix.python }} | |
| cache-to: type=gha,scope=${{ matrix.torch }}-${{ matrix.python }},mode=max | |
| platforms: ${{ matrix.platform }} | |
| - name: Create attestation for the image | |
| uses: actions/attest-build-provenance@v3 | |
| with: | |
| subject-name: ${{ vars.DOCKERHUB_USERNAME }}/python-torch:${{ steps.build-tag.outputs.tag }} | |
| subject-digest: ${{ steps.build-push.outputs.digest }} | |
| push-to-registry: true | |
| merge: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| torch: ['2.9.1'] | |
| python: ['3.14.2', '3.14.2-slim'] | |
| index: [cu126] | |
| permissions: | |
| id-token: write # Needed for actions/attest-build-provenance build predicate | |
| attestations: write # Needed for actions/attest-build-provenance attestation upload to repository | |
| artifact-metadata: write # Needed for actions/attest-build-provenance artifact metadata storage records | |
| steps: | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Merge platform images using manifest tool | |
| id: manifest | |
| run: | | |
| # This must match the build job tag generation | |
| tag="$(echo -n "${{ matrix.torch }}${{ matrix.index && format('-{0}', matrix.index) || '' }}-${{ matrix.python }}" | tr -c 'a-zA-Z0-9._-' '[-*]')" | |
| echo "tag=${tag}" >> $GITHUB_OUTPUT | |
| name="$DOCKERHUB_USERNAME/python-torch:${tag}" | |
| echo "name=${name}" >> $GITHUB_OUTPUT | |
| docker buildx imagetools create \ | |
| --tag $name \ | |
| ${name}-amd64 \ | |
| ${name}-arm64 | |
| # Unfortunately we don't get the digest directly so we need to query it | |
| DIGEST=$(docker buildx imagetools inspect "${name}" --format '{{ print .Manifest.Digest }}') | |
| # Ensure the images bundled behind the digest about to be attested still have valid attestations | |
| for digest in $(docker buildx imagetools inspect "$DOCKERHUB_USERNAME/python-torch@$DIGEST" --format '{{ range .Manifest.Manifests }}{{ .Digest }} {{ end }}') | |
| do | |
| gh attestation verify oci://$DOCKERHUB_USERNAME/python-torch@${digest} \ | |
| --repo $GITHUB_REPOSITORY \ | |
| --signer-workflow $GITHUB_WORKFLOW_REF \ | |
| --source-digest $GITHUB_SHA | |
| done | |
| echo "digest=${DIGEST}" >> $GITHUB_OUTPUT | |
| env: | |
| DOCKERHUB_USERNAME: ${{ vars.DOCKERHUB_USERNAME }} | |
| - name: Create attestation for the manifest | |
| uses: actions/attest-build-provenance@v3 | |
| with: | |
| subject-name: ${{ steps.manifest.outputs.name }} | |
| subject-digest: ${{ steps.manifest.outputs.digest }} | |
| push-to-registry: true | |
| description: | |
| needs: merge | |
| # https://github.com/actions/runner-images/blob/main/images/ubuntu-slim/ubuntu-slim-Readme.md | |
| runs-on: ubuntu-slim | |
| if: github.ref == 'refs/heads/main' | |
| permissions: | |
| contents: write # For the tag creation | |
| steps: | |
| # With org.opencontainers.image.source pointing to this repository Dockerfile FROM updates in pull requests can be scanned | |
| # if the commits have matching tags with the image. | |
| # https://github.blog/changelog/2023-04-13-dependabot-now-supports-fetching-release-notes-and-changelogs-for-docker-images/ | |
| # https://octokit.github.io/rest.js/v19#git-create-ref | |
| # https://octokit.github.io/rest.js/v19#git-update-ref | |
| - name: Tag the commit or update tag | |
| if: github.ref == 'refs/heads/main' | |
| uses: actions/github-script@v8 | |
| with: | |
| script: | | |
| try { | |
| await github.rest.git.createRef({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| ref: 'refs/tags/${{ steps.build-tag.outputs.tag }}', | |
| sha: context.sha, | |
| }); | |
| } catch(e) { | |
| if (e.status === 422) { | |
| await github.rest.git.updateRef({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| ref: 'tags/${{ steps.build-tag.outputs.tag }}', | |
| sha: context.sha, | |
| force: true, | |
| }); | |
| } | |
| } | |
| # Can not use Personal Access Token to update the README. Returns FORBIDDEN. | |
| - name: Docker Hub Description | |
| uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5.0.0 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| repository: ${{ vars.DOCKERHUB_USERNAME }}/python-torch |