1- # This is largely adapted from past and recent versions of the ripgrep release workflow.
1+ # Much of this workflow is adapted from the ripgrep release workflow.
22# https://github.com/BurntSushi/ripgrep/blob/master/.github/workflows/release.yml
33
44name : release
1212 tags :
1313 - ' v*'
1414
15- env :
16- RUST_BACKTRACE : 1
17- CARGO_TERM_COLOR : always
18- CLICOLOR : 1
19-
2015defaults :
2116 run :
2217 shell : bash
2318
2419jobs :
25- # The create-release job runs purely to initialize the GitHub release itself,
26- # and names the release after the version tag that was pushed. It's separate
27- # from building the release so that we only create the release once.
20+ # Create a draft release, initially with no binary assets attached.
2821 create-release :
29- name : create-release
3022 runs-on : ubuntu-latest
23+
3124# env:
3225# # Set to force version number, e.g., when no tag exists.
3326# VERSION: TEST-0.0.0
27+
3428 steps :
35- - name : Create artifacts directory
36- run : mkdir artifacts
29+ - name : Checkout repository
30+ uses : actions/checkout@v4
3731
3832 - name : Get the release version from the tag
3933 if : env.VERSION == ''
40- run : echo 'VERSION=${{ github.ref_name }}' >> "$GITHUB_ENV"
34+ run : echo "VERSION=$REF_NAME" >> "$GITHUB_ENV"
35+ env :
36+ REF_NAME : ${{ github.ref_name }}
4137
42- - name : Create GitHub release
43- id : release
44- uses : ncipollo/release-action@v1
45- with :
46- tag : ${{ env.VERSION }}
47- name : ${{ env.VERSION }}
48- allowUpdates : true
49- omitBody : true
50- omitPrereleaseDuringUpdate : true
51- token : ${{ secrets.GITHUB_TOKEN }}
38+ - name : Validate version against Cargo.toml
39+ run : |
40+ manifest_version="$(yq -r .package.version Cargo.toml)"
41+ echo "version to name the release: $VERSION"
42+ echo "version Cargo.toml suggests: v$manifest_version"
5243
53- - name : Save release upload URL to artifact
54- run : echo '${{ steps.release.outputs.upload_url }}' > artifacts/release-upload-url
44+ case "$VERSION" in
45+ "v$manifest_version" )
46+ echo 'OK: Release name/version agrees with Cargo.toml version.'
47+ ;;
48+ TEST-* | *-DO-NOT-USE )
49+ echo 'OK: Release name/version is strange but marked as such.'
50+ ;;
51+ "$manifest_version" )
52+ echo 'STOPPING: Release name/version is missing the leading "v".'
53+ exit 1
54+ ;;
55+ * )
56+ echo 'STOPPING: Release name/version and Cargo.toml version do not match.'
57+ echo 'STOPPING: Usually this means either a wrong tag name or wrong version in Cargo.toml.'
58+ echo 'STOPPING: If intended, prepend `TEST-` or append `-DO-NOT-USE` to the release name.'
59+ exit 1
60+ ;;
61+ esac
5562
56- - name : Save version number to artifact
57- run : echo "$VERSION" > artifacts/release-version
63+ - name : Create GitHub release
64+ run : gh release create "$VERSION" --title="$VERSION" --draft
65+ env :
66+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
5867
59- - name : Upload artifacts
60- uses : actions/upload-artifact@v4
61- with :
62- name : artifacts
63- path : artifacts
68+ outputs :
69+ version : ${{ env.VERSION }}
6470
71+ # Build for a particular feature and target, and attach an archive for it.
6572 build-release :
66- name : build-release
67-
6873 needs : [ create-release ]
6974
7075 strategy :
7883 - x86_64-pc-windows-gnu
7984 - i686-pc-windows-msvc
8085 - aarch64-pc-windows-msvc
81- feature :
82- - small
83- - lean
84- - max
85- - max-pure
86+ # When changing these features, make the same change in build-macos-universal2-release.
87+ feature : [ small, lean, max, max-pure ]
8688 include :
8789 - target : x86_64-unknown-linux-musl
8890 os : ubuntu-latest
@@ -128,21 +130,28 @@ jobs:
128130 runs-on : ${{ matrix.os }}
129131
130132 env :
131- CARGO : cargo # On Linux, this will be changed to `cross` later.
133+ RUST_BACKTRACE : ' 1' # Emit backtraces on panics.
134+ CARGO_TERM_COLOR : always
135+ CLICOLOR : ' 1'
136+ CARGO : cargo # On Linux, this will be changed to `cross` in a later step.
137+ FEATURE : ${{ matrix.feature }}
138+ VERSION : ${{ needs.create-release.outputs.version }}
139+ TARGET : ${{ matrix.target }}
132140 TARGET_FLAGS : --target=${{ matrix.target }}
133- TARGET_DIR : ./target/${{ matrix.target }}
134- RUST_BACKTRACE : 1 # Emit backtraces on panics.
141+ TARGET_DIR : target/${{ matrix.target }}
135142
136143 steps :
137144 - name : Checkout repository
138145 uses : actions/checkout@v4
139146
140147 - name : Install packages (Ubuntu)
141- # Because openssl doesn't work on musl by default, we resort to max-pure. And that won't need any dependency, so we can skip this.continue-on-error
148+ # Because openssl doesn't work on musl by default, we resort to max-pure.
149+ # And that won't need any dependency, so we can skip this or use `continue-on-error`.
142150 # Once we want to support better zlib performance, we might have to re-add it.
143151 if : matrix.os == 'ubuntu-latest-disabled'
144152 run : |
145- sudo apt-get update && sudo apt-get install -y --no-install-recommends xz-utils liblz4-tool musl-tools
153+ sudo apt-get update
154+ sudo apt-get install -y --no-install-recommends xz-utils liblz4-tool musl-tools
146155
147156 - name : Install Rust
148157 uses : dtolnay/rust-toolchain@master
@@ -162,20 +171,9 @@ jobs:
162171 echo "target flag is: $TARGET_FLAGS"
163172 echo "target dir is: $TARGET_DIR"
164173
165- - name : Get release download URL
166- uses : actions/download-artifact@v4
167- with :
168- name : artifacts
169- path : artifacts
170-
171- - name : Set release upload URL and release version
172- run : |
173- echo "UPLOAD_URL=$(< artifacts/release-upload-url)" >> "$GITHUB_ENV"
174- echo "VERSION=$(< artifacts/release-version)" >> "$GITHUB_ENV"
175-
176174 - name : Build release binary
177175 run : |
178- "$CARGO" build --verbose --release "$TARGET_FLAGS" --no-default-features --features ${{ matrix.feature }}
176+ "$CARGO" build --verbose --release "$TARGET_FLAGS" --no-default-features --features "$FEATURE"
179177
180178 - name : Strip release binary (x86-64 Linux, and all macOS)
181179 if : matrix.target == 'x86_64-unknown-linux-musl' || matrix.os == 'macos-latest'
@@ -191,31 +189,164 @@ jobs:
191189 /target/arm-unknown-linux-gnueabihf/release/ein \
192190 /target/arm-unknown-linux-gnueabihf/release/gix
193191
194- - name : Build archive
192+ - name : Determine archive basename
193+ run : echo "ARCHIVE=gitoxide-$FEATURE-$VERSION-$TARGET" >> "$GITHUB_ENV"
194+
195+ - name : Pre-populate directory for archive
195196 run : |
196- staging='gitoxide-${{ matrix.feature }}-${{ env.VERSION }}-${{ matrix.target }}'
197- mkdir -p -- "$staging "
197+ mkdir -- "$ARCHIVE"
198+ cp {README.md,LICENSE-*,CHANGELOG.md} "$ARCHIVE/ "
198199
199- cp {README.md,LICENSE-*,CHANGELOG.md} "$staging/"
200+ - name : Build archive (Windows)
201+ if : matrix.os == 'windows-latest'
202+ run : |
203+ file -- "$TARGET_DIR"/release/{ein,gix}.exe
204+ cp -- "$TARGET_DIR"/release/{ein,gix}.exe "$ARCHIVE/"
205+ 7z a "$ARCHIVE.zip" "$ARCHIVE"
206+ /usr/bin/core_perl/shasum --algorithm=256 --binary "$ARCHIVE.zip" > "$ARCHIVE.zip.sha256"
207+ echo "ASSET=$ARCHIVE.zip" >> "$GITHUB_ENV"
208+ echo "ASSET_SUM=$ARCHIVE.zip.sha256" >> "$GITHUB_ENV"
200209
201- if [ '${{ matrix.os }}' = 'windows-latest' ]; then
202- file -- "$TARGET_DIR"/release/{ein,gix}.exe
203- cp -- "$TARGET_DIR"/release/{ein,gix}.exe "$staging/"
204- 7z a "$staging.zip" "$staging"
205- echo "ASSET=$staging.zip" >> "$GITHUB_ENV"
206- else
207- file -- "$TARGET_DIR"/release/{ein,gix}
208- cp -- "$TARGET_DIR"/release/{ein,gix} "$staging/"
209- tar czf "$staging.tar.gz" "$staging"
210- echo "ASSET=$staging.tar.gz" >> "$GITHUB_ENV"
211- fi
210+ - name : Build archive (Unix)
211+ if : matrix.os != 'windows-latest'
212+ run : |
213+ file -- "$TARGET_DIR"/release/{ein,gix}
214+ cp -- "$TARGET_DIR"/release/{ein,gix} "$ARCHIVE/"
215+ tar czf "$ARCHIVE.tar.gz" "$ARCHIVE"
216+ shasum --algorithm=256 --binary "$ARCHIVE.tar.gz" > "$ARCHIVE.tar.gz.sha256"
217+ echo "ASSET=$ARCHIVE.tar.gz" >> "$GITHUB_ENV"
218+ echo "ASSET_SUM=$ARCHIVE.tar.gz.sha256" >> "$GITHUB_ENV"
212219
213220 - name : Upload release archive
214- uses : actions/upload-release-asset@v1.0.2
221+ run : gh release upload "$VERSION" "$ASSET" "$ASSET_SUM"
222+ env :
223+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
224+
225+ # Add a macOS universal binary archive for a feature using its built aarch64 and x86_64 assets.
226+ build-macos-universal2-release :
227+ runs-on : macos-latest
228+
229+ needs : [ create-release, build-release ]
230+
231+ strategy :
232+ matrix :
233+ # These features need to be exactly the same as the features in build-release.
234+ feature : [ small, lean, max, max-pure ]
235+
236+ env :
237+ BASH_ENV : ./helpers.sh
238+ REPOSITORY : ${{ github.repository }}
239+ FEATURE : ${{ matrix.feature }}
240+ VERSION : ${{ needs.create-release.outputs.version }}
241+
242+ steps :
243+ - name : Define helper function
244+ run : |
245+ name() { echo "gitoxide-$FEATURE-$VERSION-$1-apple-darwin"; }
246+ declare -f name >> "$BASH_ENV"
247+
248+ - name : Obtain single-architecture releases
249+ run : |
250+ gh release --repo="$REPOSITORY" download "$VERSION" \
251+ --pattern="$(name aarch64).tar.gz" --pattern="$(name aarch64).tar.gz.sha256" \
252+ --pattern="$(name x86_64).tar.gz" --pattern="$(name x86_64).tar.gz.sha256"
253+ env :
254+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
255+
256+ - name : Unpack single-architecture releases
257+ run : |
258+ shasum --check "$(name aarch64).tar.gz.sha256" "$(name x86_64).tar.gz.sha256"
259+ tar xf "$(name aarch64).tar.gz"
260+ tar xf "$(name x86_64).tar.gz"
261+
262+ - name : Determine archive basename
263+ run : echo "ARCHIVE=$(name universal)" >> "$GITHUB_ENV"
264+
265+ - name : Pre-populate directory for archive
266+ run : |
267+ cp -R -- "$(name aarch64)" "$ARCHIVE"
268+ rm -- "$ARCHIVE"/{ein,gix}
269+
270+ - name : Create Universal 2 binaries
271+ run : |
272+ for bin in ein gix; do
273+ lipo -create "$(name aarch64)/$bin" "$(name x86_64)/$bin" -output "$ARCHIVE/$bin"
274+ file -- "$ARCHIVE/$bin"
275+ done
276+
277+ - name : Build archive
278+ run : |
279+ tar czf "$ARCHIVE.tar.gz" "$ARCHIVE"
280+ shasum --algorithm=256 --binary "$ARCHIVE.tar.gz" > "$ARCHIVE.tar.gz.sha256"
281+ echo "ASSET=$ARCHIVE.tar.gz" >> "$GITHUB_ENV"
282+ echo "ASSET_SUM=$ARCHIVE.tar.gz.sha256" >> "$GITHUB_ENV"
283+
284+ - name : Upload release archive
285+ run : gh release --repo="$REPOSITORY" upload "$VERSION" "$ASSET" "$ASSET_SUM"
286+ env :
287+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
288+
289+ # Check for some problems, consolidate checksum files into one, and mark the release non-draft.
290+ publish-release :
291+ runs-on : ubuntu-latest
292+
293+ needs : [ create-release, build-release, build-macos-universal2-release ]
294+
295+ env :
296+ REPOSITORY : ${{ github.repository }}
297+ VERSION : ${{ needs.create-release.outputs.version }}
298+
299+ steps :
300+ - name : Discover assets
301+ run : |
302+ gh release --repo="$REPOSITORY" view "$VERSION" --json assets --jq '.assets.[].name' > assets.txt
303+ env :
304+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
305+
306+ - name : Show all individual asset names
307+ run : cat assets.txt
308+
309+ # The `features` array is repeated because GHA doen't support YAML anchors.
310+ # We will check that the macOS `universal` features match the others exactly.
311+ # In the future this and the next step may be removed, or expanded to do more validation.
312+ - name : Extract macOS asset names by architecture
313+ run : |
314+ for arch in aarch64 x86_64 universal; do
315+ grep -Fw "$arch-apple-darwin" assets.txt | sort | tee -- "$arch.txt"
316+ done
317+
318+ - name : Check macOS archive features
319+ run : |
320+ mask() { sed -r 's/\w+-apple-darwin/<arch>-apple-darwin/' -- "$1.txt"; }
321+ diff -- <(mask aarch64) <(mask universal)
322+ diff -- <(mask x86_64) <(mask universal)
323+
324+ - name : Clean up local temporary macOS asset list files
325+ run : rm {assets,aarch64,x86_64,universal}.txt
326+
327+ - name : Retrieve all individual checksums
328+ run : gh release --repo="$REPOSITORY" download "$VERSION" --pattern='gitoxide-*.sha256'
329+ env :
330+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
331+
332+ - name : Concatenate checksums into one file
333+ run : cat gitoxide-*.sha256 > hashes.sha256
334+
335+ - name : Upload the combined checksum file
336+ run : gh release --repo="$REPOSITORY" upload "$VERSION" hashes.sha256
337+ env :
338+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
339+
340+ # If any step of any job fails before this, the draft still has the individual checksum files.
341+ - name : Remove the individual checksum file assets
342+ run : |
343+ for sumfile in gitoxide-*.sha256; do
344+ gh release --repo="$REPOSITORY" delete-asset "$VERSION" "$sumfile" --yes
345+ done
346+ env :
347+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
348+
349+ - name : Publish the release
350+ run : gh release --repo="$REPOSITORY" edit "$VERSION" --draft=false
215351 env :
216352 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
217- with :
218- upload_url : ${{ env.UPLOAD_URL }}
219- asset_path : ${{ env.ASSET }}
220- asset_name : ${{ env.ASSET }}
221- asset_content_type : application/octet-stream
0 commit comments