Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/scripts/release.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ if (existsSync(preJsonPath)) {
runCommand('node', [join(__dirname, 'tag-extension.mjs')]);

// Run changeset publish for npm packages
runCommand('npx', ['changeset', 'publish']);
runCommand('bunx', ['changeset', 'publish']);

console.log('βœ… Release process completed!');

Expand Down
21 changes: 20 additions & 1 deletion .github/scripts/tag-extension.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env node
import assert from 'node:assert/strict';
import { spawnSync } from 'node:child_process';
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
Expand Down Expand Up @@ -30,4 +31,22 @@ assert(pkg.version, 'package.json must have a version field');
const tag = `${pkg.name}@${pkg.version}`;

// Create and push the tag if it doesn't exist
createAndPushTag(tag);
const tagCreated = createAndPushTag(tag);

// Trigger extension release workflow via workflow_dispatch
// (push events from GITHUB_TOKEN don't trigger workflows, but workflow_dispatch does)
if (tagCreated) {
console.log(`Triggering extension-release workflow for ${tag}...`);
const result = spawnSync(
'gh',
['workflow', 'run', 'extension-release.yml', '--ref', tag],
{ encoding: 'utf8', stdio: 'inherit' }
);
if (result.status === 0) {
console.log(`βœ… Triggered extension release workflow for ${tag}`);
} else {
console.warn(
`⚠️ Failed to trigger extension release workflow (non-critical)`
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extension release failures are silently ignored

Medium Severity

When gh workflow run fails, tag-extension.mjs only logs a warning and continues. Since tag pushes created by GITHUB_TOKEN do not trigger workflows, this can complete release.mjs successfully while skipping extension-release.yml, leaving the extension unpublished with no failing CI signal.

Fix in CursorΒ Fix in Web

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extension publish failure is silently ignored

Medium Severity

tag-extension.mjs treats gh workflow run extension-release.yml failures as non-critical, so bun run release can succeed even when the extension release never starts. Because dispatch only runs when createAndPushTag returns true, a later rerun skips dispatch once the tag already exists, leaving that version unpublished.

Additional Locations (1)

Fix in CursorΒ Fix in Web

}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Workflow dispatch lacks required actions: write permission

Medium Severity

The newly added gh workflow run call in tag-extension.mjs requires the GITHUB_TOKEN to have actions: write permission to invoke the workflow dispatch API. However, the release.yml workflow only declares contents: write, pull-requests: write, and id-token: write β€” the actions permission is absent. This means the gh workflow run call will always fail silently, and since tag pushes from GITHUB_TOKEN also don't trigger workflows, the extension release will never be auto-triggered.

Additional Locations (1)

Fix in CursorΒ Fix in Web

}
51 changes: 35 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ env:
DO_NOT_TRACK: 1
NODE_ENV: development
NODE_VERSION: 20
BUN_VERSION: 1.3.12

jobs:
# Single install job that caches node_modules for all other jobs
Expand All @@ -32,16 +33,20 @@ jobs:
with:
node-version: ${{ env.NODE_VERSION }}

- uses: oven-sh/setup-bun@v2
with:
bun-version: ${{ env.BUN_VERSION }}

- name: Cache node_modules
id: cache-node-modules
uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-node${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}
key: node-modules-${{ runner.os }}-bun${{ env.BUN_VERSION }}-${{ hashFiles('bun.lock') }}

- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: npm ci
run: bun install

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI no longer enforces lockfile consistency

Medium Severity

Replacing npm ci with plain bun install removes strict lockfile validation in CI. bun install can regenerate bun.lock instead of failing when manifests and lockfile diverge, so workflows may pass with dependency states that are not actually committed.

Additional Locations (2)

Fix in CursorΒ Fix in Web

timeout-minutes: 5

# Fast checks that can run in parallel
Expand All @@ -56,20 +61,24 @@ jobs:
with:
node-version: ${{ env.NODE_VERSION }}

- uses: oven-sh/setup-bun@v2
with:
bun-version: ${{ env.BUN_VERSION }}

- name: Restore node_modules cache
id: cache-node-modules
uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-node${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}
key: node-modules-${{ runner.os }}-bun${{ env.BUN_VERSION }}-${{ hashFiles('bun.lock') }}

- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: npm ci
run: bun install
timeout-minutes: 5

- name: Format Check
run: npm run format-check
run: bun run format-check
env:
FORCE_COLOR: 1

Expand All @@ -93,7 +102,6 @@ jobs:
if: steps.changes.outputs.changesets == 'true'
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"

- name: Validate changeset package references
if: steps.changes.outputs.changesets == 'true'
Expand All @@ -116,20 +124,24 @@ jobs:
with:
node-version: ${{ env.NODE_VERSION }}

- uses: oven-sh/setup-bun@v2
with:
bun-version: ${{ env.BUN_VERSION }}

- name: Restore node_modules cache
id: cache-node-modules
uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-node${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}
key: node-modules-${{ runner.os }}-bun${{ env.BUN_VERSION }}-${{ hashFiles('bun.lock') }}

- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: npm ci
run: bun install
timeout-minutes: 5

- name: Typecheck
run: npm run turbo:typecheck
run: bun run turbo:typecheck
env:
FORCE_COLOR: 1

Expand All @@ -145,20 +157,24 @@ jobs:
with:
node-version: ${{ env.NODE_VERSION }}

- uses: oven-sh/setup-bun@v2
with:
bun-version: ${{ env.BUN_VERSION }}

- name: Restore node_modules cache
id: cache-node-modules
uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-node${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}
key: node-modules-${{ runner.os }}-bun${{ env.BUN_VERSION }}-${{ hashFiles('bun.lock') }}

- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: npm ci
run: bun install
timeout-minutes: 5

- name: Build
run: npm run turbo:build
run: bun run turbo:build
env:
NODE_ENV: production
FORCE_COLOR: 1
Expand Down Expand Up @@ -186,16 +202,20 @@ jobs:
with:
node-version: ${{ env.NODE_VERSION }}

- uses: oven-sh/setup-bun@v2
with:
bun-version: ${{ env.BUN_VERSION }}

- name: Restore node_modules cache
id: cache-node-modules
uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-node${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }}
key: node-modules-${{ runner.os }}-bun${{ env.BUN_VERSION }}-${{ hashFiles('bun.lock') }}

- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: npm ci
run: bun install
timeout-minutes: 5

- name: Download build artifacts
Expand All @@ -205,8 +225,7 @@ jobs:
path: dist/

- name: Run Tests
run: |
npm run test:coverage -- --coverageThreshold '{"global":{"branches":0,"functions":0,"lines":0,"statements":0}}' --detectOpenHandles --forceExit
run: bun run turbo:test

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI tests silently drop coverage collection

Medium Severity

The CI test command changed from npm run test:coverage (which generated coverage data with explicit thresholds) to bun run turbo:test, which runs each package's test script β€” all of which now specify --coverage=false. This silently stops collecting coverage in CI, while the Upload Test Results step still references a coverage directory that will never be generated. A test:ci script exists in root package.json (running turbo test:ci) and in apps/cli and apps/mcp, specifically designed for CI with --coverage enabled, but it's not being used.

Additional Locations (1)
Fix in CursorΒ Fix in Web

Reviewed by Cursor Bugbot for commit 83f65c2. Configure here.

env:
NODE_ENV: test
CI: true
Expand Down
60 changes: 32 additions & 28 deletions .github/workflows/extension-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ on:
permissions:
contents: read

env:
BUN_VERSION: 1.3.12
NODE_VERSION: 20

jobs:
setup:
runs-on: ubuntu-latest
Expand All @@ -29,20 +33,20 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 20
node-version: ${{ env.NODE_VERSION }}

- uses: oven-sh/setup-bun@v2
with:
bun-version: ${{ env.BUN_VERSION }}

- name: Cache node_modules
uses: actions/cache@v4
with:
path: |
node_modules
*/*/node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
path: node_modules
key: node-modules-${{ runner.os }}-bun${{ env.BUN_VERSION }}-${{ hashFiles('bun.lock') }}

- name: Install Monorepo Dependencies
run: npm ci
run: bun install
timeout-minutes: 5

typecheck:
Expand All @@ -53,25 +57,25 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 20
node-version: ${{ env.NODE_VERSION }}

- uses: oven-sh/setup-bun@v2
with:
bun-version: ${{ env.BUN_VERSION }}

- name: Restore node_modules
uses: actions/cache@v4
with:
path: |
node_modules
*/*/node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
path: node_modules
key: node-modules-${{ runner.os }}-bun${{ env.BUN_VERSION }}-${{ hashFiles('bun.lock') }}

- name: Install if cache miss
run: npm ci
run: bun install
timeout-minutes: 3

- name: Type Check Extension
working-directory: apps/extension
run: npm run typecheck
run: bun run typecheck
env:
FORCE_COLOR: 1

Expand All @@ -83,31 +87,31 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 20
node-version: ${{ env.NODE_VERSION }}

- uses: oven-sh/setup-bun@v2
with:
bun-version: ${{ env.BUN_VERSION }}

- name: Restore node_modules
uses: actions/cache@v4
with:
path: |
node_modules
*/*/node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
path: node_modules
key: node-modules-${{ runner.os }}-bun${{ env.BUN_VERSION }}-${{ hashFiles('bun.lock') }}

- name: Install if cache miss
run: npm ci
run: bun install
timeout-minutes: 3

- name: Build Extension
working-directory: apps/extension
run: npm run build
run: bun run build
env:
FORCE_COLOR: 1

- name: Package Extension
working-directory: apps/extension
run: npm run package
run: bun run package
env:
FORCE_COLOR: 1

Expand All @@ -123,7 +127,7 @@ jobs:

- name: Create VSIX Package (Test)
working-directory: apps/extension/vsix-build
run: npx vsce package --no-dependencies
run: bunx vsce package --no-dependencies
env:
FORCE_COLOR: 1

Expand Down
Loading
Loading