-
Notifications
You must be signed in to change notification settings - Fork 0
148 lines (135 loc) · 5.87 KB
/
Copy pathrelease.yml
File metadata and controls
148 lines (135 loc) · 5.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
name: Release — publish image to Docker Hub
# When this workflow fires:
# - push to main: publishes `devonartis/agentwrit:latest` and
# `devonartis/agentwrit:main-<sha>` so every main commit is traceable.
# - push of a `v*` tag: publishes semver tags `v2.0.0`, `v2.0`, `v2` AND
# updates `latest`. Tag the release commit AFTER it lands on main so the
# same image is promoted (not rebuilt) when possible.
#
# Why not on `develop` or PRs: `develop` is private dev state (we don't want
# that image downloaded by operators), and PR runs can't access secrets on
# public repos — so DOCKERHUB_TOKEN would be empty and the login step fails.
#
# What this workflow needs (set manually, one-time):
# - Docker Hub repo `devonartis/agentwrit` exists and is public
# - GitHub repo secrets:
# DOCKERHUB_USERNAME = devonartis
# DOCKERHUB_TOKEN = PAT scoped to read+write on agentwrit only
#
# Multi-arch note: amd64 + arm64 built via QEMU emulation on the x86 runner.
# Build is ~2-3x longer than amd64-only but covers Apple Silicon, Raspberry
# Pi, and ARM cloud hosts. If this becomes a bottleneck, switch to a matrix
# with native arm64 runners (GitHub's arm64 hosted runners are in preview
# for public repos — TD worth opening when we're paying attention to build
# latency).
#
# Supply-chain: the released image is signed with cosign keyless
# (OIDC-issued Sigstore certificate from GitHub Actions workload identity).
# Verify with:
# cosign verify devonartis/agentwrit:latest \
# --certificate-identity-regexp='^https://github.com/devonartis/agentwrit/.github/workflows/release.yml@' \
# --certificate-oidc-issuer=https://token.actions.githubusercontent.com
on:
push:
branches: [main]
tags: ['v*']
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false # never cancel a release mid-push
permissions:
contents: read
jobs:
publish:
name: publish-dockerhub
runs-on: ubuntu-latest
permissions:
contents: read
packages: write # not used for Docker Hub, but future-proof if we mirror to GHCR
id-token: write # required for cosign keyless signing (OIDC)
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up QEMU (for arm64 via emulation)
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Log in to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract image metadata (tags + labels)
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
with:
images: devonartis/agentwrit
# Tagging strategy:
# - `latest` — only on default branch push (main)
# - `main-<sha>` — every main push for reproducibility
# - `v1.2.3` etc. — semver tags when a release tag is pushed
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=main-${{ github.sha }},enable={{is_default_branch}}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
labels: |
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.created=${{ github.event.head_commit.timestamp }}
- name: Build and push multi-arch image
id: build
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
context: .
target: broker
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
provenance: mode=max
sbom: true
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Install cosign
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
- name: Sign the published image (keyless)
# Signs EVERY tag the build-push step emitted, using the image digest
# to avoid signing a moving target. Keyless mode uses GitHub OIDC to
# get a short-lived Sigstore certificate — no long-lived signing key
# to rotate or leak. Verify on the pull side with `cosign verify`.
env:
TAGS: ${{ steps.meta.outputs.tags }}
DIGEST: ${{ steps.build.outputs.digest }}
run: |
set -euo pipefail
for tag in $TAGS; do
echo "Signing ${tag}@${DIGEST}"
cosign sign --yes "${tag}@${DIGEST}"
done
- name: Publish summary
env:
TAGS: ${{ steps.meta.outputs.tags }}
DIGEST: ${{ steps.build.outputs.digest }}
run: |
{
echo "## Published image"
echo ""
echo "| Field | Value |"
echo "|---|---|"
echo "| Registry | Docker Hub |"
echo "| Repository | \`devonartis/agentwrit\` |"
echo "| Digest | \`${DIGEST}\` |"
echo "| Platforms | \`linux/amd64\`, \`linux/arm64\` |"
echo "| Signed | keyless (cosign + Sigstore) |"
echo ""
echo "### Tags"
for tag in $TAGS; do
echo "- \`$tag\`"
done
echo ""
echo "### Pull"
echo '```bash'
echo "docker pull devonartis/agentwrit:latest"
echo '```'
} >> "$GITHUB_STEP_SUMMARY"