Skip to content

Commit c1a33d5

Browse files
echobtcursoragent
andauthored
fix(release): tag on version-bump PR merge, no direct main push (#15)
* fix(release): tag on version-bump PR merge, no direct main push Co-authored-by: Mathis <echobt@users.noreply.github.com> * fix(release): keep version-bump green when tag jobs skip Co-authored-by: Mathis <echobt@users.noreply.github.com> * fix(release): document PR-based version bump in bump script Co-authored-by: Mathis <echobt@users.noreply.github.com> * fix(release): repair invalid YAML in version-bump workflow Co-authored-by: Mathis <echobt@users.noreply.github.com> * fix(release): avoid actions injection in version-bump Pass untrusted commit text via git log instead of interpolating github.event.head_commit.message into the run script (CodeQL cache poisoning). Keep tagging ruleset-safe (tags only, no push to main). Co-authored-by: Mathis <echobt@users.noreply.github.com> * docs: note R2 publish after tagged release Co-authored-by: Mathis <echobt@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Mathis <echobt@users.noreply.github.com>
1 parent c4af43c commit c1a33d5

7 files changed

Lines changed: 176 additions & 55 deletions

File tree

.github/workflows/version-bump.yml

Lines changed: 158 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,208 @@
11
name: Version Bump
22

3-
# Patch-bump and tag on every merge to main. workflow_dispatch keeps
4-
# explicit patch/minor/major control. Skip commits that are already bumps
5-
# so the bot cannot loop.
3+
# Version bumps land on main through normal PRs (protected branch / ruleset safe).
4+
# After a version-bump PR merges, this workflow tags v{VERSION_CLI}, which triggers
5+
# release.yml (GitHub Release + automatic R2 publish). workflow_dispatch can open a
6+
# bump PR or tag the current VERSION_CLI. This workflow never pushes commits to main.
67
on:
78
push:
89
branches: [main]
10+
paths:
11+
- VERSION_CLI
12+
- src/cortex-cli/VERSION
913
workflow_dispatch:
1014
inputs:
11-
bump_type:
12-
description: "Version bump type"
15+
action:
16+
description: "Action to perform"
1317
required: true
1418
type: choice
19+
options:
20+
- tag-current-version
21+
- open-bump-pr
22+
bump_type:
23+
description: "Bump type (only used with open-bump-pr)"
24+
required: false
25+
type: choice
1526
options:
1627
- patch
1728
- minor
1829
- major
19-
create_release:
20-
description: "Create release after bump"
21-
required: false
22-
type: boolean
23-
default: true
30+
default: patch
2431

2532
permissions:
2633
contents: write
34+
pull-requests: write
2735

2836
jobs:
29-
bump-version:
30-
name: Bump Version
37+
# Always-green job so skipped tag/PR jobs do not fail the workflow.
38+
gate:
39+
name: Workflow started
40+
runs-on: ubuntu-latest
41+
steps:
42+
- name: Note
43+
env:
44+
EVENT_NAME: ${{ github.event_name }}
45+
GIT_REF: ${{ github.ref }}
46+
run: |
47+
echo "event=${EVENT_NAME}"
48+
echo "ref=${GIT_REF}"
49+
echo "Tagging runs only for 'chore: bump version to …' merges or workflow_dispatch."
50+
51+
tag-on-version-bump-merge:
52+
name: Tag release on version-bump merge
3153
runs-on: ubuntu-latest
3254
if: |
33-
github.event_name == 'workflow_dispatch' ||
34-
(
35-
github.event_name == 'push' &&
36-
!contains(github.event.head_commit.message, 'chore: bump version')
37-
)
55+
github.event_name == 'push' &&
56+
contains(github.event.head_commit.message, 'chore: bump version to')
3857
outputs:
39-
new_version: ${{ steps.bump.outputs.new_version }}
40-
old_version: ${{ steps.bump.outputs.old_version }}
58+
version: ${{ steps.version.outputs.version }}
59+
tagged: ${{ steps.tag.outputs.tagged }}
4160
steps:
4261
- uses: actions/checkout@v4
4362
with:
4463
fetch-depth: 0
45-
token: ${{ secrets.GITHUB_TOKEN }}
4664

47-
- name: Configure Git
65+
- name: Read VERSION_CLI
66+
id: version
67+
run: |
68+
VERSION=$(tr -d '[:space:]' < VERSION_CLI)
69+
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][A-Za-z0-9.]+)?$ ]]; then
70+
echo "::error::VERSION_CLI is missing or not a valid version"
71+
exit 1
72+
fi
73+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
74+
echo "Release version from VERSION_CLI: $VERSION"
75+
76+
- name: Verify bump commit message
77+
env:
78+
VERSION: ${{ steps.version.outputs.version }}
4879
run: |
80+
expected="chore: bump version to ${VERSION}"
81+
MSG=$(git log -1 --pretty=%B)
82+
if ! printf '%s\n' "$MSG" | grep -F -q "$expected"; then
83+
echo "::error::Head commit must contain '${expected}'"
84+
exit 1
85+
fi
86+
./scripts/check-cli-version.sh
87+
88+
- name: Create and push tag
89+
id: tag
90+
env:
91+
VERSION: ${{ steps.version.outputs.version }}
92+
run: |
93+
TAG="v${VERSION}"
94+
if git rev-parse "$TAG" >/dev/null 2>&1; then
95+
echo "Tag $TAG already exists; skipping"
96+
echo "tagged=false" >> "$GITHUB_OUTPUT"
97+
exit 0
98+
fi
4999
git config user.name "github-actions[bot]"
50100
git config user.email "github-actions[bot]@users.noreply.github.com"
101+
git tag -a "$TAG" -m "Release $TAG"
102+
git push origin "$TAG"
103+
echo "tagged=true" >> "$GITHUB_OUTPUT"
104+
echo "Created and pushed $TAG"
105+
106+
open-bump-pr:
107+
name: Open version-bump PR
108+
runs-on: ubuntu-latest
109+
if: github.event_name == 'workflow_dispatch' && inputs.action == 'open-bump-pr'
110+
steps:
111+
- uses: actions/checkout@v4
112+
with:
113+
ref: main
114+
fetch-depth: 0
51115

52116
- name: Bump version
53117
id: bump
118+
env:
119+
BUMP_TYPE: ${{ inputs.bump_type }}
54120
run: |
121+
case "$BUMP_TYPE" in
122+
patch|minor|major) ;;
123+
*)
124+
echo "::error::bump_type must be patch, minor, or major"
125+
exit 1
126+
;;
127+
esac
55128
OLD_VERSION=$(tr -d '[:space:]' < VERSION_CLI)
56129
echo "old_version=$OLD_VERSION" >> "$GITHUB_OUTPUT"
57-
58-
Bump="${{ github.event_name == 'workflow_dispatch' && inputs.bump_type || 'patch' }}"
59130
chmod +x ./scripts/bump-version.sh
60-
./scripts/bump-version.sh "$Bump"
61-
131+
./scripts/bump-version.sh "$BUMP_TYPE"
62132
NEW_VERSION=$(tr -d '[:space:]' < VERSION_CLI)
63133
echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
64-
echo "Version bumped from $OLD_VERSION to $NEW_VERSION"
65134
66-
- name: Commit version bump
135+
- name: Create pull request
136+
env:
137+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
138+
NEW_VERSION: ${{ steps.bump.outputs.new_version }}
139+
OLD_VERSION: ${{ steps.bump.outputs.old_version }}
67140
run: |
141+
BRANCH="chore/bump-version-${NEW_VERSION}"
142+
git config user.name "github-actions[bot]"
143+
git config user.email "github-actions[bot]@users.noreply.github.com"
144+
git checkout -b "$BRANCH"
68145
git add VERSION_CLI src/cortex-cli/VERSION Cargo.toml Cargo.lock
69-
git commit -m "chore: bump version to ${{ steps.bump.outputs.new_version }}"
70-
git push origin HEAD
146+
git commit -m "chore: bump version to ${NEW_VERSION}"
147+
git push -u origin "$BRANCH"
148+
BODY="Automated version bump from ${OLD_VERSION} to ${NEW_VERSION}. Merge this PR (do not push to main). version-bump.yml then tags v${NEW_VERSION}; release.yml builds artifacts and publish-r2.yml publishes to software.cortex.foundation."
149+
gh pr create \
150+
--base main \
151+
--head "$BRANCH" \
152+
--title "chore: bump version to ${NEW_VERSION}" \
153+
--body "$BODY"
154+
155+
tag-current-version:
156+
name: Tag current VERSION_CLI
157+
runs-on: ubuntu-latest
158+
if: github.event_name == 'workflow_dispatch' && inputs.action == 'tag-current-version'
159+
steps:
160+
- uses: actions/checkout@v4
161+
with:
162+
fetch-depth: 0
163+
164+
- name: Read VERSION_CLI
165+
id: version
166+
run: |
167+
VERSION=$(tr -d '[:space:]' < VERSION_CLI)
168+
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][A-Za-z0-9.]+)?$ ]]; then
169+
echo "::error::VERSION_CLI is missing or not a valid version"
170+
exit 1
171+
fi
172+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
173+
./scripts/check-cli-version.sh
71174
72175
- name: Create and push tag
73-
if: github.event_name == 'push' || inputs.create_release
176+
env:
177+
VERSION: ${{ steps.version.outputs.version }}
74178
run: |
75-
git tag "v${{ steps.bump.outputs.new_version }}"
76-
git push origin "v${{ steps.bump.outputs.new_version }}"
179+
TAG="v${VERSION}"
180+
if git rev-parse "$TAG" >/dev/null 2>&1; then
181+
echo "::error::Tag $TAG already exists"
182+
exit 1
183+
fi
184+
git config user.name "github-actions[bot]"
185+
git config user.email "github-actions[bot]@users.noreply.github.com"
186+
git tag -a "$TAG" -m "Release $TAG"
187+
git push origin "$TAG"
188+
echo "Created and pushed $TAG (triggers release.yml)"
77189
78-
notify:
190+
summary:
79191
name: Summary
80192
runs-on: ubuntu-latest
81-
needs: bump-version
193+
needs: [tag-on-version-bump-merge]
194+
if: always() && needs.tag-on-version-bump-merge.result != 'skipped'
82195
steps:
83196
- name: Summary
197+
env:
198+
VERSION: ${{ needs.tag-on-version-bump-merge.outputs.version }}
199+
TAGGED: ${{ needs.tag-on-version-bump-merge.outputs.tagged }}
84200
run: |
85-
echo "## Version bump" >> "$GITHUB_STEP_SUMMARY"
86-
echo "" >> "$GITHUB_STEP_SUMMARY"
87-
echo "| | |" >> "$GITHUB_STEP_SUMMARY"
88-
echo "|---|---|" >> "$GITHUB_STEP_SUMMARY"
89-
echo "| **Previous** | ${{ needs.bump-version.outputs.old_version }} |" >> "$GITHUB_STEP_SUMMARY"
90-
echo "| **New** | ${{ needs.bump-version.outputs.new_version }} |" >> "$GITHUB_STEP_SUMMARY"
201+
{
202+
echo "## Version tag"
203+
echo ""
204+
echo "| | |"
205+
echo "|---|---|"
206+
echo "| **Version** | ${VERSION} |"
207+
echo "| **Tagged** | ${TAGGED} |"
208+
} >> "$GITHUB_STEP_SUMMARY"

.rules/git.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99
- tests added
1010
- no secrets
1111
- CI on PRs to `main` is required: fmt, clippy `-D warnings`, test, audit, TUI checks.
12-
- Versioning: `.github/workflows/version-bump.yml` patch-bumps and tags on merge to `main`. Do not add another version bot.
12+
- Versioning: bump `VERSION_CLI` / `Cargo.toml` / `src/cortex-cli/VERSION` in a PR; merge tags `v*.*.*` via `.github/workflows/version-bump.yml`. Do not add another version bot or push directly to `main`.
1313
- Do not commit `Cargo.lock` deletions. This is a binary workspace; the lockfile is source of truth.
1414
- PR titles and bodies: Cortex CLI / Cortex Code. Never Grok.

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Short contract for agents working in this repository. Prefer linking over restat
66

77
**Do not** write `Grok`, `Grok Bot`, or `Grok-core` in code, docs, PR titles, or UI copy.
88

9-
Working branch: **`main`**. Releases are annotated tags `v*.*.*` cut on `main` by `.github/workflows/version-bump.yml` (patch bump + tag on merge; `workflow_dispatch` for minor/major).
9+
Working branch: **`main`**. Version bumps land on `main` via PR; `.github/workflows/version-bump.yml` tags `v*.*.*` after a `chore: bump version to …` merge (or `workflow_dispatch` to tag `VERSION_CLI` / open a bump PR). Tags trigger `release.yml`, which publishes to R2 via `publish-r2.yml`.
1010

1111
## Workspace map
1212

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,12 @@ through `generate_tui_demo` and rasterises the frames into `docs/media/intro.gif
179179

180180
## Release and CI secrets
181181

182-
Merges to `main` run [`.github/workflows/version-bump.yml`](.github/workflows/version-bump.yml),
183-
which patch-bumps the version and tags it. Tags run
184-
[`release.yml`](.github/workflows/release.yml), which builds GitHub Release
185-
assets and **automatically** publishes them to Cloudflare R2 /
186-
[software.cortex.foundation](https://software.cortex.foundation) via
187-
[`publish-r2.yml`](.github/workflows/publish-r2.yml).
182+
Version bumps merge to `main` in a normal PR (`chore: bump version to …`).
183+
That merge runs [`.github/workflows/version-bump.yml`](.github/workflows/version-bump.yml),
184+
which tags `v*.*.*`. Tags run [`release.yml`](.github/workflows/release.yml),
185+
which builds GitHub Release assets and **automatically** publishes them to
186+
Cloudflare R2 / [software.cortex.foundation](https://software.cortex.foundation)
187+
via [`publish-r2.yml`](.github/workflows/publish-r2.yml).
188188

189189
This repository does not invent cloud accounts. The secret *names* CI expects are
190190
listed in [docs/CI_SECRETS.md](./docs/CI_SECRETS.md). Values never go in git.

docs/CI_SECRETS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ None of these values belong in git. Do not add AWS access keys or an IAM user fo
88

99
No secrets. `fmt`, `clippy`, `test`, `audit`, and TUI jobs use the public crates.io index and `GITHUB_TOKEN`.
1010

11-
## Version bump (`.github/workflows/version-bump.yml`)
11+
## Version bump / tag (`.github/workflows/version-bump.yml`)
1212

1313
| Secret | Used for |
1414
|--------|----------|
15-
| `GITHUB_TOKEN` | Commit the bump on `main` and push tag `vX.Y.Z` (default Actions token is enough if repo settings allow) |
15+
| `GITHUB_TOKEN` | Open version-bump PRs and push release tags `vX.Y.Z` (no direct commits to protected `main`) |
1616

1717
## Release artifacts (`.github/workflows/release.yml`)
1818

docs/CONTRIBUTING.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,12 @@ update the matching reference page in the same PR.
107107

108108
## Releases
109109

110-
Merging to `main` triggers `.github/workflows/version-bump.yml`, which
111-
patch-bumps the version and tags it. Minor and major bumps are a manual
112-
`workflow_dispatch`. The version lives in `VERSION_CLI`,
110+
Bump the version in a PR (`./scripts/bump-version.sh patch|minor|major`, commit
111+
`chore: bump version to X.Y.Z`). Merging that PR runs
112+
`.github/workflows/version-bump.yml`, which tags `vX.Y.Z` and triggers
113+
`release.yml` (GitHub Release plus automatic R2 publish). Use
114+
`workflow_dispatch` on the same workflow to open an automated bump PR or tag
115+
the current `VERSION_CLI`. The version lives in `VERSION_CLI`,
113116
`[workspace.package].version` and `src/cortex-cli/VERSION`, and
114117
`./scripts/check-cli-version.sh` verifies the three agree — do not introduce a
115118
second scheme.

scripts/bump-version.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,8 @@ else
262262
echo "Next steps:"
263263
echo " 1. Review the changes: git diff"
264264
echo " 2. Commit: git commit -am \"chore: bump version to $NEW_VERSION\""
265-
echo " 3. Tag for release: git tag v$NEW_VERSION"
266-
echo " 4. Push: git push && git push --tags"
265+
echo " 3. Open a PR to main (do not push commits to main directly)"
266+
echo " 4. After merge, version-bump.yml tags v$NEW_VERSION; release.yml builds and publishes"
267267
else
268268
echo ""
269269
echo -e "${RED}ERROR: Version consistency check failed!${NC}"

0 commit comments

Comments
 (0)