Refresh Cargo.lock for 0.9.0; auto-tag releases from Release branches
This commit is contained in:
parent
b8eedf2137
commit
40a6ed8993
2 changed files with 86 additions and 13 deletions
|
|
@ -7,7 +7,13 @@ name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [master]
|
# Pushing a branch whose name starts with Release cuts a release: the version
|
||||||
|
# comes from Cargo.toml and the release job creates the tag itself. Pushing a
|
||||||
|
# v* tag by hand still works and takes the same path. The lowercase pattern is
|
||||||
|
# there because branch names are case-sensitive and a silent no-op would be a
|
||||||
|
# miserable thing to debug, as is the fact that * does not match / in these
|
||||||
|
# filters - Release/0.9.1 needs the ** form to be seen at all.
|
||||||
|
branches: [master, 'Release*', 'Release/**', 'release*', 'release/**']
|
||||||
tags: ['v*']
|
tags: ['v*']
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [master]
|
branches: [master]
|
||||||
|
|
@ -50,6 +56,22 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Check the tag matches the workspace version
|
||||||
|
# Asset names come from [workspace.package] version, not from the tag, so
|
||||||
|
# tagging v0.9.0 against version 0.8.8 would publish a release called
|
||||||
|
# v0.9.0 full of 0.8.8 files. Fails in seconds, before anything is built.
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
run: |
|
||||||
|
version=$(sed -n '/^\[workspace\.package\]/,/^\[/{ s/^version[[:space:]]*=[[:space:]]*"\([^"]*\)".*/\1/p }' Cargo.toml)
|
||||||
|
tag="${GITHUB_REF#refs/tags/}"
|
||||||
|
if [ "v$version" != "$tag" ]; then
|
||||||
|
echo "ERROR: tag $tag does not match the workspace version $version." >&2
|
||||||
|
echo "Bump [workspace.package] version in Cargo.toml, refresh Cargo.lock," >&2
|
||||||
|
echo "commit, delete the tag and re-tag." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "OK: $tag matches the workspace version"
|
||||||
|
|
||||||
- name: Install build dependencies
|
- name: Install build dependencies
|
||||||
run: |
|
run: |
|
||||||
apt-get update -qq
|
apt-get update -qq
|
||||||
|
|
@ -242,13 +264,31 @@ jobs:
|
||||||
retention-days: 14
|
retention-days: 14
|
||||||
|
|
||||||
# -------------------------------------------------------------- release ----
|
# -------------------------------------------------------------- release ----
|
||||||
|
#
|
||||||
|
# Two ways in, one path out:
|
||||||
|
# push a Release* branch -> the tag is derived from the workspace version
|
||||||
|
# push a v* tag by hand -> that tag is used as-is
|
||||||
|
#
|
||||||
|
# Either way this runs only after linux and windows-cross are green, so a
|
||||||
|
# failing test cannot produce a release.
|
||||||
|
#
|
||||||
|
# The tag is created by the same API call that creates the release. Creating it
|
||||||
|
# in an earlier step would not work: a tag pushed with CI's own token does not
|
||||||
|
# re-trigger workflows, so a design that tagged first and waited for the tag
|
||||||
|
# event would stall with no release and no error.
|
||||||
release:
|
release:
|
||||||
needs: [linux, windows-cross]
|
needs: [linux, windows-cross]
|
||||||
if: startsWith(github.ref, 'refs/tags/v')
|
if: >-
|
||||||
|
startsWith(github.ref, 'refs/tags/v')
|
||||||
|
|| startsWith(github.ref, 'refs/heads/Release')
|
||||||
|
|| startsWith(github.ref, 'refs/heads/release')
|
||||||
runs-on: forgejo-runner
|
runs-on: forgejo-runner
|
||||||
container:
|
container:
|
||||||
image: catthehacker/ubuntu:act-24.04
|
image: catthehacker/ubuntu:act-24.04
|
||||||
steps:
|
steps:
|
||||||
|
# Only needed to read the workspace version on a Release* branch push.
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: artifacts
|
path: artifacts
|
||||||
|
|
@ -261,20 +301,47 @@ jobs:
|
||||||
RELEASE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
RELEASE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
api="${GITHUB_API_URL:-$GITHUB_SERVER_URL/api/v1}"
|
api="${GITHUB_API_URL:-$GITHUB_SERVER_URL/api/v1}"
|
||||||
tag="${GITHUB_REF#refs/tags/}"
|
|
||||||
auth="Authorization: token $RELEASE_TOKEN"
|
auth="Authorization: token $RELEASE_TOKEN"
|
||||||
|
repo="$GITHUB_REPOSITORY"
|
||||||
|
|
||||||
|
# One source of truth for the version: the same [workspace.package]
|
||||||
|
# field build-deb.sh reads and the artifact names already carry. The
|
||||||
|
# branch name only signals intent - nothing is parsed out of it.
|
||||||
|
case "$GITHUB_REF" in
|
||||||
|
refs/tags/*)
|
||||||
|
tag="${GITHUB_REF#refs/tags/}" ;;
|
||||||
|
*)
|
||||||
|
version=$(sed -n '/^\[workspace\.package\]/,/^\[/{ s/^version[[:space:]]*=[[:space:]]*"\([^"]*\)".*/\1/p }' Cargo.toml)
|
||||||
|
[ -n "$version" ] || { echo "could not read the version from Cargo.toml" >&2; exit 1; }
|
||||||
|
tag="v$version" ;;
|
||||||
|
esac
|
||||||
|
echo "release tag: $tag commit: $GITHUB_SHA"
|
||||||
|
|
||||||
|
# A published version is immutable. If the tag already exists at some
|
||||||
|
# other commit, stop rather than ship two different builds under one
|
||||||
|
# version - the usual cause is forgetting to bump Cargo.toml.
|
||||||
|
at=$(curl -sS -H "$auth" "$api/repos/$repo/tags/$tag" | jq -r '.commit.sha // empty')
|
||||||
|
if [ -n "$at" ] && [ "$at" != "$GITHUB_SHA" ]; then
|
||||||
|
echo "ERROR: tag $tag already exists at $at, not $GITHUB_SHA." >&2
|
||||||
|
echo "Bump [workspace.package] version in Cargo.toml, refresh Cargo.lock" >&2
|
||||||
|
echo "with 'cargo update -w', commit and push again." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
mkdir -p dist
|
mkdir -p dist
|
||||||
find artifacts -type f -exec mv -t dist -- {} +
|
find artifacts -type f -exec mv -t dist -- {} +
|
||||||
ls -l dist/
|
ls -l dist/
|
||||||
|
|
||||||
# Reuse the release when it already exists, so re-running a tag build
|
# Creating a release whose tag_name does not exist yet makes Forgejo
|
||||||
# replaces assets instead of failing.
|
# create the tag at target_commitish, so this one call both tags and
|
||||||
id=$(curl -sS -H "$auth" "$api/repos/$GITHUB_REPOSITORY/releases/tags/$tag" | jq -r '.id // empty')
|
# publishes. Reuse an existing release so a re-run replaces assets
|
||||||
|
# instead of failing.
|
||||||
|
id=$(curl -sS -H "$auth" "$api/repos/$repo/releases/tags/$tag" | jq -r '.id // empty')
|
||||||
if [ -z "$id" ]; then
|
if [ -z "$id" ]; then
|
||||||
id=$(curl -fsS -X POST "$api/repos/$GITHUB_REPOSITORY/releases" \
|
id=$(curl -fsS -X POST "$api/repos/$repo/releases" \
|
||||||
-H "$auth" -H 'Content-Type: application/json' \
|
-H "$auth" -H 'Content-Type: application/json' \
|
||||||
-d "$(jq -n --arg t "$tag" '{tag_name: $t, name: $t, draft: false, prerelease: false}')" \
|
-d "$(jq -n --arg t "$tag" --arg c "$GITHUB_SHA" \
|
||||||
|
'{tag_name: $t, target_commitish: $c, name: $t, draft: false, prerelease: false}')" \
|
||||||
| jq -r '.id // empty')
|
| jq -r '.id // empty')
|
||||||
fi
|
fi
|
||||||
[ -n "$id" ] || { echo "could not create or find a release for $tag" >&2; exit 1; }
|
[ -n "$id" ] || { echo "could not create or find a release for $tag" >&2; exit 1; }
|
||||||
|
|
@ -283,11 +350,11 @@ jobs:
|
||||||
name=$(basename "$f")
|
name=$(basename "$f")
|
||||||
echo "uploading $name"
|
echo "uploading $name"
|
||||||
# Replace an asset of the same name left by an earlier run.
|
# Replace an asset of the same name left by an earlier run.
|
||||||
old=$(curl -sS -H "$auth" "$api/repos/$GITHUB_REPOSITORY/releases/$id/assets" \
|
old=$(curl -sS -H "$auth" "$api/repos/$repo/releases/$id/assets" \
|
||||||
| jq -r --arg n "$name" '.[] | select(.name == $n) | .id')
|
| jq -r --arg n "$name" '.[] | select(.name == $n) | .id')
|
||||||
[ -z "$old" ] || curl -fsS -X DELETE -H "$auth" \
|
[ -z "$old" ] || curl -fsS -X DELETE -H "$auth" \
|
||||||
"$api/repos/$GITHUB_REPOSITORY/releases/$id/assets/$old"
|
"$api/repos/$repo/releases/$id/assets/$old"
|
||||||
curl -fsS -X POST "$api/repos/$GITHUB_REPOSITORY/releases/$id/assets?name=$name" \
|
curl -fsS -X POST "$api/repos/$repo/releases/$id/assets?name=$name" \
|
||||||
-H "$auth" -F "attachment=@$f" -o /dev/null
|
-H "$auth" -F "attachment=@$f" -o /dev/null
|
||||||
done
|
done
|
||||||
echo "published $tag"
|
echo "published $tag"
|
||||||
|
|
|
||||||
10
README.md
10
README.md
|
|
@ -387,8 +387,14 @@ pagination: the table is virtualized, so a single scroll list capped at
|
||||||
- `QSB_SNIPPET_PERF=1 cargo test --release -p quicksearch-core --test
|
- `QSB_SNIPPET_PERF=1 cargo test --release -p quicksearch-core --test
|
||||||
snippet_perf -- --nocapture`: snippet pipeline benchmark.
|
snippet_perf -- --nocapture`: snippet pipeline benchmark.
|
||||||
- `.forgejo/workflows/ci.yml`: builds both platforms on every push to `master`
|
- `.forgejo/workflows/ci.yml`: builds both platforms on every push to `master`
|
||||||
and every pull request, and attaches the `.deb`, a Linux tarball and a
|
and every pull request. To cut a release, bump `[workspace.package] version`
|
||||||
Windows zip to a release on a `v*` tag. The Linux job runs in an Ubuntu
|
in `Cargo.toml`, run `cargo update -w` so the lockfile agrees (CI builds with
|
||||||
|
`--locked`), and push the commit on a branch named `Release...`. Once both
|
||||||
|
build jobs are green, CI tags that commit `v<version>` and publishes a release
|
||||||
|
with the `.deb`, a Linux tarball and a Windows zip attached; pushing a `v*`
|
||||||
|
tag by hand does the same thing. The version is never taken from the branch
|
||||||
|
name, and a tag that already exists at a different commit aborts the release
|
||||||
|
rather than shipping two builds under one version. The Linux job runs in an Ubuntu
|
||||||
22.04 container on purpose — `packaging/build-deb.sh` reads the package's
|
22.04 container on purpose — `packaging/build-deb.sh` reads the package's
|
||||||
`libc6` floor from the binary it just built, so the builder's glibc becomes
|
`libc6` floor from the binary it just built, so the builder's glibc becomes
|
||||||
the package's minimum, and 22.04 pins it at 2.35. The Windows job
|
the package's minimum, and 22.04 pins it at 2.35. The Windows job
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue