Repository navigation
166 lines (146 loc) · 6.51 KB
/
Copy pathrelease.yml
File metadata and controls
166 lines (146 loc) · 6.51 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
name: release
# Version tags only. The glob is the closest GitHub's filter syntax gets to
# semver -- it has no way to say "no leading zeros" or to spell the prerelease
# grammar -- so anything obviously not a version (`nightly`, `v2-wip`, a moving
# `latest`) never starts a run, and the gate job below re-checks what does
# against the real thing. A tag that gets past the glob but fails the check is
# skipped rather than failed: an unrecognised tag is not an error, it just is
# not a release.
on:
push:
tags: ['v[0-9]+.[0-9]+.[0-9]+*']
permissions:
contents: read
jobs:
gate:
name: check tag
runs-on: ubuntu-latest
outputs:
release: ${{ steps.check.outputs.release }}
version: ${{ steps.check.outputs.version }}
# Debian maps SemVer prerelease punctuation into its own ordering syntax.
package: ${{ steps.check.outputs.package }}
prerelease: ${{ steps.check.outputs.prerelease }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- id: check
run: |
tag=$GITHUB_REF_NAME
version=${tag#v}
# semver.org's published regex, with its named groups dropped.
semver='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)'
semver+='(-((0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)'
semver+='(\.(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*))?'
semver+='(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?$'
if [[ ! $version =~ $semver ]]; then
echo "release=false" >> "$GITHUB_OUTPUT"
echo "\`$tag\` is not a semver version tag; nothing built." \
>> "$GITHUB_STEP_SUMMARY"
exit 0
fi
# Ask the same resolver the packages call. On a tag this must be the
# tag verbatim (minus v); checking it here catches checkout/ref bugs
# before four architecture jobs do expensive work.
manifest=$(mktemp)
cmake -DSOURCE_DIR=. -DOUTPUT_MANIFEST="$manifest" \
-P cmake/version.cmake
resolved=$(sed -n 's/^set(CORELET_VERSION "\(.*\)")$/\1/p' "$manifest")
package=$(sed -n 's/^set(CORELET_VERSION_DEBIAN "\(.*\)")$/\1/p' "$manifest")
if [ "$resolved" != "$version" ] || [ -z "$package" ]; then
echo "::error::tag $tag resolved as '$resolved' (Debian '$package')"
exit 1
fi
# A prerelease is the -suffix only; build metadata after + may
# contain a hyphen of its own and says nothing about stability.
prerelease=false
[[ ${version%%+*} == *-* ]] && prerelease=true
echo "release=true" >> "$GITHUB_OUTPUT"
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "package=$package" >> "$GITHUB_OUTPUT"
echo "prerelease=$prerelease" >> "$GITHUB_OUTPUT"
# The same workflows that build every push, called rather than copied so a
# release cannot be built differently from what CI has been testing all along.
debian:
needs: gate
if: needs.gate.outputs.release == 'true'
uses: ./.github/workflows/debian.yml
macos:
needs: gate
if: needs.gate.outputs.release == 'true'
uses: ./.github/workflows/macos.yml
# One release for all four packages, and only once every one of them is
# built: a release missing an architecture is worse than one that arrives a
# few minutes later. Skipping either build job skips this too.
publish:
needs: [gate, debian, macos]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
with:
pattern: corelet-*
merge-multiple: true
path: dist
# The gate resolved the tag on its own runner; each package job resolves
# it again on its own. v0.1.0 shipped with the two of them disagreeing --
# correct DMGs beside debs that called themselves 0.0.0, because the
# container builds could not read the checkout and said so to nobody.
# Every asset carries its version in its name, so the tag can be checked
# against what four separate jobs actually produced, one step before the
# release exists.
- name: Check the packages carry the tag's version
working-directory: dist
run: |
wrong=
for f in corelet_*.deb; do
case $f in
corelet_${{ needs.gate.outputs.package }}_*.deb) ;;
*) wrong="$wrong $f" ;;
esac
done
for f in Corelet-*.dmg; do
case $f in
Corelet-${{ needs.gate.outputs.version }}-*.dmg) ;;
*) wrong="$wrong $f" ;;
esac
done
if [ -n "$wrong" ]; then
echo "::error::$GITHUB_REF_NAME did not build as itself:$wrong"
exit 1
fi
# Nothing here is notarized or signed with a key anyone can check
# against, so the checksums are the only way a download can be verified
# at all. The -dbgsym packages stay out of the release: they are for
# debugging a build you already have, and they would double the asset
# list on the page people come to for one file.
- name: Checksums
working-directory: dist
run: |
sha256sum corelet_*.deb Corelet-*.dmg | tee SHA256SUMS
- uses: softprops/action-gh-release@v2
with:
name: Corelet ${{ needs.gate.outputs.version }}
prerelease: ${{ needs.gate.outputs.prerelease }}
fail_on_unmatched_files: true
generate_release_notes: true
files: |
dist/corelet_*.deb
dist/Corelet-*.dmg
dist/SHA256SUMS
body: |
## Install
**uConsole and other Debian machines** -- `arm64` for the uConsole,
`amd64` for an x86 desktop. Installing the file rather than the
bare name is what pulls the Qt runtime in with it:
sudo apt install ./corelet_${{ needs.gate.outputs.package }}_arm64.deb
**macOS** -- `arm64` for Apple Silicon, `x86_64` for Intel. The
disk images want macOS 15 or newer, since the Qt inside them is a
Homebrew bottle built for that release.
The macOS builds are ad-hoc signed, not notarized, so Gatekeeper
refuses them on first launch and the Control-click bypass no
longer works. Open the app once from System Settings > Privacy &
Security > Open Anyway, or run
xattr -dr com.apple.quarantine /Applications/Corelet.app