#!/bin/sh # Release one workflow: bump its version, date its changelog, commit, tag, # package, then (after confirmation) push, publish the package on the tag # and redeploy the site. # # scripts/release major|minor|patch [--dry-run] # # --dry-run does everything up to the package, shows the release commit, then # undoes the commit and tag. The package stays in dist/. set -eu die() { echo "error: $*" >&2 exit 1 } usage="usage: scripts/release major|minor|patch [--dry-run]" [ $# -eq 2 ] || [ $# -eq 3 ] || die "$usage" name=$1 bump=$2 dry_run=false if [ $# -eq 3 ]; then [ "$3" = --dry-run ] || die "$usage" dry_run=true fi root=$(cd "$(dirname "$0")/.." && pwd) cd "$root" dir=workflows/$name [ -d "$dir" ] || die "no workflow at $dir" [ -z "$(jj diff --summary)" ] || die "the working copy has changes" [ "$(jj log --no-graph -r @- -T commit_id)" = "$(jj log --no-graph -r main -T commit_id)" ] || die "the working copy's parent isn't main" # The Unreleased section becomes the release notes. notes=$(awk '/^## Unreleased/ { f = 1; next } /^## / { f = 0 } f' "$dir/CHANGELOG.md" | sed -e '/./,$!d') [ -n "$notes" ] || die "nothing under ## Unreleased in $dir/CHANGELOG.md" current=$(sed -n 's/^version = "\(.*\)"$/\1/p' "$dir/Cargo.toml" | head -1) IFS=. read -r major minor patch </dev/null && die "tag $tag already exists" echo "Releasing $display $current -> $version" start=$(jj op log -n 1 --no-graph -T 'id.short()') sed -i '' "1,/^version = /s/^version = \".*\"$/version = \"$version\"/" "$dir/Cargo.toml" plutil -replace version -string "$version" "$dir/workflow/info.plist" cargo metadata --format-version 1 --offline >/dev/null # updates Cargo.lock changelog=$(awk -v heading="## $version - $(date +%Y-%m-%d)" \ '{ print } /^## Unreleased/ { print ""; print heading }' "$dir/CHANGELOG.md") printf '%s\n' "$changelog" >"$dir/CHANGELOG.md" # The site's data (and its download link) now sees the dated changelog. site/scripts/workflow-data >/dev/null jj --quiet commit -m "Release $display $version" jj --quiet sign -r @- # sign now, so pushing doesn't rewrite the tagged commit jj --quiet bookmark move main --to @- commit=$(jj log --no-graph -r main -T commit_id) # verbatim: the notes' "### Added" headings would otherwise be stripped as # comments. git tag -a --cleanup=verbatim "$tag" -m "$display $version" -m "$notes" "$commit" package=$(scripts/package "$name" "$tag") if $dry_run; then echo jj show --stat -r main echo git tag -n99 -l "$tag" git tag -d "$tag" >/dev/null jj --quiet op restore "$start" echo echo "Dry run: undid the release commit and tag. Package: $package" exit 0 fi echo echo "Tagged $tag and built $package." printf 'Push, publish the package and deploy the site? [y/N] ' read -r answer if [ "$answer" != y ]; then echo "Stopped before pushing. To undo: git tag -d $tag && jj op restore $start" exit 0 fi jj git push --bookmark main git push origin "refs/tags/$tag" scripts/publish-artifact "$tag" "$package" site/scripts/deploy