Conversation
Adds .github/workflows/release.yml — a workflow_dispatch entry point that produces a real GitHub Release (not just a tag) with auto- generated notes. What the workflow does on Run: 1. Validates the input version is semver and the v<version> tag does not already exist. 2. Gates the release on yarn typecheck + yarn test passing. 3. Bumps `version` in the root and both workspace package.json files in lockstep (single-product monorepo). 4. Commits the bump as 'release: v<version>' and pushes to main. 5. Creates the immutable v<version> tag plus moves the major-version pointer (v1, v2, …) — the moving tag is what consumers pin via @v1. 6. Creates a GitHub Release via `gh release create --generate-notes`, marking it as pre-release if the version contains a hyphen suffix (e.g. 1.0.0-rc.1). README has a new "Releasing (maintainers)" section explaining the flow and the branch-protection gotcha (default GITHUB_TOKEN may need to be allow-listed in protection rules).
📝 WalkthroughWalkthroughAdds a manual GitHub Actions release workflow and README docs. The workflow validates a SemVer input, runs typecheck/tests, bumps package.json versions (root and workspaces), creates annotated + major pointer tags, pushes to main, and creates a GitHub Release (auto-notes, prerelease when hyphenated). ChangesRelease Workflow & Documentation
sequenceDiagram
autonumber
actor Maintainer
participant GitHub as "GitHub Actions"
participant Repo as "Repository (git)"
participant Node as "Node/Yarn"
participant GHCLI as "gh (GitHub CLI)"
Maintainer->>GitHub: Manually dispatch workflow (version)
GitHub->>Repo: Confirm ref is refs/heads/main
GitHub->>GitHub: Validate SemVer & tag absence
GitHub->>Node: Setup Node 22 + Yarn
Node->>Node: yarn install, typecheck, test
GitHub->>Repo: Update package.json versions, commit
GitHub->>Repo: Create annotated tag v$VERSION and update v<major>
GitHub->>Repo: Push commit and tags to main
GitHub->>GHCLI: gh release create v$VERSION --generate-notes [--prerelease?]
GHCLI->>GitHub: Create GitHub Release
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Review rate limit: 8/10 reviews remaining, refill in 11 minutes and 18 seconds. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/release.yml:
- Around line 28-33: The workflow allows workflow_dispatch from arbitrary
branches but later unconditionally pushes HEAD to main; update the push step
(the step that runs the git push/force push to main) to only run when the
dispatch came from the main branch by adding a conditional that checks
github.ref == 'refs/heads/main' (or equivalent: github.event_name ==
'workflow_dispatch' && github.ref == 'refs/heads/main') so non-main refs cannot
be pushed to main; also ensure the checkout uses fetch-depth: 0 remains but the
push step is gated so only refs matching main execute the push.
- Line 37: The SemVer regex in the if condition that tests "$VERSION" currently
disallows build metadata; update the pattern used in the if ! [[ "$VERSION" =~
... ]] check to accept an optional +build metadata segment by appending an
optional (\+[0-9A-Za-z.-]+)? group so valid versions like 1.2.3+build.7 pass
(keep the existing optional pre-release group -[0-9A-Za-z.-]+? intact and ensure
anchors ^...$ remain).
🪄 Autofix (Beta)
❌ Autofix failed (check again to retry)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 4428ab29-2abf-4219-bd7a-46131d5bfb9c
📒 Files selected for processing (2)
.github/workflows/release.ymlREADME.md
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. ⛔ CodeRabbit does not have permission to push changes to this repository. Please ensure CodeRabbit has Contents: Read and write permission. |
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. ⛔ CodeRabbit does not have permission to push changes to this repository. Please ensure CodeRabbit has Contents: Read and write permission. |
Two CodeRabbit findings on PR #9: 1. Critical: workflow_dispatch can launch from any branch, but the workflow pushes HEAD to main. That would silently release a non-main ref's code. Add an early step that hard-fails if github.ref != refs/heads/main. 2. Minor: SemVer 2.0.0 allows build metadata after a + (e.g. 1.2.3+build.7). The previous regex rejected those. Extend it to accept an optional +[0-9A-Za-z.-]+ suffix. Refs: - #9 (comment) - #9 (comment)
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/release.yml:
- Around line 105-109: The prerelease detection wrongly treats any '-' anywhere
in VERSION as prerelease (so versions like 1.2.3+build-7 are misclassified); fix
it by testing for a hyphen only in the part of VERSION before any build metadata
by first stripping anything after '+' (e.g., assign BASE from VERSION up to the
first '+' using shell parameter expansion) and then set
PRERELEASE_FLAG="--prerelease" only if that BASE contains a '-' ; update the
block that sets PRERELEASE_FLAG and reference the VERSION and PRERELEASE_FLAG
variables so the logic checks BASE (stripped of build metadata) for a prerelease
suffix.
- Around line 82-84: The git commit step can fail when there are no staged
changes; after the git add (package.json action/package.json site/package.json)
replace the unconditional git commit -m "release: v$VERSION" with a guard that
checks for staged changes (e.g., use git diff --cached --quiet || git commit -m
"release: v$VERSION" or if git diff --cached --quiet; then echo "no changes to
commit"; else git commit -m "release: v$VERSION"; fi) so the workflow continues
safely on reruns when npm pkg set produced no changes.
🪄 Autofix (Beta)
❌ Autofix failed (check again to retry)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 1f1d4a53-dc81-4761-8564-78f2c1d162a7
📒 Files selected for processing (1)
.github/workflows/release.yml
| git add package.json action/package.json site/package.json | ||
| git commit -m "release: v$VERSION" | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C2 'git add package\.json action/package\.json site/package\.json|git commit -m "release: v\$VERSION"' .github/workflows/release.ymlRepository: znat/gitpulse
Length of output: 374
🏁 Script executed:
cat -n .github/workflows/release.yml | head -100Repository: znat/gitpulse
Length of output: 4007
Guard git commit to support safe reruns.
The git commit at line 83 fails when there are no staged changes, which occurs during workflow reruns for the same version after a partial failure. When the workflow fails after the Push step but before completion (e.g., at GitHub Release), a rerun checks out code that already contains the version bump. The subsequent npm pkg set calls are idempotent and produce no changes, causing git commit to exit with code 1 and fail the step.
Wrap the commit in a conditional check:
Suggested patch
npm pkg set version="$VERSION" -w `@gitpulse/action`
npm pkg set version="$VERSION" -w `@gitpulse/site`
git add package.json action/package.json site/package.json
- git commit -m "release: v$VERSION"
+ if ! git diff --cached --quiet; then
+ git commit -m "release: v$VERSION"
+ else
+ echo "No version file changes detected; continuing without a new commit."
+ fi🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/release.yml around lines 82 - 84, The git commit step can
fail when there are no staged changes; after the git add (package.json
action/package.json site/package.json) replace the unconditional git commit -m
"release: v$VERSION" with a guard that checks for staged changes (e.g., use git
diff --cached --quiet || git commit -m "release: v$VERSION" or if git diff
--cached --quiet; then echo "no changes to commit"; else git commit -m "release:
v$VERSION"; fi) so the workflow continues safely on reruns when npm pkg set
produced no changes.
| # Pre-release detection: any version with a hyphen suffix is a pre-release. | ||
| PRERELEASE_FLAG="" | ||
| if [[ "$VERSION" == *-* ]]; then | ||
| PRERELEASE_FLAG="--prerelease" | ||
| fi |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
versions=("1.2.3" "1.2.3-rc.1" "1.2.3+build-7" "1.2.3-rc.1+build-7")
for v in "${versions[@]}"; do
old=""
[[ "$v" == *-* ]] && old="--prerelease"
core="${v%%+*}"
new=""
[[ "$core" == *-* ]] && new="--prerelease"
printf "%-20s old=%-13s new=%s\n" "$v" "${old:-<none>}" "${new:-<none>}"
doneRepository: znat/gitpulse
Length of output: 269
🏁 Script executed:
cat -n .github/workflows/release.yml | sed -n '100,115p'Repository: znat/gitpulse
Length of output: 685
🏁 Script executed:
cat -n .github/workflows/release.yml | sed -n '40,60p'Repository: znat/gitpulse
Length of output: 985
Fix prerelease detection to ignore build metadata.
The version validation at line 48 correctly allows SemVer build metadata (e.g., 1.2.3+build-7), but the prerelease detection at line 107 incorrectly flags any version containing - as a prerelease. This means 1.2.3+build-7 would be marked as prerelease even though it is not.
Suggested patch
VERSION="${{ inputs.version }}"
# Pre-release detection: any version with a hyphen suffix is a pre-release.
PRERELEASE_FLAG=""
- if [[ "$VERSION" == *-* ]]; then
+ CORE_VERSION="${VERSION%%+*}" # strip optional +buildmetadata
+ if [[ "$CORE_VERSION" == *-* ]]; then
PRERELEASE_FLAG="--prerelease"
fi🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/release.yml around lines 105 - 109, The prerelease
detection wrongly treats any '-' anywhere in VERSION as prerelease (so versions
like 1.2.3+build-7 are misclassified); fix it by testing for a hyphen only in
the part of VERSION before any build metadata by first stripping anything after
'+' (e.g., assign BASE from VERSION up to the first '+' using shell parameter
expansion) and then set PRERELEASE_FLAG="--prerelease" only if that BASE
contains a '-' ; update the block that sets PRERELEASE_FLAG and reference the
VERSION and PRERELEASE_FLAG variables so the logic checks BASE (stripped of
build metadata) for a prerelease suffix.
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. ⛔ CodeRabbit does not have permission to push changes to this repository. Please ensure CodeRabbit has Contents: Read and write permission. |
|
| Filename | Overview |
|---|---|
| .github/workflows/release.yml | New one-click release workflow; two issues: shell injection via direct template expression interpolation in run steps, and a partial-push failure scenario that makes the workflow un-retryable without manual intervention. |
| README.md | Adds a "Releasing (maintainers)" section documenting the workflow steps and the branch-protection gotcha; documentation looks accurate and complete. |
Sequence Diagram
sequenceDiagram
actor Maintainer
participant GHA as GitHub Actions
participant Repo as GitHub Repo (main)
participant GHR as GitHub Releases
Maintainer->>GHA: workflow_dispatch (version=1.0.0)
GHA->>GHA: Reject if not dispatched from main
GHA->>GHA: Validate semver + check tag doesn't exist
GHA->>GHA: yarn typecheck + yarn test (gate)
GHA->>GHA: npm pkg set version across workspaces
GHA->>Repo: git push HEAD:main (bump commit)
GHA->>Repo: git push v1.0.0 (immutable tag)
GHA->>Repo: git push v1 --force (major pointer)
GHA->>GHR: gh release create v1.0.0 --generate-notes
Reviews (1): Last reviewed commit: "fix(release): reject non-main dispatch +..." | Re-trigger Greptile
| - name: Validate version + ensure tag does not already exist | ||
| run: | | ||
| VERSION="${{ inputs.version }}" |
There was a problem hiding this comment.
Shell injection via
${{ inputs.version }} in run: steps
GitHub's template engine expands ${{ inputs.version }} directly into the shell script text before the shell processes it. A value like 1.0.0" && malicious_cmd; echo " would cause the assignment VERSION="1.0.0" && malicious_cmd; echo "", executing malicious_cmd before the regex check can block it. The fix is to use env: blocks so the value arrives as a shell variable, never as shell text.
Apply the same env: pattern to every subsequent step that sets VERSION="${{ inputs.version }}" (Bump, Tag, Push, Release steps).
| - name: Validate version + ensure tag does not already exist | |
| run: | | |
| VERSION="${{ inputs.version }}" | |
| - name: Validate version + ensure tag does not already exist | |
| env: | |
| INPUT_VERSION: ${{ inputs.version }} | |
| run: | | |
| VERSION="$INPUT_VERSION" |
| - name: Push commit + tags | ||
| run: | | ||
| VERSION="${{ inputs.version }}" | ||
| MAJOR="v${VERSION%%.*}" | ||
| git push origin HEAD:main | ||
| git push origin "v$VERSION" | ||
| git push origin "$MAJOR" --force |
There was a problem hiding this comment.
Partial push failure leaves workflow un-retryable
If git push origin HEAD:main succeeds (line 96) but the subsequent tag push on line 97 or 98 fails, the version-bump commit is already on main with no tags and no GitHub Release. A retry of the full workflow will then fail at the "Bump package.json" step because npm pkg set writes the same value, leaving nothing for git commit — error: nothing to commit. At that point the operator must manually push the two tags and create the release by hand. Consider consolidating the pushes into a single git push with --follow-tags, or adding explicit error handling / recovery instructions in the workflow.
Adds `.github/workflows/release.yml` — a one-click `workflow_dispatch` entry point that produces a real GitHub Release (not just a tag) with auto-generated notes.
How to release
What the workflow does
What this gives consumers
```yaml
stable, auto-upgrades on non-breaking releases (the actions/checkout@v4 pattern)
uses: znat/gitpulse/.github/workflows/publish.yaml@v1
locked to one exact release for full reproducibility
uses: znat/gitpulse/.github/workflows/publish.yaml@v1.0.0
```
README
New "Releasing (maintainers)" section walks through the flow and notes the branch-protection gotcha (default `GITHUB_TOKEN` may need to be allow-listed if `main` is protected).
Test plan
Summary by CodeRabbit