-
Notifications
You must be signed in to change notification settings - Fork 0
191 lines (170 loc) · 6.83 KB
/
Copy pathplugin-release.yml
File metadata and controls
191 lines (170 loc) · 6.83 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
182
183
184
185
186
187
188
189
190
191
name: Reusable Plugin Release
on:
workflow_call:
permissions: {}
concurrency:
group: plugin-release-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
verify:
name: Verify release bundle
permissions:
contents: read
uses: mpiton/vortex/.github/workflows/plugin-ci.yml@f63e53f866bbdf5e5e3e8f62a37f78e13cec5298
release:
name: Publish immutable GitHub release
if: >-
startsWith(github.ref, 'refs/tags/v') &&
github.actor == github.repository_owner
needs: verify
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
contents: write
steps:
- name: Download verified bundle
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: plugin-release-${{ github.sha }}
path: dist
- name: Verify release metadata
env:
RELEASE_TAG: ${{ github.ref_name }}
shell: bash
run: |
(
cd dist
sha256sum --check SHA256SUMS
)
python3 - <<'PY'
import os
import re
import tomllib
with open("dist/plugin.toml", "rb") as file:
manifest = tomllib.load(file)["plugin"]
tag = os.environ["RELEASE_TAG"]
if tag != f"v{manifest['version']}":
raise SystemExit(
f"tag {tag!r} does not match plugin version {manifest['version']!r}"
)
plugin_name = manifest.get("name")
if not isinstance(plugin_name, str):
raise SystemExit("plugin name is missing from plugin.toml")
release_wasm_asset = f"{plugin_name.replace('-', '_')}.wasm"
if re.fullmatch(r"[A-Za-z_][A-Za-z0-9_]*\.wasm", release_wasm_asset) is None:
raise SystemExit("plugin name cannot be mapped to a release WASM asset")
with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as env:
env.write(f"PLUGIN_WASM_ASSET={release_wasm_asset}\n")
PY
- name: Create or verify immutable release
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
RELEASE_TAG: ${{ github.ref_name }}
shell: bash
run: |
release_assets=(
"plugin.wasm"
"plugin.toml"
"SHA256SUMS"
)
if [[ "${PLUGIN_WASM_ASSET}" != "plugin.wasm" ]]; then
release_assets+=("${PLUGIN_WASM_ASSET}")
fi
release_paths=()
download_patterns=()
for asset in "${release_assets[@]}"; do
test -s "dist/${asset}"
release_paths+=("dist/${asset}")
download_patterns+=(--pattern "${asset}")
done
if ! cmp --silent dist/plugin.wasm "dist/${PLUGIN_WASM_ASSET}"; then
echo "release WASM asset differs from verified plugin.wasm" >&2
exit 1
fi
if ! gh release view "${RELEASE_TAG}" >/dev/null 2>&1; then
gh release create "${RELEASE_TAG}" "${release_paths[@]}" \
--verify-tag \
--generate-notes \
--title "${RELEASE_TAG}"
fi
expected_assets="$(printf '%s\n' "${release_assets[@]}" | LC_ALL=C sort)"
actual_assets="$(gh release view "${RELEASE_TAG}" \
--json assets --jq '.assets[].name' | LC_ALL=C sort)"
if [[ "${actual_assets}" != "${expected_assets}" ]]; then
echo "release asset set differs from the verified bundle" >&2
diff -u <(printf '%s\n' "${expected_assets}") \
<(printf '%s\n' "${actual_assets}") || true
exit 1
fi
published="$(mktemp -d)"
gh release download "${RELEASE_TAG}" --dir "${published}" \
"${download_patterns[@]}"
while IFS= read -r asset; do
if ! cmp --silent "dist/${asset}" "${published}/${asset}"; then
echo "release asset content differs: ${asset}" >&2
exit 1
fi
done <<<"${expected_assets}"
registry-consistency:
name: Check central registry after release
if: startsWith(github.ref, 'refs/tags/v')
needs: release
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions:
contents: read
steps:
- name: Download released bundle
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: plugin-release-${{ github.sha }}
path: dist
- name: Compare release with central registry
id: registry-check
continue-on-error: true
shell: bash
run: |
registry="${RUNNER_TEMP}/registry.toml"
curl --fail --silent --show-error --location \
--proto '=https' --tlsv1.2 \
https://raw.githubusercontent.com/mpiton/vortex/main/registry/registry.toml \
--output "${registry}"
REGISTRY_PATH="${registry}" python3 - <<'PY'
import hashlib
import os
import pathlib
import tomllib
dist = pathlib.Path("dist")
with (dist / "plugin.toml").open("rb") as file:
manifest = tomllib.load(file)["plugin"]
with open(os.environ["REGISTRY_PATH"], "rb") as file:
entries = tomllib.load(file)["plugin"]
matches = [item for item in entries if item["name"] == manifest["name"]]
if not matches:
raise SystemExit("plugin is missing from the central registry")
if len(matches) != 1:
raise SystemExit(
f"expected exactly one registry entry, found {len(matches)}"
)
entry = matches[0]
for key in ("version", "min_vortex_version"):
if entry[key] != manifest[key]:
raise SystemExit(f"registry {key} differs from plugin.toml")
wasm_sha = hashlib.sha256((dist / "plugin.wasm").read_bytes()).hexdigest()
manifest_sha = hashlib.sha256((dist / "plugin.toml").read_bytes()).hexdigest()
if entry["checksum_sha256"] != wasm_sha:
raise SystemExit("registry WASM checksum differs from release artifact")
if entry["checksum_sha256_toml"] != manifest_sha:
raise SystemExit("registry manifest checksum differs from plugin.toml")
PY
- name: Report registry update requirement
if: steps.registry-check.outcome == 'failure'
shell: bash
run: |
echo "::warning title=Registry update required::The release is published, but vortex/registry/registry.toml does not match its assets."
{
echo "### Registry update required"
echo
echo "The release is published and immutable. Update \`vortex/registry/registry.toml\` with its version and checksums."
} >> "${GITHUB_STEP_SUMMARY}"