diff --git a/README.md b/README.md index 7d35f4c..6451f44 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ The lookup uses `cargo metadata --no-deps`, ignores non-workspace packages, and Contains release-plz post-processing commands: - `x52-bump-changelogs` checks out a release-plz pull request, adds the released versions to crate changelogs, updates README version links, and pushes a commit when anything changed. -- `x52-update-release-notes` copies the matching changelog sections into GitHub releases. +- `x52-update-release-notes` copies the matching changelog sections into GitHub releases. Use `--then-undraft` to publish each release after its notes update succeeds. - `x52-comment-release-pr` adds or updates a draft-release link comment on the merged release pull request. - `x52-comment-release-assets-uploaded` adds or updates a comment after the release assets are uploaded. - `x52-update-homebrew-tap` updates macOS checksums in `x52dev/homebrew-tap` and opens a formula pull request. @@ -115,6 +115,17 @@ For GitHub Actions, enter the development shell before invoking the release comm Pass release-plz output through `RELEASE_PLZ_PR_JSON` or `RELEASE_PLZ_RELEASES_JSON`, and provide `GH_TOKEN` for GitHub mutations. +`x52-update-release-notes` leaves the release's draft status unchanged by default. +To publish each release after its changelog notes are set, run: + +```sh +x52-update-release-notes --then-undraft +``` + +The command skips releases whose package has no `CHANGELOG.md`. A failed notes +update stops the command before it publishes that release. An empty changelog +section uses the existing fallback note and can still be published. + The commands use fixed `x52-` HTML markers. They make retries update the existing comment instead of creating another one: ```sh diff --git a/release-tools/test.bash b/release-tools/test.bash index da34ba6..fe4ccac 100644 --- a/release-tools/test.bash +++ b/release-tools/test.bash @@ -94,6 +94,11 @@ printf ' <%s>' "$@" >>"$COMMAND_LOG" printf '\n' >>"$COMMAND_LOG" case "$*" in + 'release edit demo-v1.1.0 --notes='*) + if [[ "${RELEASE_NOTES_EDIT_FAIL:-false}" == "true" ]]; then + exit 17 + fi + ;; *'/commits/'*'/pulls'*) printf '42\n' ;; @@ -202,10 +207,69 @@ grep -Fq 'gh <42>' "$command_log" grep -Fq 'git ' "$command_log" export RELEASE_PLZ_RELEASES_JSON='[{"package_name":"demo","version":"1.1.0","tag":"demo-v1.1.0"}]' -x52-update-release-notes +COMMAND_LOG="$test_root/release-notes-default.log" x52-update-release-notes + +cat >"$test_root/expected-release-notes-default.log" <<'EOF' +gh <--notes=- Added feature.> +EOF + +diff -u "$test_root/expected-release-notes-default.log" "$test_root/release-notes-default.log" + +COMMAND_LOG="$test_root/release-notes-undraft.log" x52-update-release-notes --then-undraft + +cat >"$test_root/expected-release-notes-undraft.log" <<'EOF' +gh <--notes=- Added feature.> +gh <--draft=false> +EOF + +diff -u "$test_root/expected-release-notes-undraft.log" "$test_root/release-notes-undraft.log" + +if COMMAND_LOG="$test_root/release-notes-failed.log" RELEASE_NOTES_EDIT_FAIL=true \ + x52-update-release-notes --then-undraft; then + echo "Expected a failed release notes update to fail" >&2 + exit 1 +else + [[ "$?" == 17 ]] +fi + +diff -u "$test_root/expected-release-notes-default.log" "$test_root/release-notes-failed.log" + +mv "$fixture_root/CHANGELOG.md" "$fixture_root/CHANGELOG.md.saved" +touch "$test_root/release-notes-missing.log" +COMMAND_LOG="$test_root/release-notes-missing.log" x52-update-release-notes --then-undraft +[[ ! -s "$test_root/release-notes-missing.log" ]] + +cat >"$fixture_root/CHANGELOG.md" <<'EOF' +# Changelog + +## 1.1.0 +EOF + +COMMAND_LOG="$test_root/release-notes-empty.log" x52-update-release-notes --then-undraft + +cat >"$test_root/expected-release-notes-empty.log" <<'EOF' +gh <--notes=- No significant changes since the previous release.> +gh <--draft=false> +EOF + +diff -u "$test_root/expected-release-notes-empty.log" "$test_root/release-notes-empty.log" +mv "$fixture_root/CHANGELOG.md.saved" "$fixture_root/CHANGELOG.md" + +touch "$test_root/release-notes-invalid-option.log" +if COMMAND_LOG="$test_root/release-notes-invalid-option.log" \ + x52-update-release-notes --unknown >"$test_root/release-notes-invalid-option-output.log" 2>&1; then + echo "Expected an unknown release notes option to fail" >&2 + exit 1 +else + [[ "$?" == 2 ]] +fi + +[[ ! -s "$test_root/release-notes-invalid-option.log" ]] +[[ "$(<"$test_root/release-notes-invalid-option-output.log")" == 'Unknown argument: --unknown' ]] -grep -Fq 'gh ' "$command_log" -grep -Fq '<--notes=- Added feature.>' "$command_log" +env -u RELEASE_PLZ_RELEASES_JSON X52_CARGO=/nonexistent \ + x52-update-release-notes --help >"$test_root/release-notes-help.log" +[[ "$(<"$test_root/release-notes-help.log")" == *'Usage: x52-update-release-notes [--then-undraft]'* ]] export GITHUB_REPOSITORY='example/demo' x52-comment-release-pr "$RELEASE_PLZ_RELEASES_JSON" deadbeef >"$comment_log" diff --git a/release-tools/update-release-notes.bash b/release-tools/update-release-notes.bash index 9b4975f..966381a 100644 --- a/release-tools/update-release-notes.bash +++ b/release-tools/update-release-notes.bash @@ -1,6 +1,28 @@ set -eEuo pipefail shopt -s inherit_errexit +undraft=false + +while (( $# > 0 )); do + case "$1" in + --then-undraft) + undraft=true + ;; + -h | --help) + echo "Usage: x52-update-release-notes [--then-undraft]" + echo "Copy changelog notes to GitHub releases." + echo "Use --then-undraft to publish each release after its notes update succeeds." + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + exit 2 + ;; + esac + + shift +done + release_plz_releases_json="${RELEASE_PLZ_RELEASES_JSON:?RELEASE_PLZ_RELEASES_JSON is required}" cargo_bin="${X52_CARGO:-cargo}" gh_bin="${X52_GH:-gh}" @@ -76,6 +98,11 @@ update_release_notes() { fi "$gh_bin" release edit "$tag" --notes="$notes" + + if [[ "$undraft" == "true" ]]; then + echo "Publishing ${tag}" + "$gh_bin" release edit "$tag" --draft=false + fi } while IFS=$'\t' read -r name version tag; do