-
Notifications
You must be signed in to change notification settings - Fork 1
181 lines (165 loc) · 7.35 KB
/
Copy pathrelease.yml
File metadata and controls
181 lines (165 loc) · 7.35 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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
name: Release Images
# Build and publish the three blockstor container images on a version tag.
#
# Images (Dockerfile multi-stage targets → canonical ghcr.io paths):
# - controller → ghcr.io/cozystack/blockstor-controller
# - apiserver → ghcr.io/cozystack/blockstor-apiserver
# - satellite → ghcr.io/cozystack/blockstor-satellite
#
# The repository's dev stand (stand/build-images.sh) builds the exact same
# three targets into a throwaway localhost:5000 registry with a floating
# `:dev` tag. This release flow instead pushes to the canonical public
# registry (ghcr.io, derived from the Go module path
# github.com/cozystack/blockstor and the short image names used by the stand
# manifests: blockstor-controller / blockstor-apiserver / blockstor-satellite).
#
# Tagging is handled by docker/metadata-action's `type=semver` rules:
# tag v1.33.2 → images tagged `1.33.2`, `1.33`, and `latest`.
# Pre-release tags (v1.33.0-rc.1) get `1.33.0-rc.1` only — no `latest`.
# This matches the repo's `vMAJOR.MINOR.PATCH[-rc.N]` tag convention
# (see `git tag -l`).
#
# After the images publish, the workflow ALSO cuts the GitHub Release object
# for the tag (body taken from the matching CHANGELOG.md section).
on:
push:
tags:
- 'v*'
# Manual trigger for re-publishing a tag (e.g. after a registry outage).
# The chosen ref must be a tag for the version stamping to be meaningful.
workflow_dispatch:
# GITHUB_TOKEN needs packages:write to push to ghcr.io; contents:read to
# check out the tagged tree.
permissions:
contents: read
packages: write
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
build-push:
name: Build and push ${{ matrix.image }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
# `target` is the Dockerfile stage; `image` is the ghcr.io repo
# suffix under ghcr.io/${{ github.repository_owner }}/.
- target: controller
image: blockstor-controller
- target: apiserver
image: blockstor-apiserver
- target: satellite
image: blockstor-satellite
steps:
- name: Clone the code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
# Full history so the in-image git SHA stamp (Bug 171) is the real
# commit, not a shallow placeholder. The GIT_HASH build-arg below
# is resolved on the runner where the .git tree exists.
fetch-depth: 0
- name: Set up QEMU
# Enables cross-arch emulation so the satellite's debian apt install
# resolves arm64 packages during the linux/arm64 build leg.
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Log in to GitHub Container Registry
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
with:
images: ghcr.io/${{ github.repository_owner }}/${{ matrix.image }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=ref,event=tag
# Tag `latest` only on a stable (non-pre-release) semver tag.
flavor: |
latest=auto
- name: Resolve build stamps
id: stamp
# Mirrors stand/build-images.sh + the top-level Makefile: the
# Dockerfile excludes .git via .dockerignore, so the SHA/time are
# resolved on the runner and passed in as --build-arg.
run: |
echo "git_hash=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
echo "build_time=$(date -u +%FT%TZ)" >> "$GITHUB_OUTPUT"
- name: Build and push ${{ matrix.image }}
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
file: ./Dockerfile
target: ${{ matrix.target }}
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
# OCI labels from metadata-action include
# org.opencontainers.image.source=<repo URL>, which lets GHCR
# auto-link each published package to cozystack/blockstor and inherit
# the repo's visibility. `annotations` carries the same metadata onto
# the multi-arch image index manifest.
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
build-args: |
GIT_HASH=${{ steps.stamp.outputs.git_hash }}
BUILD_TIME=${{ steps.stamp.outputs.build_time }}
provenance: false
github-release:
name: Create GitHub Release
# After all three images publish, cut the GitHub Release for the tag:
# title = the tag, body = the matching "## <tag> — <date>" section of
# CHANGELOG.md (the same content used for prior releases). Pre-release tags
# (vMAJOR.MINOR.PATCH-rc.N / -alpha / -beta) are marked pre-release and not
# "Latest". Idempotent: updates the release if it already exists (re-run).
needs: build-push
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Clone the code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Cut the GitHub Release from the CHANGELOG section
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
# vMAJOR.MINOR.PATCH[-rc.N] convention: pre-release tags are not Latest.
prerelease=()
latest=(--latest)
case "$TAG" in
*-rc*|*-alpha*|*-beta*) prerelease=(--prerelease); latest=(--latest=false) ;;
esac
# Body = the CHANGELOG.md section under "## <tag> — <date>", up to the
# next "## " heading; leading/trailing blank lines trimmed.
notes="$(mktemp)"
awk -v tag="$TAG" '
index($0, "## " tag " ") == 1 { f=1; next }
f && /^## / { exit }
f { print }
' CHANGELOG.md | sed '/./,$!d' > "$notes"
awk 'NF{p=NR} {a[NR]=$0} END{for (i=1;i<=p;i++) print a[i]}' "$notes" > "$notes.trim"
mv "$notes.trim" "$notes"
if gh release view "$TAG" >/dev/null 2>&1; then
echo "Release $TAG already exists; updating it."
edit_body=()
[ -s "$notes" ] && edit_body=(--notes-file "$notes")
gh release edit "$TAG" --title "$TAG" "${edit_body[@]}" "${prerelease[@]}" "${latest[@]}"
elif [ -s "$notes" ]; then
gh release create "$TAG" --title "$TAG" --verify-tag --notes-file "$notes" "${prerelease[@]}" "${latest[@]}"
else
echo "::warning::CHANGELOG.md has no section for $TAG; using auto-generated notes."
gh release create "$TAG" --title "$TAG" --verify-tag --generate-notes "${prerelease[@]}" "${latest[@]}"
fi