feat: publish tag without patch version #37
Workflow file for this run
This file contains 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
# Build and publish a Docker image. | |
# | |
# Assumed to run as a subworkflow of .github/workflows/release.yml; specifically, as a local | |
# artifacts job within `cargo-dist`. | |
# | |
# TODO(charlie): Ideally, the publish step would happen as a publish job within `cargo-dist`, but | |
# sharing the built image as an artifact between jobs is challenging. | |
name: "Build Docker image" | |
on: | |
workflow_call: | |
inputs: | |
plan: | |
required: true | |
type: string | |
pull_request: | |
paths: | |
- .github/workflows/build-docker.yml | |
env: | |
UV_BASE_IMG: ghcr.io/${{ github.repository_owner }}/uv | |
jobs: | |
docker-build: | |
name: Build Docker image (ghcr.io/astral-sh/uv) for ${{ matrix.platform }} | |
runs-on: ubuntu-latest | |
environment: | |
name: release | |
strategy: | |
fail-fast: false | |
matrix: | |
platform: | |
- linux/amd64 | |
- linux/arm64 | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
submodules: recursive | |
- uses: docker/setup-buildx-action@v3 | |
- uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Extract metadata (tags, labels) for Docker | |
id: meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: ${{ env.UV_BASE_IMG }} | |
- name: Check tag consistency | |
if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }} | |
run: | | |
version=$(grep "version = " pyproject.toml | sed -e 's/version = "\(.*\)"/\1/g') | |
if [ "${{ fromJson(inputs.plan).announcement_tag }}" != "${version}" ]; then | |
echo "The input tag does not match the version from pyproject.toml:" >&2 | |
echo "${{ fromJson(inputs.plan).announcement_tag }}" >&2 | |
echo "${version}" >&2 | |
exit 1 | |
else | |
echo "Releasing ${version}" | |
fi | |
- name: Normalize Platform Pair (replace / with -) | |
run: | | |
platform=${{ matrix.platform }} | |
echo "PLATFORM_TUPLE=${platform//\//-}" >> $GITHUB_ENV | |
# Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/ | |
- name: Build and push by digest | |
id: build | |
uses: docker/build-push-action@v6 | |
with: | |
context: . | |
platforms: ${{ matrix.platform }} | |
cache-from: type=gha,scope=uv-${{ env.PLATFORM_TUPLE }} | |
cache-to: type=gha,mode=min,scope=uv-${{ env.PLATFORM_TUPLE }} | |
labels: ${{ steps.meta.outputs.labels }} | |
outputs: type=image,name=${{ env.UV_BASE_IMG }},push-by-digest=true,name-canonical=true,push=${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }} | |
- name: Export digests | |
run: | | |
mkdir -p /tmp/digests | |
digest="${{ steps.build.outputs.digest }}" | |
touch "/tmp/digests/${digest#sha256:}" | |
- name: Upload digests | |
uses: actions/upload-artifact@v4 | |
with: | |
name: digests-${{ env.PLATFORM_TUPLE }} | |
path: /tmp/digests/* | |
if-no-files-found: error | |
retention-days: 1 | |
docker-publish: | |
name: Publish Docker image (ghcr.io/astral-sh/uv) | |
runs-on: ubuntu-latest | |
environment: | |
name: release | |
needs: | |
- docker-build | |
if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }} | |
steps: | |
- name: Download digests | |
uses: actions/download-artifact@v4 | |
with: | |
path: /tmp/digests | |
pattern: digests-* | |
merge-multiple: true | |
- uses: docker/setup-buildx-action@v3 | |
- name: Extract metadata (tags, labels) for Docker | |
id: meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: ${{ env.UV_BASE_IMG }} | |
tags: | | |
type=pep440,pattern={{ version }},value=${{ fromJson(inputs.plan).announcement_tag }} | |
type=pep440,pattern={{ major }}.{{ minor }},value=${{ fromJson(inputs.plan).announcement_tag }} | |
- uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
# Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/ | |
- name: Create manifest list and push | |
working-directory: /tmp/digests | |
# The jq command expands the docker/metadata json "tags" array entry to `-t tag1 -t tag2 ...` for each tag in the array | |
# The printf will expand the base image with the `<UV_BASE_IMG>@sha256:<sha256> ...` for each sha256 in the directory | |
# The final command becomes `docker buildx imagetools create -t tag1 -t tag2 ... <UV_BASE_IMG>@sha256:<sha256_1> <UV_BASE_IMG>@sha256:<sha256_2> ...` | |
run: | | |
docker buildx imagetools create \ | |
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ | |
$(printf '${{ env.UV_BASE_IMG }}@sha256:%s ' *) |