with one click
generate-release-ag
// Create a new release, bump version up to the .999 patch threshold, generate a complete CHANGELOG (with PR co-authors + every commit since the last tag), and manage Pull Requests
// Create a new release, bump version up to the .999 patch threshold, generate a complete CHANGELOG (with PR co-authors + every commit since the last tag), and manage Pull Requests
Create a new release, bump version up to the .999 patch threshold, generate a complete CHANGELOG (with PR co-authors + every commit since the last tag), and manage Pull Requests
Create a new release, bump version up to the .999 patch threshold, generate a complete CHANGELOG (with PR co-authors + every commit since the last tag), and manage Pull Requests
Automatically run a browser-automation agent to visually validate all new UI features from the current release and capture evidence WebP recordings of the changes.
Automatically run a browser-automation agent to visually validate all new UI features from the current release and capture evidence WebP recordings of the changes.
Deploy the latest OmniRoute code to the Akamai VPS (69.164.221.35)
Deploy the latest OmniRoute code to BOTH the Akamai VPS and the Local VPS
| name | generate-release-ag |
| description | Create a new release, bump version up to the .999 patch threshold, generate a complete CHANGELOG (with PR co-authors + every commit since the last tag), and manage Pull Requests |
Bump version, build a complete CHANGELOG from every commit since the last tag (with PR back-reference and contributor attribution), commit, open a PR to main and wait for user confirmation before tagging, publishing, and deploying.
VERSION RULE: Always use PATCH bumps (3.x.y → 3.x.y+1) NEVER use
npm version minorornpm version major. Always use:npm version patch --no-git-tag-versionThe threshold rule: whenyreaches 1000, bump to3.(x+1).0— e.g.3.8.999→3.9.0.
🔴 INTEGRATION BRANCH RULE: The
release/vX.Y.Zbranch is the integration target for the entire release cycle. Bug fixes and feature implementations land here via per-issue PRs from short-livedfix/<ISSUE>-<short>orfeat/<ISSUE>-<short>worktrees (see/resolve-issues,/implement-features). Contributor PRs from/review-prslikewise merge into this branch. The release branch is then merged tomainvia a single release PR at the end of the cycle.
Phase 0 → security audit (npm + CodeQL + Dependabot)
Phase 1 → bump → full quality gate → changelog from commits → commit → push → open PR
↕ 🛑 STOP: notify user, wait for PR merge
Phase 2 → deploy main to Local VPS for homologation
↕ 🛑 STOP: notify user, wait for OK
Phase 3 → tag → GitHub release → Docker → npm → Akamai
Phase 4 → monitor CI pipelines and validate artifacts
NEVER push directly to main or create tags before the user confirms the PR.
# 1. Local dependency audit
npm audit --production --audit-level=high
# 2. GitHub CodeQL alerts (open + high severity)
gh api '/repos/diegosouzapw/OmniRoute/code-scanning/alerts?state=open&severity=high' \
--jq '.[] | {rule: .rule.id, path: .most_recent_instance.location.path, msg: .most_recent_instance.message.text}' \
2>/dev/null || echo "(no CodeQL access or no alerts)"
# 3. Dependabot alerts (open + high/critical)
gh api '/repos/diegosouzapw/OmniRoute/dependabot/alerts?state=open' \
--jq '.[] | select(.security_advisory.severity == "high" or .security_advisory.severity == "critical") | {pkg: .dependency.package.name, sev: .security_advisory.severity, summary: .security_advisory.summary}' \
2>/dev/null || echo "(no Dependabot access or no alerts)"
Fix or justify (per Hard Rule #14) any high/critical findings before proceeding.
# To create a new release branch (MUST always be created from main):
git checkout main
git pull origin main
git checkout -b release/v3.9.0
# If continuing the current cycle, just verify:
git branch --show-current
grep '"version"' package.json
🔴 BRANCH-VERSION PARITY GATE:
BRANCH=$(git branch --show-current)
BRANCH_VER=${BRANCH#release/v}
PKG_VER=$(node -p "require('./package.json').version")
if [[ "$BRANCH" != release/v* ]]; then
echo "❌ Not on a release/v* branch (current: $BRANCH). Aborting."; exit 1
fi
echo "Branch target: $BRANCH_VER"
echo "package.json: $PKG_VER"
⚠️ ATOMIC COMMIT RULE — bump and feature/fix code MUST land in the same commit so that
git show vX.Y.Zalways contains both. NEVER commit features first and bump in a separate commit.
npm version patch --no-git-tag-version
npm install
🎯 Goal: produce a complete CHANGELOG section — emoji-grouped sections, PR back-reference, and
— thanks @userattribution. Nothing must slip through.
🔴 NO MIXUPS RULE: do not mix backlog of the previous version. The new section must contain ONLY commits whose merge/landing happened after the previous tag.
LAST_TAG=$(git describe --tags --abbrev=0)
NEW_VERSION=$(node -p "require('./package.json').version")
TODAY=$(date -u +%F)
echo "Range: $LAST_TAG..HEAD → v$NEW_VERSION ($TODAY)"
git log --no-merges "$LAST_TAG..HEAD" --pretty=format:'%h %s' > /tmp/release_commits.txt
wc -l /tmp/release_commits.txt
git log --merges "$LAST_TAG..HEAD" --pretty=format:'%h %s%n author=%an <%ae>' > /tmp/release_merges.txt
git log "$LAST_TAG..HEAD" --pretty=format:'---%n%h | %s%n author=%an <%ae>%n body=%b' > /tmp/release_detailed.txt
grep -oE '#[0-9]+' /tmp/release_commits.txt | sort -u > /tmp/release_prs.txt
> /tmp/release_pr_meta.json
while read -r PR; do
N=${PR#\#}
gh pr view "$N" --repo diegosouzapw/OmniRoute \
--json number,title,author,mergeCommit,body \
>> /tmp/release_pr_meta.json 2>/dev/null || echo "(skip $PR — not found)"
echo "" >> /tmp/release_pr_meta.json
done < /tmp/release_prs.txt
Using /tmp/release_commits.txt + /tmp/release_pr_meta.json + /tmp/release_detailed.txt, build a new entry that:
### ✨ New Features — feat(*)### 🔧 Bug Fixes — fix(*)### 📝 Maintenance — chore(*), refactor(*), docs(*), test(*), ci(*), build(*)### 🔒 Security — security-flagged commits (only if any)- **type(scope):** human-friendly description — extra context if useful. ([#PR](https://github.com/diegosouzapw/OmniRoute/pull/PR) — thanks @author / @coauthor1 / @coauthor2)
(thanks @author).thanks @originalAuthor / @diegosouzapw)./tmp/release_commits.txt. Any unlisted commit must either be explicitly added or consolidated under a roll-up bullet. Do NOT silently drop commits.Layout in CHANGELOG.md (right below ## [Unreleased]):
## [Unreleased]
---
## [3.9.0] — 2026-05-27
### ✨ New Features
- **feat(scope):** description ([#1234](https://github.com/diegosouzapw/OmniRoute/pull/1234) — thanks @author)
### 🔧 Bug Fixes
- **fix(scope):** description ([#1235](https://github.com/diegosouzapw/OmniRoute/pull/1235) — thanks @author / @diegosouzapw)
### 📝 Maintenance
- **chore(scope):** description (thanks @diegosouzapw)
---
## [3.8.999] — 2026-05-20
NEW_VERSION=$(node -p "require('./package.json').version")
COMMITS=$(wc -l < /tmp/release_commits.txt)
BULLETS=$(awk "/^## \\[$NEW_VERSION\\]/{flag=1;next} /^## \\[/{flag=0} flag" CHANGELOG.md | grep -c '^- ')
echo "Commits in range: $COMMITS"
echo "Changelog bullets: $BULLETS"
if [ "$BULLETS" -lt $(( COMMITS / 3 )) ]; then
echo "⚠️ Bullet count looks low (< commits/3). Re-review /tmp/release_commits.txt for missed entries."
fi
VERSION=$(node -p "require('./package.json').version")
sed -i "s/ version: .*/ version: $VERSION/" docs/reference/openapi.yaml
echo "✓ openapi.yaml → $VERSION"
for dir in electron open-sse; do
if [ -d "$dir" ] && [ -f "$dir/package.json" ]; then
(cd "$dir" && npm version "$VERSION" --no-git-tag-version --allow-same-version > /dev/null)
echo "✓ $dir/package.json → $VERSION"
fi
done
npm install
No /update-docs workflow exists (deprecated in v3.8). Apply manually OR via parallel agents:
README.md first (feature table row + "What's new in vX.Y.Z" section).git diff README.md > /tmp/readme.patch.docs/i18n/*/README.md, translating the diff into the target language.docs/<AREA>.md if architecture/counts changed.npm run check:docs-sync && npm run check:docs-all.npm test)Precedent: v3.8.2 landed with 49 broken tests because only
npm testwas running. Lint + typecheck + cycles caught zero of those regressions.
set -e
npm run lint
npm run typecheck:core
npm run check:cycles
npm run check:docs-all
npm test
All five must pass before opening the PR.
VERSION=$(node -p "require('./package.json').version")
git add -A
git commit -m "chore(release): v$VERSION — $(date -u +%F)"
git push origin "release/v$VERSION"
NEVER include
Co-Authored-By:trailers in the release commit (Hard Rule #16). Attribution lives inside the CHANGELOG entries.
VERSION=$(node -p "require('./package.json').version")
awk "/^## \\[$VERSION\\]/{flag=1; print; next} /^---/{if(flag) {flag=0; exit}} flag" CHANGELOG.md > /tmp/changelog_body.txt
{
echo ""
echo "---"
echo ""
echo "### Quality Gate"
echo "- lint: pass"
echo "- typecheck:core: pass"
echo "- check:cycles: pass"
echo "- check:docs-all: pass"
echo "- tests: pass"
echo ""
echo "### Coverage of commits since previous tag"
LAST_TAG=$(git describe --tags --abbrev=0 HEAD~1 2>/dev/null || echo "(no previous tag)")
COMMITS=$(git rev-list --no-merges "$LAST_TAG..HEAD" | wc -l)
echo "- Range: \`$LAST_TAG..HEAD\`"
echo "- Commits inspected: $COMMITS"
echo ""
echo "### ⚠️ After merging: run Phase 2 (Local VPS homologation) before tagging."
} >> /tmp/changelog_body.txt
gh pr create \
--repo diegosouzapw/OmniRoute \
--base main \
--head "release/v$VERSION" \
--title "Release v$VERSION" \
--body-file /tmp/changelog_body.txt
Present the report and stop. Provide:
git diff --stat $LAST_TAG..HEADDO NOT proceed to Phase 2 until the user confirms.
Run only AFTER the user has merged the PR into
mainand all CI jobs pass.
main to the Local VPSDelegate to the deploy-vps-local-ag workflow (single source of truth — do NOT inline SCP/SSH here):
/deploy-vps-local-ag
Provide smoke-test checklist:
GET / returns 200/dashboard)/v1/chat/completions with default provider returns a streampm2 logs omniroute --lines 100Wait for user OK before Phase 3.
git checkout main
git pull origin main
VERSION=$(node -p "require('./package.json').version")
NOTES=$(awk "/^## \\[$VERSION\\]/{flag=1; next} /^---/{if(flag) {flag=0; exit}} flag" CHANGELOG.md | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
[ -z "$NOTES" ] && NOTES="OmniRoute v$VERSION Release"
git tag -a "v$VERSION" -m "Release v$VERSION"
git push origin "v$VERSION"
gh release create "v$VERSION" \
--repo diegosouzapw/OmniRoute \
--title "v$VERSION" \
--notes "$NOTES" \
--target main \
|| gh release edit "v$VERSION" \
--repo diegosouzapw/OmniRoute \
--title "v$VERSION" \
--notes "$NOTES"
gh run list --repo diegosouzapw/OmniRoute --workflow docker-publish.yml --limit 3
gh run watch --repo diegosouzapw/OmniRoute
npm publish
npm info omniroute version
Delegate to deploy-vps-akamai-ag workflow if available, or run the inline equivalent of deploy-vps-local-ag against 69.164.221.35. Do NOT duplicate the procedure here.
VERSION=$(node -p "require('./package.json').version")
PREV=$(git describe --tags --abbrev=0 "v$VERSION^")
gh release edit "v$VERSION" --repo diegosouzapw/OmniRoute --prerelease
git checkout "$PREV" && /deploy-vps-akamai-ag
npm deprecate "omniroute@$VERSION" "broken release — use $PREV"
gh run list --repo diegosouzapw/OmniRoute --workflow docker-publish.yml --limit 1
gh run list --repo diegosouzapw/OmniRoute --workflow electron-release.yml --limit 1
gh run watch <RUN_ID>
npm info omniroute version
gh run view <RUN_ID> --log-failed
VERSION=$(node -p "require('./package.json').version")
gh workflow run <workflow.yml> --repo diegosouzapw/OmniRoute --ref "v$VERSION"
Branch is kept for historical purposes. Do not delete.
docs/* are current BEFORE this workflow — run npm run check:docs-all first.prepublishOnly script runs npm run build:cli automatically during npm publish.npm info omniroute version.npm install after version bump.gh auth switch -u diegosouzapw if git push fails with the wrong account.deploy-vps-local-ag, deploy-vps-akamai-ag if present). Never inline SCP/SSH commands here.| CI failure | Cause | Fix |
|---|---|---|
[docs-sync] FAIL - OpenAPI version differs from package.json | Skipped step 5 — docs/reference/openapi.yaml version not updated | Run step 5 (sed -i ...) and commit |
[docs-sync] FAIL - CHANGELOG.md first section must be "## [Unreleased]" | ## [Unreleased] missing or not at top of CHANGELOG | Add ## [Unreleased]\n\n---\n before the first versioned ## [x.y.z] |
Electron Linux .deb build fails (FpmTarget error) | fpm Ruby gem not installed on ubuntu-latest runner | Already fixed in electron-release.yml (gem install fpm step) |
Docker Hub 502 error writing layer blob | Transient Docker Hub network error during ARM64 push | Re-run the Docker publish workflow; no code change needed |
| Coverage gate fails (statements/lines < 75% or branches < 70%) | Production code changed without tests | Add tests, re-run npm run test:coverage (see CLAUDE.md hard rule #9) |