From 43065d00ae4cb8e0d17ac2d7068c38a4deb6ffc4 Mon Sep 17 00:00:00 2001 From: Elliott de Launay Date: Wed, 13 May 2026 03:04:58 +0000 Subject: [PATCH] feat: release workflow --- .github/workflows/changeset-release.yml | 117 ++++++++++++-------- .roo/commands/release.md | 140 +++++++++++++++++------- 2 files changed, 175 insertions(+), 82 deletions(-) diff --git a/.github/workflows/changeset-release.yml b/.github/workflows/changeset-release.yml index 7c274b0639..76c66632a7 100644 --- a/.github/workflows/changeset-release.yml +++ b/.github/workflows/changeset-release.yml @@ -1,5 +1,5 @@ name: Changeset Release -run-name: Changeset Release ${{ github.actor != 'R00-B0T' && '- Create PR' || '- Update Changelog' }} +run-name: Changeset Release ${{ github.event_name != 'pull_request' && '- Create PR' || github.event.pull_request.user.login != vars.RELEASE_BOT_LOGIN && '- Create PR' || '- Validate Version PR' }} on: workflow_dispatch: @@ -9,24 +9,37 @@ on: env: REPO_PATH: ${{ github.repository }} GIT_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || 'main' }} + VERSION_BUMP_PR_TITLE: Zoo Code changeset version bump jobs: # Job 1: Create version bump PR when changesets are merged to main changeset-pr-version-bump: + # Loop guard: title comparison skips the version-bump PR itself so the job + # doesn't recurse when that PR merges. The title is set by VERSION_BUMP_PR_TITLE. if: > ( github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main' && - github.actor != 'R00-B0T' ) || + github.event.pull_request.title != 'Zoo Code changeset version bump' ) || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: + - name: Generate release bot token + id: release-bot-token + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ vars.RELEASE_APP_ID }} + private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} + permission-contents: write + permission-pull-requests: write + - name: Git Checkout uses: actions/checkout@v4 with: + token: ${{ steps.release-bot-token.outputs.token }} fetch-depth: 0 ref: ${{ env.GIT_REF }} - name: Setup Node.js and pnpm @@ -46,15 +59,15 @@ jobs: id: changesets uses: changesets/action@v1 with: - commit: "changeset version bump" - title: "Changeset version bump" + commit: "chore: zoo code changeset version bump" + title: ${{ env.VERSION_BUMP_PR_TITLE }} version: pnpm changeset:version # This performs the changeset version bump env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ steps.release-bot-token.outputs.token }} - # Job 2: Process version bump PR created by R00-B0T - changeset-pr-edit-approve: - name: Auto approve and merge Bump version PRs + # Job 2: Validate and approve version bump PRs created by the release bot + changeset-pr-validate-approve: + name: Validate and approve Bump version PRs runs-on: ubuntu-latest permissions: contents: write @@ -62,23 +75,30 @@ jobs: if: > github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'main' && - github.actor == 'R00-B0T' && - contains(github.event.pull_request.title, 'Changeset version bump') + github.event.pull_request.user.login == vars.RELEASE_BOT_LOGIN && + github.event.pull_request.title == 'Zoo Code changeset version bump' steps: - name: Determine checkout ref id: checkout-ref + env: + EVENT_ACTION: ${{ github.event.action }} + HEAD_REF: ${{ github.head_ref }} + PR_SHA: ${{ github.event.pull_request.head.sha }} + PR_AUTHOR: ${{ github.event.pull_request.user.login }} + RELEASE_BOT_LOGIN: ${{ vars.RELEASE_BOT_LOGIN }} run: | - echo "Event action: ${{ github.event.action }}" + echo "Event action: $EVENT_ACTION" echo "Actor: ${{ github.actor }}" - echo "Head ref: ${{ github.head_ref }}" - echo "PR SHA: ${{ github.event.pull_request.head.sha }}" + echo "Head ref: $HEAD_REF" + echo "PR SHA: $PR_SHA" + echo "PR author: $PR_AUTHOR" - if [[ "${{ github.event.action }}" == "opened" && "${{ github.actor }}" == "R00-B0T" ]]; then - echo "Using branch ref: ${{ github.head_ref }}" - echo "git_ref=${{ github.head_ref }}" >> $GITHUB_OUTPUT + if [[ "$EVENT_ACTION" == "opened" && "$PR_AUTHOR" == "$RELEASE_BOT_LOGIN" ]]; then + echo "Using branch ref: $HEAD_REF" + echo "git_ref=$HEAD_REF" >> $GITHUB_OUTPUT else - echo "Using SHA ref: ${{ github.event.pull_request.head.sha }}" - echo "git_ref=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT + echo "Using SHA ref: $PR_SHA" + echo "git_ref=$PR_SHA" >> $GITHUB_OUTPUT fi - name: Checkout Repo @@ -88,22 +108,42 @@ jobs: fetch-depth: 0 ref: ${{ steps.checkout-ref.outputs.git_ref }} - # Commit and push changelog updates - - name: Push Changelog updates - if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-ready') }} + - name: Setup Node.js and pnpm + uses: ./.github/actions/setup-node-pnpm + with: + install-args: "--frozen-lockfile" + + - name: Build workspace packages + run: | + pnpm --filter @roo-code/build build + pnpm --filter @roo-code/vscode-webview build + + - name: Validate version bump PR + env: + POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }} run: | - git config user.name "R00-B0T" - git config user.email github-actions@github.com - echo "Running git add and commit..." - git add CHANGELOG.md - git commit -m "Updating CHANGELOG.md format" - git status - echo "--------------------------------------------------------------------------------" - echo "Pushing to remote..." - echo "--------------------------------------------------------------------------------" - git push - - # Add label to indicate changelog has been formatted + package_name=$(node -p "require('./src/package.json').name") + publisher=$(node -p "require('./src/package.json').publisher") + package_version=$(node -p "require('./src/package.json').version") + + test "$package_name" = "zoo-code" + test "$publisher" = "ZooCodeOrganization" + + node -e 'const version = process.argv[1]; if (!/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(version)) { throw new Error("Invalid SemVer version: " + version) }' "$package_version" + grep -q "## \\[$package_version\\]\\|## $package_version" CHANGELOG.md + + pnpm --filter ./src bundle --production + cmp README.md src/README.md + + pnpm --filter ./src vsix + test -f "bin/zoo-code-${package_version}.vsix" + + artifact_name=$(unzip -p "bin/zoo-code-${package_version}.vsix" extension/package.json | jq -r '.name') + artifact_publisher=$(unzip -p "bin/zoo-code-${package_version}.vsix" extension/package.json | jq -r '.publisher') + test "$artifact_name" = "zoo-code" + test "$artifact_publisher" = "ZooCodeOrganization" + + # Add label to indicate release validation passed - name: Add changelog-ready label if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-ready') }} uses: actions/github-script@v7 @@ -117,16 +157,7 @@ jobs: labels: ['changelog-ready'] }); - # Auto-approve PR only after it has been labeled - name: Auto approve PR - if: contains(github.event.pull_request.labels.*.name, 'changelog-ready') uses: hmarr/auto-approve-action@v4 with: - review-message: "I'm approving since it's a bump version PR" - - # Auto-merge PR - - name: Automerge on PR - if: false # Needs enablePullRequestAutoMerge in repo settings to work contains(github.event.pull_request.labels.*.name, 'changelog-ready') - run: gh pr merge --auto --merge ${{ github.event.pull_request.number }} - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + review-message: "Approving the Zoo Code changeset version bump PR after release validation passed" diff --git a/.roo/commands/release.md b/.roo/commands/release.md index 2e09783a58..fc680c1eb4 100644 --- a/.roo/commands/release.md +++ b/.roo/commands/release.md @@ -1,45 +1,107 @@ --- -description: "Create a new release of the Roo Code extension" +description: "Prepare a new release of the Zoo Code extension" argument-hint: patch | minor | major mode: code --- -1. Identify the SHA corresponding to the most recent release using GitHub CLI: `gh release view --json tagName,targetCommitish,publishedAt` -2. Analyze changes since the last release using: `gh pr list --state merged --base main --json number,title,author,url,mergedAt,closingIssuesReferences --limit 1000 -q '[.[] | select(.mergedAt > "TIMESTAMP") | {number, title, author: .author.login, url, mergedAt, issues: .closingIssuesReferences}] | sort_by(.number)'` -3. For each PR with linked issues, fetch the issue details to get the issue reporter: `gh issue view ISSUE_NUMBER --json number,author -q '{number, reporter: .author.login}'` -4. Summarize the changes. If the user did not specify, ask them whether this should be a major, minor, or patch release. -5. Create a changeset in .changeset/v[version].md instead of directly modifying package.json. The format is: +1. Identify the most recent stable extension release: -``` ---- -"roo-cline": patch|minor|major ---- -[list of changes] -``` - -- Always include contributor attribution and the PR number: use "(PR # by @username)". -- For PRs that close issues, include both the issue number and the PR number and authors: "- Fix: Description (#123 by @reporter, PR #456 by @contributor)" -- For PRs without linked issues, include the PR number and author: "- Add support for feature (PR #456 by @contributor)" -- Provide brief descriptions of each item to explain the change -- Order the list from most important to least important -- Example formats: - - With issue: "- Fix: Resolve memory leak in extension (#456 by @issueReporter, PR #789 by @prAuthor)" - - Without issue: "- Add support for Gemini 2.5 Pro caching (PR #789 by @contributor)" -- CRITICAL: Include EVERY SINGLE PR in the changeset - don't assume you know which ones are important. Count the total PRs to verify completeness and cross-reference the list to ensure nothing is missed. - -6. If the generate_image tool is available, create a release image at `releases/[version]-release.png` - - The image should feature a realistic-looking kangaroo doing something human-like that relates to the main highlight of the release - - Pass `releases/template.png` as the reference image for aspect ratio and kangaroo style - - Add the generated image to .changeset/v[version].md before the list of changes with format: `![X.Y.Z Release - Description](/releases/X.Y.Z-release.png)` -7. If a major or minor release: - - Ask the user what the three most important areas to highlight are in the release - - Update the English version relevant announcement files and documentation (webview-ui/src/components/chat/Announcement.tsx, README.md, and the `latestAnnouncementId` in src/core/webview/ClineProvider.ts) - - Ask the user to confirm that the English version looks good to them before proceeding - - Use the new_task tool to create a subtask in `translate` mode with detailed instructions of which content needs to be translated into all supported languages (The READMEs as well as the translation strings) -8. Create a new branch for the release preparation: `git checkout -b release/v[version]` -9. Commit and push the changeset file and any documentation updates to the repository: `git add . && git commit -m "chore: add changeset for v[version]" && git push origin release/v[version]` -10. Create a pull request for the release: `gh pr create --title "Release v[version]" --body "Release preparation for v[version]. This PR includes the changeset and any necessary documentation updates." --base main --head release/v[version]` -11. The GitHub Actions workflow will automatically: - - Create a version bump PR when changesets are merged to main - - Update the CHANGELOG.md with proper formatting - - Publish the release when the version bump PR is merged + ```bash + gh release view --json tagName,targetCommitish,publishedAt + ``` + +2. Analyze changes since that release: + + ```bash + gh pr list --state merged --base main --json number,title,author,url,mergedAt,closingIssuesReferences --limit 1000 -q '[.[] | select(.mergedAt > "TIMESTAMP") | {number, title, author: .author.login, url, mergedAt, issues: .closingIssuesReferences}] | sort_by(.number)' + ``` + +3. For each PR with linked issues, fetch the issue reporter: + + ```bash + gh issue view ISSUE_NUMBER --json number,author -q '{number, reporter: .author.login}' + ``` + +4. Summarize the changes. If the user did not specify a release type, ask whether this should be a major, minor, or patch release. + +5. Review and update the Marketplace-facing root `README.md`. + + - Treat root `README.md` as the source of truth for Marketplace content. + - Update the "What's New" section for the release when appropriate. + - Do not manually edit `src/README.md`; the extension bundle step copies root `README.md` into `src/README.md`. + - Check for stale upstream Roo Code wording that should now say Zoo Code. + +6. Create a changeset in `.changeset/v[version].md` instead of directly modifying `src/package.json`. The format is: + + ```md + --- + "zoo-code": patch|minor|major + --- + + [list of changes] + ``` + + - Always include contributor attribution and the PR number: use `(PR # by @username)`. + - For PRs that close issues, include both issue and PR authors: `- Fix: Description (#123 by @reporter, PR #456 by @contributor)`. + - For PRs without linked issues, include the PR number and author: `- Add support for feature (PR #456 by @contributor)`. + - Provide brief descriptions of each item to explain the change. + - Order the list from most important to least important. + - Include every PR in the release window. Count the PRs and cross-reference the list before creating the PR. + +7. If an image generation tool is available, create a release image at `releases/[version]-release.png`. + + - The image should relate to the main release highlight and fit the existing release-image style. + - Add the generated image to `.changeset/v[version].md` before the list of changes: + + ```md + ![X.Y.Z Release - Description](/releases/X.Y.Z-release.png) + ``` + +8. For a major or minor release: + + - Ask the user what three areas should be highlighted. + - Update relevant announcement files and documentation, including `webview-ui/src/components/chat/Announcement.tsx`, `README.md`, and the `latestAnnouncementId` in `src/core/webview/ClineProvider.ts`. + - Ask the user to confirm the English announcement before proceeding. + - Arrange translation updates for all supported locales affected by README, announcement, or package localization changes. + +9. Create and push a release-prep branch: + + ```bash + git checkout -b release/v[version] + git add .changeset/v[version].md README.md releases/[version]-release.png + git commit -m "chore: add changeset for v[version]" + git push origin release/v[version] + ``` + + Adjust the staged files to match the actual release changes. + +10. Create the release-prep PR: + + ```bash + gh pr create --title "Release v[version]" --body "Release preparation for v[version]. This PR includes the changeset, Marketplace README updates, and any release assets or announcement updates." --base main --head release/v[version] + ``` + +11. After the release-prep PR is merged, GitHub Actions should create a version-bump PR titled `Zoo Code changeset version bump`. + + - That PR should update `src/package.json`, `CHANGELOG.md`, `src/CHANGELOG.md`, and remove consumed changesets. + - The validation workflow should verify extension identity, changelog content, README sync, and VSIX packaging. + - The workflow expects these repository settings: + - Variable `RELEASE_APP_ID`: the release GitHub App ID. + - Secret `RELEASE_APP_PRIVATE_KEY`: the release GitHub App private key. + - Variable `RELEASE_BOT_LOGIN`: the PR author login for release bot PRs, currently expected to be `app/roomote`. + - A human should review and merge this version-bump PR. + +12. After the version-bump PR is merged, create the release tag on the resulting `main` commit: + + ```bash + git switch main + git pull origin main + git tag v[version] + git push origin v[version] + ``` + +13. The stable publish workflow runs from the `v[version]` tag. + + - Do not create the tag before the version-bump PR is merged. + - The publish workflow validates that the tag version matches `src/package.json`. + - Marketplace and Open VSX publishing use the configured CI secrets.