From 0d88d95b4635e7fdfe5f9e29bc608647e9f788bd Mon Sep 17 00:00:00 2001 From: Andrew Ring Date: Mon, 15 Jun 2026 23:53:42 -0500 Subject: [PATCH 1/6] Add Docker image publishing to release workflow Adds a docker job that reuses the already-built static Linux binaries to build and push multi-arch (amd64/arm64) images to GHCR. Uses a minimal scratch-based Dockerfile with no Rust compilation inside Docker. Images are tagged with semver versions (e.g. 0.1.12, 0.1, 0) and published to ghcr.io/andrewring/github-distributed-owners. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 59 ++++++++++++++++++++++++++++++++-- Dockerfile | 4 +++ 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 Dockerfile diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0c112cb..cde458b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,5 +1,5 @@ -name: Release Binaries -run-name: Release Binaries (${{ inputs.tag || github.event.release.tag_name }}) +name: Release +run-name: Release (${{ inputs.tag || github.event.release.tag_name }}) on: release: @@ -149,3 +149,58 @@ jobs: flags+=(--clobber) fi gh release upload "$TAG" artifacts/* "${flags[@]}" + + docker: + name: Push Docker Image + needs: build + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + steps: + - uses: actions/checkout@v6 + with: + ref: ${{ env.TAG }} + sparse-checkout: Dockerfile + sparse-checkout-cone-mode: false + + - name: Download Linux artifacts + uses: actions/download-artifact@v4 + with: + pattern: github-distributed-owners-linux-* + merge-multiple: true + + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to GHCR + uses: docker/login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v6 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=semver,pattern={{version}},value=${{ env.TAG }} + type=semver,pattern={{major}}.{{minor}},value=${{ env.TAG }} + type=semver,pattern={{major}},value=${{ env.TAG }} + + - name: Build and push + uses: docker/build-push-action@v7 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1cb5e55 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM scratch +ARG TARGETARCH +COPY github-distributed-owners-linux-${TARGETARCH} /github-distributed-owners +ENTRYPOINT ["/github-distributed-owners"] From 554ab542314951d664529d04178a1af6307074f3 Mon Sep 17 00:00:00 2001 From: Andrew Ring Date: Tue, 16 Jun 2026 14:14:37 -0500 Subject: [PATCH 2/6] Generate Dockerfile inline instead of checking out from tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Old tags don't have the Dockerfile, so checking out at the tag ref fails. Generate it inline in the workflow instead — the repo copy remains for documentation/discoverability. Also removes the now-unnecessary contents: read permission from the docker job. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index cde458b..34204e4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -155,17 +155,19 @@ jobs: needs: build runs-on: ubuntu-latest permissions: - contents: read packages: write env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} steps: - - uses: actions/checkout@v6 - with: - ref: ${{ env.TAG }} - sparse-checkout: Dockerfile - sparse-checkout-cone-mode: false + - name: Create Dockerfile + run: | + cat > Dockerfile <<'DOCKERFILE' + FROM scratch + ARG TARGETARCH + COPY github-distributed-owners-linux-${TARGETARCH} /github-distributed-owners + ENTRYPOINT ["/github-distributed-owners"] + DOCKERFILE - name: Download Linux artifacts uses: actions/download-artifact@v4 From 3b96a68030c2fe7892888f6ebcd45eab99cfa7ea Mon Sep 17 00:00:00 2001 From: Andrew Ring Date: Tue, 16 Jun 2026 14:21:01 -0500 Subject: [PATCH 3/6] Remove unused Dockerfile The docker job generates this inline in the workflow, so the repo copy is dead code. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- Dockerfile | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 1cb5e55..0000000 --- a/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM scratch -ARG TARGETARCH -COPY github-distributed-owners-linux-${TARGETARCH} /github-distributed-owners -ENTRYPOINT ["/github-distributed-owners"] From 50d4dbca8d0ef6832f3a8ca49071f8d145bb6a1c Mon Sep 17 00:00:00 2001 From: Andrew Ring Date: Tue, 16 Jun 2026 15:47:14 -0500 Subject: [PATCH 4/6] Add cargo caching and fix floating Docker tags on backfill - Add Swatinem/rust-cache to the build matrix for faster re-runs and sequential backfill builds - Add update_tags input to workflow_dispatch (default: false) to control whether floating Docker tags (latest, major, major.minor) are updated. Backfill runs now only push the exact version tag. The release trigger always updates all tags. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 34204e4..11becb3 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,6 +15,11 @@ on: required: false type: boolean default: false + update_tags: + description: "Update floating Docker tags (latest, major, major.minor)" + required: false + type: boolean + default: false permissions: contents: read @@ -94,6 +99,10 @@ jobs: - name: Add Rust target run: rustup target add ${{ matrix.target }} + - uses: Swatinem/rust-cache@v2 + with: + key: ${{ matrix.target }} + - name: Build run: cargo build --release --locked --target ${{ matrix.target }} @@ -193,10 +202,12 @@ jobs: uses: docker/metadata-action@v6 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + flavor: | + latest=${{ github.event_name == 'release' || inputs.update_tags }} tags: | type=semver,pattern={{version}},value=${{ env.TAG }} - type=semver,pattern={{major}}.{{minor}},value=${{ env.TAG }} - type=semver,pattern={{major}},value=${{ env.TAG }} + type=semver,pattern={{major}}.{{minor}},value=${{ env.TAG }},enable=${{ github.event_name == 'release' || inputs.update_tags }} + type=semver,pattern={{major}},value=${{ env.TAG }},enable=${{ github.event_name == 'release' || inputs.update_tags }} - name: Build and push uses: docker/build-push-action@v7 From 933395559b6c2c36941246c6196029b1f8245d4c Mon Sep 17 00:00:00 2001 From: Andrew Ring Date: Tue, 16 Jun 2026 15:49:38 -0500 Subject: [PATCH 5/6] Fix execute permission on binary in Docker image Artifact upload/download strips the execute bit. Use COPY --chmod=755 (supported by BuildKit/buildx) to restore it in the scratch image. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 11becb3..25704b8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -174,7 +174,7 @@ jobs: cat > Dockerfile <<'DOCKERFILE' FROM scratch ARG TARGETARCH - COPY github-distributed-owners-linux-${TARGETARCH} /github-distributed-owners + COPY --chmod=755 github-distributed-owners-linux-${TARGETARCH} /github-distributed-owners ENTRYPOINT ["/github-distributed-owners"] DOCKERFILE From bca9ad3638a1b385ef3f9faca4df1d650b1fc695 Mon Sep 17 00:00:00 2001 From: Andrew Ring Date: Tue, 16 Jun 2026 15:53:54 -0500 Subject: [PATCH 6/6] Add release summary with parameters to workflow log and summary Adds a summary job that logs all workflow parameters (tag, commit, trigger, actor, clobber, update_tags) to both the Actions log and the job summary page as a markdown table. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 25704b8..41d8b86 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -28,6 +28,29 @@ env: TAG: ${{ inputs.tag || github.event.release.tag_name }} jobs: + summary: + name: Release Summary + runs-on: ubuntu-latest + steps: + - name: Log parameters + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + run: | + commit=$(gh api "repos/$GH_REPO/git/ref/tags/$TAG" --jq '.object.sha' 2>/dev/null || echo "unknown") + { + echo "## Release Parameters" + echo "" + echo "| Parameter | Value |" + echo "| --- | --- |" + echo "| **Tag** | \`$TAG\` |" + echo "| **Commit** | \`${commit:0:12}\` |" + echo "| **Trigger** | \`${{ github.event_name }}\` |" + echo "| **Actor** | @${{ github.actor }} |" + echo "| **Clobber** | \`${{ inputs.clobber || false }}\` |" + echo "| **Update floating tags** | \`${{ inputs.update_tags || false }}\` |" + } | tee -a "$GITHUB_STEP_SUMMARY" + validate: name: Validate Release Tag if: github.event_name == 'workflow_dispatch'