Add make tag target for GitHub release - #334
Conversation
Tags the current build.gradle version and creates a GitHub release with the matching CHANGELOG section as notes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| if git rev-parse "$VERSION" >/dev/null 2>&1; then | ||
| echo "Tag $VERSION already exists" >&2 | ||
| exit 1 |
There was a problem hiding this comment.
git rev-parse may match non-tag refs
git rev-parse "$VERSION" succeeds for any ref with that name — branches, remotes, etc. — not just tags. If a branch 1.0.1 exists (unlikely but possible), the script exits with "tag already exists" when no tag has been created. Scoping the lookup to refs/tags/ avoids the ambiguity.
| if git rev-parse "$VERSION" >/dev/null 2>&1; then | |
| echo "Tag $VERSION already exists" >&2 | |
| exit 1 | |
| if git rev-parse "refs/tags/$VERSION" >/dev/null 2>&1; then | |
| echo "Tag $VERSION already exists" >&2 | |
| exit 1 | |
| fi |
| NOTES="$(awk -v v="$VERSION" ' | ||
| $0 ~ "^## \\[" v "\\]" { found=1; next } | ||
| found && /^## \[/ { exit } | ||
| found { print } | ||
| ' CHANGELOG.md)" |
There was a problem hiding this comment.
Dots in version string are unescaped in awk regex
v is interpolated directly into an awk ERE, where . matches any character. 1.0.1 would also match 1X0Y1. While version numbers of that form are contrived, escaping the dots makes the match strict and avoids false positives if version components ever vary.
| NOTES="$(awk -v v="$VERSION" ' | |
| $0 ~ "^## \\[" v "\\]" { found=1; next } | |
| found && /^## \[/ { exit } | |
| found { print } | |
| ' CHANGELOG.md)" | |
| $0 ~ "^## \\[" gensub(/\./, "\\\\.", "g", v) "\\]" { found=1; next } |
Alternatively, switch to a fixed-string index() comparison for the header detection.
| git tag -a "$VERSION" -m "Release $VERSION" | ||
| git push origin "$VERSION" | ||
|
|
||
| gh release create "$VERSION" --title "Version $VERSION" --notes "$NOTES" |
There was a problem hiding this comment.
No rollback if
gh release create fails after tag is pushed
The script pushes the tag on line 31, then calls gh release create on line 33. If the release creation fails (network error, release already exists, missing gh auth, etc.), the tag is already live on the remote but no GitHub release exists. Re-running the script will immediately fail at the "tag already exists" guard, leaving the repo in a half-released state.
Consider either checking for an existing GitHub release before tagging (gh release view "$VERSION"), or deleting the remote tag on failure:
git tag -a "$VERSION" -m "Release $VERSION"
git push origin "$VERSION"
if ! gh release create "$VERSION" --title "Version $VERSION" --notes "$NOTES"; then
echo "Release creation failed; removing remote tag $VERSION" >&2
git push origin --delete "$VERSION"
git tag -d "$VERSION"
exit 1
fi| if [[ -z "${NOTES// }" ]]; then | ||
| echo "No CHANGELOG section found for [$VERSION]" >&2 | ||
| exit 1 |
There was a problem hiding this comment.
Whitespace trimming misses tabs and newlines
${NOTES// } removes only ASCII space characters. If the CHANGELOG section between two headers contains only blank lines (i.e. NOTES is composed entirely of newline characters), the guard [[ -z "${NOTES// }" ]] evaluates to false and the script proceeds with effectively empty release notes. Use tr -d '[:space:]' to catch all whitespace.
| if [[ -z "${NOTES// }" ]]; then | |
| echo "No CHANGELOG section found for [$VERSION]" >&2 | |
| exit 1 | |
| if [[ -z "$(echo "$NOTES" | tr -d '[:space:]')" ]]; then |
🦙 MegaLinter status: ✅ SUCCESS
See detailed report in MegaLinter reports |
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Scope existence check to refs/tags/ to avoid matching branches - Escape dots in version for awk regex - Use tr -d '[:space:]' to catch tabs/newlines in notes guard - Roll back tag if gh release create fails Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same class of issue as the awk fix; address while reviewing PR #334. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Summary
wf/tag-release.shthat reads the currentversionfrombuild.gradle, extracts the matching## [x.y.z]section fromCHANGELOG.md, creates an annotated git tag, pushes it, and runsgh release createwith those notes.make tag.Complements
make release(publishes to the Nextflow Plugin Registry) by handling the separate GitHub-release step.Test plan
make tagafter merge to cut the 1.0.1 GitHub release🤖 Generated with Claude Code
Greptile Summary
This PR adds
wf/tag-release.sh(wired asmake tag) which reads the version frombuild.gradle, extracts the matchingCHANGELOG.mdsection, creates an annotated git tag, pushes it, and callsgh release create.git push origin "$VERSION"runs beforegh release create. If the GitHub release step fails (auth error, release already exists, network timeout), the tag is already live on the remote but no release is attached. The "tag already exists" guard then prevents any re-run, leaving the repo in a half-released state without rollback.Confidence Score: 3/5
Needs the partial-failure rollback fixed before running in production; the remaining issues are minor.
One P1 (tag pushed without rollback on release-creation failure) plus three P2s (ref scoping, awk dot escaping, whitespace check) pulls the score below the P1 ceiling of 4.
wf/tag-release.sh — specifically lines 30-33 around tag push / release create ordering
Important Files Changed
tagto .PHONY and wires it towf/tag-release.sh; straightforward and correct.Sequence Diagram
sequenceDiagram participant Dev as Developer participant Script as tag-release.sh participant FS as Filesystem participant Git as Git (local+remote) participant GH as GitHub Releases Dev->>Script: make tag Script->>FS: grep version from build.gradle FS-->>Script: VERSION Script->>Git: git rev-parse refs/tags/VERSION Git-->>Script: not found → proceed Script->>FS: awk extract CHANGELOG section FS-->>Script: NOTES Script->>Git: git tag -a VERSION Script->>Git: git push origin VERSION Git-->>Script: tag pushed ✓ Script->>GH: gh release create VERSION --notes NOTES GH-->>Script: release created ✓ (or ✗ → tag stranded) Script->>Dev: echo "Tagged and released VERSION"Reviews (1): Last reviewed commit: "Make release depend on tag" | Re-trigger Greptile