diff --git a/.github/workflows/release-ide.yml b/.github/workflows/release-ide.yml new file mode 100644 index 0000000..b5f0732 --- /dev/null +++ b/.github/workflows/release-ide.yml @@ -0,0 +1,131 @@ +name: Release IDE Extensions + +on: + push: + tags: + - "ide-v*.*.*" + workflow_dispatch: + inputs: + dry-run: + description: "Dry run (don't actually publish)" + required: false + type: boolean + default: false + +jobs: + release: + name: Build and Publish IDE Extensions + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Extract version from tag + id: version + run: | + if [[ "${{ github.event_name }}" == "push" ]]; then + # Extract version from tag (ide-v1.2.3 -> 1.2.3) + VERSION="${GITHUB_REF#refs/tags/ide-v}" + else + # For manual trigger, read from package.json + VERSION=$(jq -r .version packages/vscode/package.json) + fi + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Extracted version: $VERSION" + + - name: Verify tag version matches package.json + if: ${{ github.event_name == 'push' }} + run: | + PKG_VERSION=$(jq -r .version packages/vscode/package.json) + TAG_VERSION="${{ steps.version.outputs.version }}" + if [[ "$PKG_VERSION" != "$TAG_VERSION" ]]; then + echo "Error: Tag version ($TAG_VERSION) does not match package.json version ($PKG_VERSION)" + echo "The tag must match the committed version. Ensure you've merged the Version Packages PR first." + exit 1 + fi + echo "Version verified: $PKG_VERSION" + + - name: Log manual run version source + if: ${{ github.event_name == 'workflow_dispatch' }} + run: | + VERSION=$(jq -r .version packages/vscode/package.json) + echo "Manual run uses package.json version: $VERSION" + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version-file: package.json + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Build VS Code extension + run: bunx turbo run build --filter=t-req-vscode... + + - name: Run VS Code unit tests + run: bun run --cwd packages/vscode test:unit + + - name: Run VS Code integration tests + run: xvfb-run -a bun run --cwd packages/vscode test:integration + + - name: Package VSIX + id: package + working-directory: packages/vscode + run: | + VERSION="${{ steps.version.outputs.version }}" + VSIX_NAME="t-req-vscode-${VERSION}.vsix" + bunx @vscode/vsce package --no-dependencies --out "$VSIX_NAME" + SHA256=$(sha256sum "$VSIX_NAME" | awk '{print $1}') + echo "vsix_name=$VSIX_NAME" >> "$GITHUB_OUTPUT" + echo "sha256=$SHA256" >> "$GITHUB_OUTPUT" + echo "Created $VSIX_NAME" + echo "SHA256: $SHA256" + + - name: Upload VSIX artifact + uses: actions/upload-artifact@v4 + with: + name: t-req-ide-vsix + path: packages/vscode/${{ steps.package.outputs.vsix_name }} + + - name: Publish to VS Code Marketplace + if: ${{ github.event_name == 'push' || !inputs.dry-run }} + working-directory: packages/vscode + env: + VSCE_PAT: ${{ secrets.VSCE_PAT }} + run: | + if [[ -z "$VSCE_PAT" ]]; then + echo "Missing VSCE_PAT secret" + exit 1 + fi + bunx @vscode/vsce publish --packagePath "${{ steps.package.outputs.vsix_name }}" --pat "$VSCE_PAT" + + - name: Publish to Cursor (OpenVSX) + if: ${{ github.event_name == 'push' || !inputs.dry-run }} + working-directory: packages/vscode + env: + OVSX_TOKEN: ${{ secrets.OVSX_TOKEN }} + run: | + if [[ -z "$OVSX_TOKEN" ]]; then + echo "Missing OVSX_TOKEN secret" + exit 1 + fi + bunx ovsx publish "${{ steps.package.outputs.vsix_name }}" -p "$OVSX_TOKEN" + + - name: Dry run summary + if: ${{ github.event_name == 'workflow_dispatch' && inputs.dry-run }} + run: | + echo "=== DRY RUN SUMMARY ===" + echo "Version: ${{ steps.version.outputs.version }}" + echo "VSIX: packages/vscode/${{ steps.package.outputs.vsix_name }}" + echo "SHA256: ${{ steps.package.outputs.sha256 }}" + echo "" + echo "[dry-run] Would publish to VS Code Marketplace" + echo "[dry-run] Would publish to Cursor (OpenVSX)" diff --git a/package.json b/package.json index 8ca0c26..fcc2c9c 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "release:app": "bun run script/release.ts --package app", "release:core": "bun run script/release.ts --package core", "release:sdk": "bun run script/release.ts --package sdk", + "release:ide": "bun run script/release.ts --package ide", "release:plugin-base": "bun run script/release.ts --package plugin-base", "release:plugin-assert": "bun run script/release.ts --package plugin-assert", "sst:dev": "sst dev", diff --git a/script/release.ts b/script/release.ts index f8f0ca5..b729375 100644 --- a/script/release.ts +++ b/script/release.ts @@ -31,6 +31,7 @@ const PACKAGES: Record = { core: { path: 'packages/core', tagPrefix: 'core-v' }, app: { path: 'packages/app', tagPrefix: 'app-v' }, sdk: { path: 'packages/sdk/js', tagPrefix: 'sdk-v' }, + ide: { path: 'packages/vscode', tagPrefix: 'ide-v' }, 'plugin-base': { path: 'packages/plugins/base', tagPrefix: 'plugin-base-v' }, 'plugin-assert': { path: 'packages/plugins/assert', tagPrefix: 'plugin-assert-v' } }; @@ -75,7 +76,7 @@ function printHelp(): void { Usage: bun run script/release.ts [options] Options: - --package, -p Package to release (core, app, sdk, plugin-base, plugin-assert). Can be specified multiple times. + --package, -p Package to release (core, app, sdk, ide, plugin-base, plugin-assert). Can be specified multiple times. --dry-run, -n Show what would be done without making changes --help, -h Show this help message @@ -83,6 +84,7 @@ Examples: bun run script/release.ts --package core bun run script/release.ts --package app --dry-run bun run script/release.ts --package sdk + bun run script/release.ts --package ide bun run script/release.ts --package plugin-base bun run script/release.ts --package plugin-assert bun run script/release.ts --package core --package app