Skip to content

Commit 35774af

Browse files
committed
chore: replace cargo-dist with cross + gh CLI release workflow
- Delete dist-workspace.toml (cargo-dist config) - Rename [profile.dist] → [profile.release] in Cargo.toml (same LTO/strip settings) - Replace 299-line cargo-dist-generated release.yml with clean 109-line custom workflow: - Triggers on v*.*.* tags - Validates tag matches Cargo.toml version - Builds 6 targets via cross (aarch64/x86_64 macOS, Linux gnu/musl, Windows MSVC) - Creates draft GitHub release via gh release create --generate-notes - Uploads .tar.gz/.zip + SHA256 checksums via gh release upload Matches SOTA pattern used by ripgrep, fd, bat, eza — no external release orchestration.
1 parent c4377d1 commit 35774af

File tree

3 files changed

+83
-295
lines changed

3 files changed

+83
-295
lines changed

.github/workflows/release.yml

Lines changed: 82 additions & 271 deletions
Original file line numberDiff line numberDiff line change
@@ -1,298 +1,109 @@
1-
# This file was autogenerated by dist: https://axodotdev.github.io/cargo-dist
2-
#
3-
# Copyright 2022-2024, axodotdev
4-
# SPDX-License-Identifier: MIT or Apache-2.0
5-
#
6-
# CI that:
7-
#
8-
# * checks for a Git Tag that looks like a release
9-
# * builds artifacts with dist (archives, installers, hashes)
10-
# * uploads those artifacts to temporary workflow zip
11-
# * on success, uploads the artifacts to a GitHub Release
12-
#
13-
# Note that the GitHub Release will be created with a generated
14-
# title/body based on your changelogs.
15-
161
name: Release
17-
permissions:
18-
"contents": "write"
192

20-
# This task will run whenever you push a git tag that looks like a version
21-
# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc.
22-
# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where
23-
# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION
24-
# must be a Cargo-style SemVer Version (must have at least major.minor.patch).
25-
#
26-
# If PACKAGE_NAME is specified, then the announcement will be for that
27-
# package (erroring out if it doesn't have the given version or isn't dist-able).
28-
#
29-
# If PACKAGE_NAME isn't specified, then the announcement will be for all
30-
# (dist-able) packages in the workspace with that version (this mode is
31-
# intended for workspaces with only one dist-able package, or with all dist-able
32-
# packages versioned/released in lockstep).
33-
#
34-
# If you push multiple tags at once, separate instances of this workflow will
35-
# spin up, creating an independent announcement for each one. However, GitHub
36-
# will hard limit this to 3 tags per commit, as it will assume more tags is a
37-
# mistake.
38-
#
39-
# If there's a prerelease-style suffix to the version, then the release(s)
40-
# will be marked as a prerelease.
413
on:
424
push:
435
tags:
44-
- '**[0-9]+.[0-9]+.[0-9]+*'
6+
- 'v[0-9]+.[0-9]+.[0-9]+*'
7+
8+
permissions:
9+
contents: write
4510

4611
jobs:
47-
# Run 'dist plan' (or host) to determine what tasks we need to do
48-
plan:
49-
runs-on: "ubuntu-22.04"
50-
outputs:
51-
val: ${{ steps.plan.outputs.manifest }}
52-
tag: ${{ github.ref_name }}
53-
tag-flag: ${{ format('--tag={0}', github.ref_name) }}
54-
publishing: 'true'
55-
env:
56-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
12+
create-release:
13+
name: Create release
14+
runs-on: ubuntu-latest
5715
steps:
58-
- uses: actions/checkout@v6
59-
with:
60-
persist-credentials: true
61-
submodules: recursive
62-
- name: Verify tag is on main branch
16+
- uses: actions/checkout@v4
17+
- name: Verify tag matches Cargo.toml version
6318
run: |
64-
git fetch origin main --depth=50
65-
if ! git merge-base --is-ancestor "${{ github.sha }}" origin/main; then
66-
echo "::error::Release tags must be pushed from the main branch. Aborting."
19+
TAG="${GITHUB_REF_NAME#v}"
20+
CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
21+
if [ "$TAG" != "$CARGO_VERSION" ]; then
22+
echo "::error::Tag $GITHUB_REF_NAME does not match Cargo.toml version $CARGO_VERSION"
6723
exit 1
6824
fi
69-
- name: Install dist
70-
# we specify bash to get pipefail; it guards against the `curl` command
71-
# failing. otherwise `sh` won't catch that `curl` returned non-0
72-
shell: bash
73-
run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.31.0/cargo-dist-installer.sh | sh"
74-
- name: Cache dist
75-
uses: actions/upload-artifact@v6
76-
with:
77-
name: cargo-dist-cache
78-
path: ~/.cargo/bin/dist
79-
- id: plan
25+
- name: Create draft release
26+
env:
27+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8028
run: |
81-
dist host --steps=create --tag=${{ github.ref_name }} --output-format=json > plan-dist-manifest.json
82-
echo "dist ran successfully"
83-
cat plan-dist-manifest.json
84-
echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT"
85-
- name: "Upload dist-manifest.json"
86-
uses: actions/upload-artifact@v6
87-
with:
88-
name: artifacts-plan-dist-manifest
89-
path: plan-dist-manifest.json
29+
gh release create "$GITHUB_REF_NAME" \
30+
--draft \
31+
--title "$GITHUB_REF_NAME" \
32+
--generate-notes
9033
91-
# Build and packages all the platform-specific things
92-
build-local-artifacts:
93-
name: build-local-artifacts (${{ join(matrix.targets, ', ') }})
94-
# Let the initial task tell us to not run (currently very blunt)
95-
needs:
96-
- plan
97-
if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') }}
34+
build-release:
35+
name: Build (${{ matrix.target }})
36+
needs: create-release
37+
runs-on: ${{ matrix.os }}
9838
strategy:
9939
fail-fast: false
100-
# Target platforms/runners are computed by dist in create-release.
101-
# Each member of the matrix has the following arguments:
102-
#
103-
# - runner: the github runner
104-
# - dist-args: cli flags to pass to dist
105-
# - install-dist: expression to run to install dist on the runner
106-
#
107-
# Typically there will be:
108-
# - 1 "global" task that builds universal installers
109-
# - N "local" tasks that build each platform's binaries and platform-specific installers
110-
matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }}
111-
runs-on: ${{ matrix.runner }}
112-
container: ${{ matrix.container && matrix.container.image || null }}
113-
env:
114-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
115-
BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json
40+
matrix:
41+
include:
42+
- target: aarch64-apple-darwin
43+
os: macos-latest
44+
- target: x86_64-apple-darwin
45+
os: macos-13
46+
- target: aarch64-unknown-linux-gnu
47+
os: ubuntu-latest
48+
use_cross: true
49+
- target: x86_64-unknown-linux-gnu
50+
os: ubuntu-latest
51+
- target: x86_64-unknown-linux-musl
52+
os: ubuntu-latest
53+
use_cross: true
54+
- target: x86_64-pc-windows-msvc
55+
os: windows-latest
11656
steps:
117-
- name: enable windows longpaths
118-
run: |
119-
git config --global core.longpaths true
120-
- uses: actions/checkout@v6
121-
with:
122-
persist-credentials: false
123-
submodules: recursive
124-
- name: Install Rust non-interactively if not already installed
125-
if: ${{ matrix.container }}
126-
run: |
127-
if ! command -v cargo > /dev/null 2>&1; then
128-
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
129-
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
130-
fi
131-
- name: Install dist
132-
run: ${{ matrix.install_dist.run }}
133-
# Get the dist-manifest
134-
- name: Fetch local artifacts
135-
uses: actions/download-artifact@v7
136-
with:
137-
pattern: artifacts-*
138-
path: target/distrib/
139-
merge-multiple: true
140-
- name: Install dependencies
141-
run: |
142-
${{ matrix.packages_install }}
143-
- name: Build artifacts
144-
run: |
145-
# Actually do builds and make zips and whatnot
146-
dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json
147-
echo "dist ran successfully"
148-
- id: cargo-dist
149-
name: Post-build
150-
# We force bash here just because github makes it really hard to get values up
151-
# to "real" actions without writing to env-vars, and writing to env-vars has
152-
# inconsistent syntax between shell and powershell.
153-
shell: bash
154-
run: |
155-
# Parse out what we just built and upload it to scratch storage
156-
echo "paths<<EOF" >> "$GITHUB_OUTPUT"
157-
dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT"
158-
echo "EOF" >> "$GITHUB_OUTPUT"
57+
- uses: actions/checkout@v4
15958

160-
cp dist-manifest.json "$BUILD_MANIFEST_NAME"
161-
- name: "Upload artifacts"
162-
uses: actions/upload-artifact@v6
163-
with:
164-
name: artifacts-build-local-${{ join(matrix.targets, '_') }}
165-
path: |
166-
${{ steps.cargo-dist.outputs.paths }}
167-
${{ env.BUILD_MANIFEST_NAME }}
59+
- name: Install Rust toolchain
60+
run: rustup target add ${{ matrix.target }}
16861

169-
# Build and package all the platform-agnostic(ish) things
170-
build-global-artifacts:
171-
needs:
172-
- plan
173-
- build-local-artifacts
174-
runs-on: "ubuntu-22.04"
175-
env:
176-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
177-
BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json
178-
steps:
179-
- uses: actions/checkout@v6
180-
with:
181-
persist-credentials: false
182-
submodules: recursive
183-
- name: Install cached dist
184-
uses: actions/download-artifact@v7
62+
- name: Install cross
63+
if: matrix.use_cross
64+
uses: taiki-e/install-action@v2
18565
with:
186-
name: cargo-dist-cache
187-
path: ~/.cargo/bin/
188-
- run: chmod +x ~/.cargo/bin/dist
189-
# Get all the local artifacts for the global tasks to use (for e.g. checksums)
190-
- name: Fetch local artifacts
191-
uses: actions/download-artifact@v7
192-
with:
193-
pattern: artifacts-*
194-
path: target/distrib/
195-
merge-multiple: true
196-
- id: cargo-dist
66+
tool: cross
67+
68+
- name: Build
19769
shell: bash
19870
run: |
199-
dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json
200-
echo "dist ran successfully"
201-
202-
# Parse out what we just built and upload it to scratch storage
203-
echo "paths<<EOF" >> "$GITHUB_OUTPUT"
204-
jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT"
205-
echo "EOF" >> "$GITHUB_OUTPUT"
71+
if [ "${{ matrix.use_cross }}" = "true" ]; then
72+
cross build --release --target ${{ matrix.target }}
73+
else
74+
cargo build --release --target ${{ matrix.target }}
75+
fi
20676
207-
cp dist-manifest.json "$BUILD_MANIFEST_NAME"
208-
- name: "Upload artifacts"
209-
uses: actions/upload-artifact@v6
210-
with:
211-
name: artifacts-build-global
212-
path: |
213-
${{ steps.cargo-dist.outputs.paths }}
214-
${{ env.BUILD_MANIFEST_NAME }}
215-
# Determines if we should publish/announce
216-
host:
217-
needs:
218-
- plan
219-
- build-local-artifacts
220-
- build-global-artifacts
221-
# Only run if we're "publishing", and only if plan, local and global didn't fail (skipped is fine)
222-
if: ${{ always() && needs.plan.result == 'success' && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }}
223-
env:
224-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
225-
runs-on: "ubuntu-22.04"
226-
outputs:
227-
val: ${{ steps.host.outputs.manifest }}
228-
steps:
229-
- uses: actions/checkout@v6
230-
with:
231-
persist-credentials: false
232-
submodules: recursive
233-
- name: Install cached dist
234-
uses: actions/download-artifact@v7
235-
with:
236-
name: cargo-dist-cache
237-
path: ~/.cargo/bin/
238-
- run: chmod +x ~/.cargo/bin/dist
239-
# Fetch artifacts from scratch-storage
240-
- name: Fetch artifacts
241-
uses: actions/download-artifact@v7
242-
with:
243-
pattern: artifacts-*
244-
path: target/distrib/
245-
merge-multiple: true
246-
- id: host
77+
- name: Package and checksum
78+
id: package
24779
shell: bash
24880
run: |
249-
dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json
250-
echo "artifacts uploaded and released successfully"
251-
cat dist-manifest.json
252-
echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT"
253-
- name: "Upload dist-manifest.json"
254-
uses: actions/upload-artifact@v6
255-
with:
256-
# Overwrite the previous copy
257-
name: artifacts-dist-manifest
258-
path: dist-manifest.json
259-
# Create a GitHub Release while uploading all files to it
260-
- name: "Download GitHub Artifacts"
261-
uses: actions/download-artifact@v7
262-
with:
263-
pattern: artifacts-*
264-
path: artifacts
265-
merge-multiple: true
266-
- name: Cleanup
267-
run: |
268-
# Remove the granular manifests
269-
rm -f artifacts/*-dist-manifest.json
270-
- name: Create GitHub Release
271-
env:
272-
PRERELEASE_FLAG: "${{ fromJson(steps.host.outputs.manifest).announcement_is_prerelease && '--prerelease' || '' }}"
273-
ANNOUNCEMENT_TITLE: "${{ fromJson(steps.host.outputs.manifest).announcement_title }}"
274-
ANNOUNCEMENT_BODY: "${{ fromJson(steps.host.outputs.manifest).announcement_github_body }}"
275-
RELEASE_COMMIT: "${{ github.sha }}"
276-
run: |
277-
# Write and read notes from a file to avoid quoting breaking things
278-
echo "$ANNOUNCEMENT_BODY" > $RUNNER_TEMP/notes.txt
81+
BIN="serpapi"
82+
TARGET="${{ matrix.target }}"
83+
VERSION="${GITHUB_REF_NAME#v}"
84+
PKG="${BIN}-${VERSION}-${TARGET}"
85+
86+
mkdir "$PKG"
87+
cp README.md LICENSE "$PKG/"
27988
280-
gh release create "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file "$RUNNER_TEMP/notes.txt" artifacts/*
89+
if [[ "$TARGET" == *"windows"* ]]; then
90+
cp "target/${TARGET}/release/${BIN}.exe" "$PKG/"
91+
7z a "${PKG}.zip" "$PKG"
92+
ARCHIVE="${PKG}.zip"
93+
else
94+
cp "target/${TARGET}/release/${BIN}" "$PKG/"
95+
tar czf "${PKG}.tar.gz" "$PKG"
96+
ARCHIVE="${PKG}.tar.gz"
97+
fi
28198
99+
sha256sum "$ARCHIVE" > "${ARCHIVE}.sha256"
100+
echo "archive=$ARCHIVE" >> "$GITHUB_OUTPUT"
101+
echo "sha256=${ARCHIVE}.sha256" >> "$GITHUB_OUTPUT"
282102
283-
announce:
284-
needs:
285-
- plan
286-
- host
287-
# use "always() && ..." to allow us to wait for all publish jobs while
288-
# still allowing individual publish jobs to skip themselves (for prereleases).
289-
# "host" however must run to completion, no skipping allowed!
290-
if: ${{ always() && needs.host.result == 'success' }}
291-
runs-on: "ubuntu-22.04"
292-
env:
293-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
294-
steps:
295-
- uses: actions/checkout@v6
296-
with:
297-
persist-credentials: false
298-
submodules: recursive
103+
- name: Upload to release
104+
env:
105+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
106+
run: |
107+
gh release upload "$GITHUB_REF_NAME" \
108+
"${{ steps.package.outputs.archive }}" \
109+
"${{ steps.package.outputs.sha256 }}"

Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,7 @@ targets = []
5252
assert_cmd = "2"
5353
predicates = "3"
5454

55-
# The profile that 'dist' will build with
56-
[profile.dist]
57-
inherits = "release"
55+
[profile.release]
5856
lto = true
5957
codegen-units = 1
6058
strip = "symbols"

0 commit comments

Comments
 (0)