From ed743c1f7f3e315ca488bc8474f25a575c8200f7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 21:47:45 +0000 Subject: [PATCH 1/5] Initial plan From 24e9592c1c00f0d275cc2db2a68b5854b47817f1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 22:00:27 +0000 Subject: [PATCH 2/5] Automate release pipeline: one-trigger workflow with marketplace publish, changelog updates, and proper release notes - Rewrite release.yml to generate notes from merged PRs (fixes empty release notes) - Update CHANGELOG.md before VSIX packaging (fixes always-out-of-date changelog) - Add publish job for automated VS Code Marketplace publishing via VSCE_PAT secret - Add update-changelog job to create PR with synced CHANGELOG.md after release - Add publish_marketplace workflow input and upload VSIX as workflow artifact - Update sync-release-notes.yml to manual-only (avoid duplicate PRs) - Update CONTRIBUTING.md with simplified one-step release process - Update publish.ps1 header to mark as manual fallback - Update pre-release.js checklist to reflect new streamlined process Co-authored-by: rajbos <6085745+rajbos@users.noreply.github.com> --- .github/workflows/release.yml | 213 +++++++++++++++++++++-- .github/workflows/sync-release-notes.yml | 42 ++--- CONTRIBUTING.md | 79 +++------ publish.ps1 | 12 +- scripts/pre-release.js | 15 +- 5 files changed, 247 insertions(+), 114 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cca41024..134fde67 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,14 +3,19 @@ name: Release on: push: tags: - - 'v*' # Triggers on version tags like v1.0.0, v1.2.3, etc. - workflow_dispatch: # Allows manual trigger from GitHub UI + - 'v*' # Tag push: build + GitHub release only (no marketplace publish) + workflow_dispatch: # Manual trigger: full pipeline including marketplace publish inputs: create_tag: description: 'Create tag from package.json version' required: false default: 'true' type: boolean + publish_marketplace: + description: 'Publish to VS Code Marketplace after creating the release' + required: false + default: 'true' + type: boolean permissions: contents: read @@ -20,6 +25,10 @@ jobs: permissions: contents: write runs-on: ubuntu-latest + outputs: + version: ${{ steps.extract_version.outputs.tag_version }} + tag_name: ${{ steps.tag_name.outputs.tag_name }} + vsix_file: ${{ steps.vsix_filename.outputs.vsix_file }} steps: - name: Harden the runner (Audit all outbound calls) @@ -123,6 +132,47 @@ jobs: fi echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT echo "Tag name: $TAG_NAME" + + - name: Generate release notes + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + TAG_NAME="${{ steps.tag_name.outputs.tag_name }}" + VERSION="${{ steps.extract_version.outputs.tag_version }}" + echo "Generating release notes for $TAG_NAME..." + + # Use GitHub API to auto-generate notes from merged PRs since last release + if gh api repos/${{ github.repository }}/releases/generate-notes \ + -f tag_name="${TAG_NAME}" \ + --jq '.body' > /tmp/release_notes.md 2>/dev/null && [ -s /tmp/release_notes.md ]; then + echo "✅ Generated release notes from merged PRs" + else + echo "Release ${VERSION}" > /tmp/release_notes.md + echo "⚠️ Could not auto-generate notes, using fallback" + fi + + echo "--- Release notes preview ---" + cat /tmp/release_notes.md + echo "---" + + - name: Update CHANGELOG.md for VSIX packaging + run: | + VERSION="${{ steps.extract_version.outputs.tag_version }}" + node -e " + const fs = require('fs'); + const version = process.argv[1]; + const notes = fs.readFileSync('/tmp/release_notes.md', 'utf8').trim(); + let changelog = fs.readFileSync('CHANGELOG.md', 'utf8'); + const marker = '## [Unreleased]'; + const idx = changelog.indexOf(marker); + if (idx >= 0) { + const insertAt = changelog.indexOf('\n', idx) + 1; + const section = '\n## [' + version + ']\n\n' + notes + '\n'; + changelog = changelog.slice(0, insertAt) + section + changelog.slice(insertAt); + } + fs.writeFileSync('CHANGELOG.md', changelog); + console.log('✅ Updated CHANGELOG.md with v' + version + ' notes for VSIX packaging'); + " "$VERSION" - name: Install dependencies run: npm ci @@ -158,22 +208,13 @@ jobs: VSIX_FILE=$(ls *.vsix | head -n 1) echo "vsix_file=$VSIX_FILE" >> $GITHUB_OUTPUT echo "VSIX file: $VSIX_FILE" - - - name: Generate release notes - run: | - # Extract the latest changes from CHANGELOG.md if it has been updated - # Write to a file to avoid shell interpretation issues with special characters - if grep -q "## \[.*\]" CHANGELOG.md; then - # Try to extract the latest version section from changelog - NOTES=$(sed -n '/## \[.*\]/,/## \[.*\]/p' CHANGELOG.md | head -n -1 | tail -n +2) - if [ -n "$NOTES" ]; then - echo "$NOTES" > /tmp/release_notes.md - else - echo "Release ${{ steps.extract_version.outputs.tag_version }}" > /tmp/release_notes.md - fi - else - echo "Release ${{ steps.extract_version.outputs.tag_version }}" > /tmp/release_notes.md - fi + + - name: Upload VSIX as workflow artifact + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: vsix-package + path: ./${{ steps.vsix_filename.outputs.vsix_file }} + retention-days: 90 - name: Create Release id: create_release @@ -185,7 +226,7 @@ jobs: set -o pipefail echo "Creating release for tag: ${{ steps.tag_name.outputs.tag_name }}" - # Create release with notes from file and upload VSIX file + # Create release with auto-generated notes and upload VSIX file gh release create "${{ steps.tag_name.outputs.tag_name }}" \ --title "Release ${{ steps.extract_version.outputs.tag_version }}" \ --notes-file /tmp/release_notes.md \ @@ -217,3 +258,137 @@ jobs: echo "\`\`\`" >> $GITHUB_STEP_SUMMARY exit 1 fi + + publish: + needs: release + if: github.event_name == 'workflow_dispatch' && inputs.publish_marketplace + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup Node.js + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: '20.x' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Download VSIX from release + id: download_vsix + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + TAG_NAME="${{ needs.release.outputs.tag_name }}" + echo "Downloading VSIX from release $TAG_NAME..." + gh release download "$TAG_NAME" \ + --repo "${{ github.repository }}" \ + --pattern "*.vsix" \ + --dir . + VSIX_FILE=$(ls *.vsix | head -n 1) + echo "Downloaded: $VSIX_FILE" + echo "vsix_file=$VSIX_FILE" >> $GITHUB_OUTPUT + + - name: Publish to VS Code Marketplace + id: publish + env: + VSCE_PAT: ${{ secrets.VSCE_PAT }} + run: | + if [ -z "$VSCE_PAT" ]; then + echo "❌ VSCE_PAT secret is not configured." + echo " Add it at: Settings → Secrets and variables → Actions" + echo " Create a PAT at https://dev.azure.com with 'Marketplace (Publish)' scope" + exit 1 + fi + + echo "Publishing ${{ steps.download_vsix.outputs.vsix_file }} to VS Code Marketplace..." + npx vsce publish \ + --packagePath "${{ steps.download_vsix.outputs.vsix_file }}" \ + --pat "$VSCE_PAT" + + - name: Publish Summary + if: always() + run: | + echo "# 🚀 VS Code Marketplace" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [ "${{ steps.publish.outcome }}" == "success" ]; then + echo "✅ Extension v${{ needs.release.outputs.version }} published to the [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=RobBos.copilot-token-tracker)" >> $GITHUB_STEP_SUMMARY + else + echo "❌ Failed to publish v${{ needs.release.outputs.version }} to marketplace." >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Ensure the \`VSCE_PAT\` secret is configured with a valid Azure DevOps PAT" >> $GITHUB_STEP_SUMMARY + echo "with the \`Marketplace (Publish)\` scope for all accessible organizations." >> $GITHUB_STEP_SUMMARY + fi + + update-changelog: + needs: release + if: always() && needs.release.result == 'success' + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: '20.x' + + - name: Sync CHANGELOG.md from GitHub releases + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: node scripts/sync-changelog.js + + - name: Check for changes + id: changes + run: | + if git diff --quiet CHANGELOG.md; then + echo "changed=false" >> $GITHUB_OUTPUT + echo "ℹ️ No changes needed" + else + echo "changed=true" >> $GITHUB_OUTPUT + echo "Changes detected in CHANGELOG.md" + fi + + - name: Create Pull Request + if: steps.changes.outputs.changed == 'true' + uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 + with: + branch: update-changelog + title: "docs: sync CHANGELOG.md with v${{ needs.release.outputs.version }} release notes" + body: | + Automatically syncs CHANGELOG.md with the latest GitHub release notes. + + Triggered by release workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + commit-message: "docs: sync CHANGELOG.md with GitHub release notes" + + - name: Changelog Summary + if: always() + run: | + echo "# 📝 Changelog Update" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [ "${{ steps.changes.outputs.changed }}" == "true" ]; then + echo "A pull request has been created to update CHANGELOG.md." >> $GITHUB_STEP_SUMMARY + else + echo "CHANGELOG.md is already up to date." >> $GITHUB_STEP_SUMMARY + fi diff --git a/.github/workflows/sync-release-notes.yml b/.github/workflows/sync-release-notes.yml index f0b54e26..1c46983e 100644 --- a/.github/workflows/sync-release-notes.yml +++ b/.github/workflows/sync-release-notes.yml @@ -1,9 +1,9 @@ name: Sync Release Notes +# Manual-only trigger — automated changelog sync is handled by the Release workflow. +# Use this to re-sync CHANGELOG.md from GitHub releases at any time. on: - workflow_dispatch: # Manual trigger - release: - types: [published, edited] # Automatic trigger when releases are published or edited + workflow_dispatch: permissions: contents: read @@ -12,7 +12,8 @@ jobs: sync-release-notes: runs-on: ubuntu-latest permissions: - contents: write # Need write permission to update CHANGELOG.md + contents: write + pull-requests: write steps: - name: Harden the runner (Audit all outbound calls) @@ -23,7 +24,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - fetch-depth: 0 # Fetch all history so we can work with all releases + fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 @@ -33,9 +34,7 @@ jobs: - name: Sync GitHub release notes to CHANGELOG.md env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - # Run the sync script from the scripts directory - node scripts/sync-changelog.js + run: node scripts/sync-changelog.js - name: Check for changes id: changes @@ -47,24 +46,6 @@ jobs: echo "changed=true" >> $GITHUB_OUTPUT echo "Changes detected in CHANGELOG.md" fi - - - name: Ensure on main branch - if: steps.changes.outputs.changed == 'true' - run: | - git checkout -b update-changelog - - - name: Commit and push changes - if: steps.changes.outputs.changed == 'true' - run: | - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - git add CHANGELOG.md - git commit -m "docs: sync CHANGELOG.md with GitHub release notes - - This commit automatically updates the CHANGELOG.md file to match - the release notes from GitHub releases, ensuring consistency - between local documentation and published releases." - git push -u origin update-changelog - name: Create Pull Request if: steps.changes.outputs.changed == 'true' @@ -73,14 +54,15 @@ jobs: branch: update-changelog title: "docs: sync CHANGELOG.md with GitHub release notes" body: | - This pull request updates the CHANGELOG.md file to reflect the latest - GitHub release notes, ensuring that the changelog is always up to date - with the published releases. + Automatically syncs CHANGELOG.md with the latest GitHub release notes. + + Triggered by: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + commit-message: "docs: sync CHANGELOG.md with GitHub release notes" - name: Summary run: | if [ "${{ steps.changes.outputs.changed }}" == "true" ]; then - echo "✅ CHANGELOG.md has been successfully updated with GitHub release notes" + echo "✅ A PR has been created to update CHANGELOG.md with GitHub release notes" else echo "ℹ️ CHANGELOG.md was already up to date with GitHub release notes" fi \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b64b6b12..eae25d00 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -394,84 +394,63 @@ All builds must pass these checks before merging. ## Pre-Release Checklist -Version: 0.0.13 | Last run: 2026-03-01 - -Run `npm run pre-release` to automate steps 1–3 below. +Run `npm run pre-release` to automate steps 1–2 below. - [ ] Version bumped in `package.json` - [ ] `npm run compile` completed successfully -- [ ] Screenshots updated in `docs/images/` (run `npm run pre-release` or update manually) - [ ] Commit and push to main branch -- [ ] Trigger GitHub Actions Release workflow (Method 1: GitHub UI → Actions → Release → Run workflow) -- [ ] Run `./publish.ps1` — syncs `CHANGELOG.md` from the new release, builds the VSIX, and publishes to the marketplace -- [ ] Commit and push the updated `CHANGELOG.md` +- [ ] Trigger Release workflow (GitHub UI → Actions → Release → Run workflow) + +The workflow handles everything else: tagging, building, testing, creating the GitHub release, publishing to the marketplace, and updating the changelog. ## Release Process -The project supports automated VSIX builds and releases through two methods: +The project uses a fully automated release pipeline via GitHub Actions. -### Method 1: Manual Trigger via GitHub UI (Recommended) +### One-Step Release (Recommended) 1. **Update the version** in `package.json` -2. **Commit and push** your changes to the main branch -3. **Go to GitHub Actions** → Release workflow -4. **Click "Run workflow"** and confirm - -The workflow will automatically: - -- Create a tag based on the version in `package.json` -- Run the full build pipeline (lint, type-check, compile, test) -- Create a VSIX package -- Create a GitHub release with auto-generated release notes -- Attach the VSIX file as a release asset - -Then run the `./publish.ps1` script to publish to the marketplace. +2. **Commit and push** to the main branch +3. **Go to GitHub Actions** → Release workflow → **Run workflow** -### Method 2: Tag-Based Release (Traditional) +The workflow inputs: +- `create_tag` — Creates a git tag from the `package.json` version (default: true) +- `publish_marketplace` — Publishes to the VS Code Marketplace (default: true) -1. **Update the version** in `package.json` -2. **Commit your changes** -3. **Create and push a version tag:** - ```bash - git tag v1.0.0 - git push origin v1.0.0 - ``` +The workflow automatically: -The release workflow will: +1. Creates a version tag (e.g., `v0.0.19`) +2. Generates release notes from merged PRs (using `.github/release.yml` categories) +3. Updates `CHANGELOG.md` in the VSIX package so the extension ships with current notes +4. Runs the full build pipeline (lint, type-check, compile, test) +5. Creates a GitHub Release with the VSIX attached +6. Publishes to the VS Code Marketplace (using the `VSCE_PAT` secret) +7. Opens a PR to sync `CHANGELOG.md` in the repository -- Verify the tag version matches `package.json` version -- Run the full build pipeline (lint, type-check, compile, test) -- Create a VSIX package -- Create a GitHub release with auto-generated release notes -- Attach the VSIX file as a release asset +> **Security:** Only users with repository write access can trigger the `workflow_dispatch`. The `VSCE_PAT` secret must be configured in repository settings (Settings → Secrets and variables → Actions). Create a PAT at https://dev.azure.com with the "Marketplace (Publish)" scope. -**Note**: The workflow will fail if the tag version doesn't match the version in `package.json`. +### Tag-Based Release (Build Only) -### Syncing Release Notes +Pushing a version tag (e.g., `git push origin v0.0.19`) triggers the build and creates a GitHub release, but does **not** publish to the marketplace. Use the workflow dispatch for the full pipeline. -The project automatically keeps `CHANGELOG.md` synchronized with GitHub release notes: +### Manual Changelog Sync -**Manual Sync:** +To manually sync the changelog with all GitHub release notes: ```bash npm run sync-changelog ``` -**Automatic Sync:** -The GitHub workflow automatically updates `CHANGELOG.md` whenever: +Or trigger the **Sync Release Notes** workflow from the Actions tab. -- A new release is published -- An existing release is edited -- The workflow is manually triggered +### Manual Publish (Fallback) -**Test the Sync:** +If you need to re-publish manually (e.g., after a marketplace upload failure): -```bash -npm run sync-changelog:test +```powershell +.\publish.ps1 -VsixPath ".\copilot-token-tracker-0.0.19.vsix" ``` -This ensures the local changelog always reflects the latest release information from GitHub. - ## Submitting Changes 1. **Fork the repository** on GitHub diff --git a/publish.ps1 b/publish.ps1 index 68b98ebf..c2d1a2d8 100644 --- a/publish.ps1 +++ b/publish.ps1 @@ -1,10 +1,14 @@ # publish.ps1 -# Publishes the extension to the VS Code Marketplace using a VSIX downloaded -# from the GitHub release. Run AFTER the GitHub Actions release workflow has -# created the GitHub release and you have downloaded the .vsix asset. +# Manual fallback for publishing to the VS Code Marketplace. +# +# PRIMARY METHOD: Use the GitHub Actions Release workflow (workflow_dispatch), +# which handles building, testing, releasing, and publishing in one step. +# +# Use this script only when you need to manually publish a pre-built VSIX +# (e.g., re-publishing after a marketplace upload failure). # # Usage: -# .\publish.ps1 -VsixPath ".\copilot-token-tracker-0.0.13.vsix" +# .\publish.ps1 -VsixPath ".\copilot-token-tracker-0.0.18.vsix" param( [string]$VsixPath # Path to the .vsix downloaded from the GitHub release diff --git a/scripts/pre-release.js b/scripts/pre-release.js index 9e5ee586..b4543b97 100644 --- a/scripts/pre-release.js +++ b/scripts/pre-release.js @@ -147,29 +147,22 @@ async function main() { console.log(' 1. Review docs/images/ screenshots and update manually if needed'); console.log(' 2. Commit changes (screenshots + CONTRIBUTING.md)'); console.log(' 3. Push to main branch'); - console.log(' 4. Trigger GitHub Actions Release workflow:'); + console.log(' 4. Trigger the Release workflow from GitHub Actions:'); console.log(' https://github.com/rajbos/github-copilot-token-usage/actions'); - console.log(' 5. Once the release exists, run ./publish.ps1 — it will sync'); - console.log(' CHANGELOG.md from the new release, build, and publish the VSIX.'); - console.log(' 6. Commit and push the updated CHANGELOG.md after publishing.'); + console.log(' (this handles tagging, building, releasing, and publishing)'); console.log(''); } // ─── CONTRIBUTING.md upsert ─────────────────────────────────────────────────── function updateContributingChecklist(filePath, version) { - const today = new Date().toISOString().split('T')[0]; const newSection = `## Pre-Release Checklist\n\n` + - `Version: ${version} | Last run: ${today}\n\n` + - `Run \`npm run pre-release\` to automate steps 1–3 below.\n\n` + + `Run \`npm run pre-release\` to automate steps 1–2 below.\n\n` + `- [ ] Version bumped in \`package.json\`\n` + `- [ ] \`npm run compile\` completed successfully\n` + - `- [ ] Screenshots updated in \`docs/images/\` (run \`npm run pre-release\` or update manually)\n` + `- [ ] Commit and push to main branch\n` + - `- [ ] Trigger GitHub Actions Release workflow (Method 1: GitHub UI → Actions → Release → Run workflow)\n` + - `- [ ] Run \`./publish.ps1\` — syncs \`CHANGELOG.md\` from the new release, builds the VSIX, and publishes to the marketplace\n` + - `- [ ] Commit and push the updated \`CHANGELOG.md\`\n`; + `- [ ] Trigger Release workflow (GitHub UI → Actions → Release → Run workflow)\n`; let content = fs.readFileSync(filePath, 'utf8'); From c4072dd209fd635e7c642f2400bc6c670e6881ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 22:01:55 +0000 Subject: [PATCH 3/5] Address code review: fix step numbering in checklist, capture generate-notes API errors Co-authored-by: rajbos <6085745+rajbos@users.noreply.github.com> --- .github/workflows/release.yml | 5 ++++- CONTRIBUTING.md | 2 +- scripts/pre-release.js | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 134fde67..3823a5e6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -144,11 +144,14 @@ jobs: # Use GitHub API to auto-generate notes from merged PRs since last release if gh api repos/${{ github.repository }}/releases/generate-notes \ -f tag_name="${TAG_NAME}" \ - --jq '.body' > /tmp/release_notes.md 2>/dev/null && [ -s /tmp/release_notes.md ]; then + --jq '.body' > /tmp/release_notes.md 2>/tmp/generate_notes_err.txt && [ -s /tmp/release_notes.md ]; then echo "✅ Generated release notes from merged PRs" else echo "Release ${VERSION}" > /tmp/release_notes.md echo "⚠️ Could not auto-generate notes, using fallback" + if [ -s /tmp/generate_notes_err.txt ]; then + echo " Error: $(cat /tmp/generate_notes_err.txt)" + fi fi echo "--- Release notes preview ---" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eae25d00..a01cca9e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -394,7 +394,7 @@ All builds must pass these checks before merging. ## Pre-Release Checklist -Run `npm run pre-release` to automate steps 1–2 below. +Run `npm run pre-release` to validate the version and compile. - [ ] Version bumped in `package.json` - [ ] `npm run compile` completed successfully diff --git a/scripts/pre-release.js b/scripts/pre-release.js index b4543b97..80ee5860 100644 --- a/scripts/pre-release.js +++ b/scripts/pre-release.js @@ -158,7 +158,7 @@ async function main() { function updateContributingChecklist(filePath, version) { const newSection = `## Pre-Release Checklist\n\n` + - `Run \`npm run pre-release\` to automate steps 1–2 below.\n\n` + + `Run \`npm run pre-release\` to validate the version and compile.\n\n` + `- [ ] Version bumped in \`package.json\`\n` + `- [ ] \`npm run compile\` completed successfully\n` + `- [ ] Commit and push to main branch\n` + From de1a2c4404dabdef6f8eb2cced438069250289ee Mon Sep 17 00:00:00 2001 From: Rob Bos Date: Wed, 18 Mar 2026 09:13:30 +0100 Subject: [PATCH 4/5] update the process --- .github/workflows/release.yml | 166 ++++++++++++++-------------------- 1 file changed, 68 insertions(+), 98 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3823a5e6..b040a30c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,12 +9,12 @@ on: create_tag: description: 'Create tag from package.json version' required: false - default: 'true' + default: true type: boolean publish_marketplace: description: 'Publish to VS Code Marketplace after creating the release' required: false - default: 'true' + default: true type: boolean permissions: @@ -63,41 +63,6 @@ jobs: echo "package_version=$PACKAGE_VERSION" >> $GITHUB_OUTPUT echo "Package version: $PACKAGE_VERSION" - - name: Create tag for manual trigger - if: steps.trigger_type.outputs.is_manual == 'true' && inputs.create_tag - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - VERSION="v${{ steps.package_version.outputs.package_version }}" - echo "Creating tag: $VERSION" - - # Check if tag already exists on remote using exit code - if git ls-remote --exit-code --tags origin "refs/tags/$VERSION" >/dev/null 2>&1; then - echo "❌ Tag $VERSION already exists on remote!" - echo "Please update the version in package.json or delete the existing tag." - exit 1 - fi - - # Create and push the tag - git config --local user.name "github-actions[bot]" - git config --local user.email "github-actions[bot]@users.noreply.github.com" - git tag -a "$VERSION" -m "Release $VERSION" - git push origin "$VERSION" - - # Verify tag was created successfully on remote - echo "Verifying tag was created on remote..." - for i in {1..5}; do - if git ls-remote --exit-code --tags origin "refs/tags/$VERSION" >/dev/null 2>&1; then - echo "✅ Tag $VERSION created and verified on remote" - exit 0 - fi - echo "Waiting for tag to propagate (attempt $i/5)..." - sleep 2 - done - - echo "❌ Failed to verify tag creation on remote" - exit 1 - - name: Extract version from tag id: extract_version run: | @@ -176,6 +141,72 @@ jobs: fs.writeFileSync('CHANGELOG.md', changelog); console.log('✅ Updated CHANGELOG.md with v' + version + ' notes for VSIX packaging'); " "$VERSION" + + - name: Create changelog branch and commit + if: steps.trigger_type.outputs.is_manual == 'true' + id: changelog_branch + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + VERSION="${{ steps.extract_version.outputs.tag_version }}" + BRANCH="changelog/v${VERSION}" + echo "branch=$BRANCH" >> $GITHUB_OUTPUT + + git config --local user.name "github-actions[bot]" + git config --local user.email "github-actions[bot]@users.noreply.github.com" + + # Check if branch already exists on remote + if git ls-remote --exit-code --heads origin "refs/heads/$BRANCH" >/dev/null 2>&1; then + echo "❌ Branch $BRANCH already exists on remote!" + echo "Delete it or bump the version before re-running." + exit 1 + fi + + if git diff --quiet CHANGELOG.md; then + echo "ℹ️ No changes to CHANGELOG.md, skipping branch + commit" + exit 0 + fi + + git checkout -b "$BRANCH" + git add CHANGELOG.md + git commit -m "docs: update CHANGELOG.md for v${VERSION}" + git push origin "$BRANCH" + echo "✅ Pushed CHANGELOG.md update to $BRANCH" + + - name: Create tag for manual trigger + if: steps.trigger_type.outputs.is_manual == 'true' && inputs.create_tag == true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + VERSION="v${{ steps.package_version.outputs.package_version }}" + echo "Creating tag: $VERSION" + + # Check if tag already exists on remote using exit code + if git ls-remote --exit-code --tags origin "refs/tags/$VERSION" >/dev/null 2>&1; then + echo "❌ Tag $VERSION already exists on remote!" + echo "Please update the version in package.json or delete the existing tag." + exit 1 + fi + + # Create and push the tag + git config --local user.name "github-actions[bot]" + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git tag -a "$VERSION" -m "Release $VERSION" + git push origin "$VERSION" + + # Verify tag was created successfully on remote + echo "Verifying tag was created on remote..." + for i in {1..5}; do + if git ls-remote --exit-code --tags origin "refs/tags/$VERSION" >/dev/null 2>&1; then + echo "✅ Tag $VERSION created and verified on remote" + exit 0 + fi + echo "Waiting for tag to propagate (attempt $i/5)..." + sleep 2 + done + + echo "❌ Failed to verify tag creation on remote" + exit 1 - name: Install dependencies run: npm ci @@ -333,65 +364,4 @@ jobs: echo "with the \`Marketplace (Publish)\` scope for all accessible organizations." >> $GITHUB_STEP_SUMMARY fi - update-changelog: - needs: release - if: always() && needs.release.result == 'success' - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 - with: - egress-policy: audit - - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - - - name: Setup Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version: '20.x' - - - name: Sync CHANGELOG.md from GitHub releases - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: node scripts/sync-changelog.js - - - name: Check for changes - id: changes - run: | - if git diff --quiet CHANGELOG.md; then - echo "changed=false" >> $GITHUB_OUTPUT - echo "ℹ️ No changes needed" - else - echo "changed=true" >> $GITHUB_OUTPUT - echo "Changes detected in CHANGELOG.md" - fi - - - name: Create Pull Request - if: steps.changes.outputs.changed == 'true' - uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 - with: - branch: update-changelog - title: "docs: sync CHANGELOG.md with v${{ needs.release.outputs.version }} release notes" - body: | - Automatically syncs CHANGELOG.md with the latest GitHub release notes. - - Triggered by release workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - commit-message: "docs: sync CHANGELOG.md with GitHub release notes" - - name: Changelog Summary - if: always() - run: | - echo "# 📝 Changelog Update" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - if [ "${{ steps.changes.outputs.changed }}" == "true" ]; then - echo "A pull request has been created to update CHANGELOG.md." >> $GITHUB_STEP_SUMMARY - else - echo "CHANGELOG.md is already up to date." >> $GITHUB_STEP_SUMMARY - fi From 32b49f2dc16c940afccc907812f18fda0f82de27 Mon Sep 17 00:00:00 2001 From: Rob Bos Date: Wed, 18 Mar 2026 09:14:02 +0100 Subject: [PATCH 5/5] versionbump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f921657c..b7bb5000 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "copilot-token-tracker", "displayName": "Copilot Token Tracker", "description": "Shows daily and monthly (estimated) GitHub Copilot token usage stats in VS Code status bar", - "version": "0.0.18", + "version": "0.0.19", "publisher": "RobBos", "engines": { "vscode": "^1.110.0"