-
Notifications
You must be signed in to change notification settings - Fork 0
112 lines (101 loc) · 4.38 KB
/
release.yml
File metadata and controls
112 lines (101 loc) · 4.38 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
name: Release
# NEU-B.4: enforce that every published release tag is GPG-signed (or
# annotated and signed via SSH/Sigstore-equivalent), then publish a
# minimal release with the source tarball + an `IMAGE_DIGEST.txt`
# attestation pointing at the cosign-signed container image.
#
# A Compliance-edition operator who pulls a tagged release can verify
# two independent claims:
# 1. The git tag is GPG-signed by a maintainer key listed in
# docs/release-signing.md.
# 2. The corresponding container image is cosign-signed via Sigstore
# (see workflows/docker.yml).
#
# This workflow runs on tag push only. It does NOT make new tags;
# tag creation stays a maintainer's local action so the GPG private
# key never leaves their machine.
on:
push:
tags: ["v*"]
permissions:
contents: write
jobs:
verify-and-publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # need full history so `git verify-tag` can resolve
- name: Import maintainer GPG public keys
run: |
# Maintainer public keys live in docs/release-signing.md as
# ASCII-armored blocks delimited by ----BEGIN PGP PUBLIC KEY BLOCK----.
# Extract and import every block we find.
if [[ -f docs/release-signing.md ]]; then
awk '
/-----BEGIN PGP PUBLIC KEY BLOCK-----/ {flag=1}
flag {print}
/-----END PGP PUBLIC KEY BLOCK-----/ {flag=0; print ""}
' docs/release-signing.md > /tmp/maintainer-keys.asc
if [[ -s /tmp/maintainer-keys.asc ]]; then
gpg --import /tmp/maintainer-keys.asc
else
echo "::error::No PGP public keys found in docs/release-signing.md. Add a maintainer key block before publishing a release."
exit 1
fi
else
echo "::error::docs/release-signing.md missing — cannot verify tag signature. Restore the file or add a maintainer key block."
exit 1
fi
- name: Verify tag is GPG-signed
run: |
TAG="${GITHUB_REF#refs/tags/}"
if ! git verify-tag "$TAG"; then
echo "::error::Tag $TAG is not signed by a maintainer key listed in docs/release-signing.md."
echo "Maintainers create signed tags with: git tag -s vX.Y.Z -m 'release vX.Y.Z'"
exit 1
fi
echo "Tag $TAG verified."
- name: Build source tarball
run: |
TAG="${GITHUB_REF#refs/tags/}"
git archive --format=tar.gz --prefix="filemorph-${TAG}/" \
-o "filemorph-${TAG}.tar.gz" "$TAG"
- name: Wait for cosign-signed container image
# The Docker workflow runs in parallel on the same tag push; give
# it a head-start so the digest reference is meaningful when the
# release notes are written. If the image hasn't been pushed yet,
# the digest pointer is omitted — the release still publishes.
run: sleep 60
- name: Resolve image digest (best-effort)
id: digest
run: |
TAG="${GITHUB_REF#refs/tags/}"
IMAGE="ghcr.io/${GITHUB_REPOSITORY,,}:${TAG#v}"
echo "image=$IMAGE" >> "$GITHUB_OUTPUT"
# Try to resolve the digest from GHCR; tolerate failure so a
# transient registry blip doesn't block the source release.
if DIGEST=$(docker buildx imagetools inspect "$IMAGE" --format '{{json .Manifest.Digest}}' 2>/dev/null | tr -d '"'); then
echo "digest=$DIGEST" >> "$GITHUB_OUTPUT"
else
echo "digest=" >> "$GITHUB_OUTPUT"
fi
- name: Write image-digest attestation
run: |
TAG="${GITHUB_REF#refs/tags/}"
{
echo "Image: ${{ steps.digest.outputs.image }}"
echo "Digest: ${{ steps.digest.outputs.digest }}"
echo ""
echo "Verify the cosign signature with:"
echo " cosign verify ${{ steps.digest.outputs.image }} \\"
echo " --certificate-identity-regexp '^https://github\\.com/${GITHUB_REPOSITORY}/' \\"
echo " --certificate-oidc-issuer https://token.actions.githubusercontent.com"
} > IMAGE_DIGEST.txt
- name: Publish release
uses: softprops/action-gh-release@v2
with:
files: |
filemorph-*.tar.gz
IMAGE_DIGEST.txt
generate_release_notes: true