name: Extension Release on: push: branches: - main paths: - 'apps/extension/**' workflow_dispatch: inputs: force_publish: description: 'Force publish even without version changes' required: false default: false type: boolean permissions: contents: read concurrency: extension-release-${{ github.ref }} jobs: check-version: runs-on: ubuntu-latest outputs: should-publish: ${{ steps.version-check.outputs.should-publish }} current-version: ${{ steps.version-check.outputs.current-version }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Check version changes id: version-check run: | # Get current version from package.json CURRENT_VERSION=$(jq -r '.version' apps/extension/package.json) echo "current-version=$CURRENT_VERSION" >> $GITHUB_OUTPUT # Check if this is a force publish if [ "${{ github.event.inputs.force_publish }}" = "true" ]; then echo "should-publish=true" >> $GITHUB_OUTPUT echo "Force publish requested" exit 0 fi # Check if version changed in the last commit if git diff HEAD~1 HEAD --name-only | grep -q "apps/extension/package.json\|apps/extension/package.publish.json"; then # Check if version field actually changed PREV_VERSION=$(git show HEAD~1:apps/extension/package.json | jq -r '.version') if [ "$CURRENT_VERSION" != "$PREV_VERSION" ]; then echo "should-publish=true" >> $GITHUB_OUTPUT echo "Version changed from $PREV_VERSION to $CURRENT_VERSION" else echo "should-publish=false" >> $GITHUB_OUTPUT echo "No version change detected" fi else echo "should-publish=false" >> $GITHUB_OUTPUT echo "No package.json changes detected" fi build-and-publish: needs: check-version if: needs.check-version.outputs.should-publish == 'true' runs-on: ubuntu-latest environment: extension-release steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-node@v4 with: node-version: 20 - uses: pnpm/action-setup@v4 with: version: latest - name: Cache pnpm dependencies uses: actions/cache@v4 with: path: | ~/.pnpm-store apps/extension/node_modules key: ${{ runner.os }}-extension-pnpm-${{ hashFiles('apps/extension/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-extension-pnpm- - name: Install Extension Dependencies working-directory: apps/extension run: pnpm install --frozen-lockfile timeout-minutes: 5 - name: Run Tests working-directory: apps/extension run: xvfb-run -a pnpm run test env: CI: true FORCE_COLOR: 1 timeout-minutes: 10 - name: Lint Extension working-directory: apps/extension run: pnpm run lint env: FORCE_COLOR: 1 - name: Type Check Extension working-directory: apps/extension run: pnpm run check-types env: FORCE_COLOR: 1 - name: Build Extension working-directory: apps/extension run: pnpm run build env: FORCE_COLOR: 1 - name: Package Extension working-directory: apps/extension run: pnpm run package env: FORCE_COLOR: 1 - name: Verify Package Structure working-directory: apps/extension run: | echo "=== Checking vsix-build structure ===" ls -la vsix-build/ echo "=== Checking dist contents ===" ls -la vsix-build/dist/ echo "=== Verifying required files ===" test -f vsix-build/package.json || (echo "Missing package.json" && exit 1) test -f vsix-build/dist/extension.js || (echo "Missing extension.js" && exit 1) echo "=== Checking package.json content ===" cat vsix-build/package.json | jq '.name, .version, .publisher' - name: Create VSIX Package working-directory: apps/extension/vsix-build run: pnpm exec vsce package --no-dependencies env: FORCE_COLOR: 1 - name: Get VSIX filename id: vsix-info working-directory: apps/extension/vsix-build run: | VSIX_FILE=$(ls *.vsix) echo "vsix-filename=$VSIX_FILE" >> $GITHUB_OUTPUT echo "Found VSIX: $VSIX_FILE" - name: Validate VSIX Package working-directory: apps/extension/vsix-build run: | echo "=== VSIX Package Contents ===" unzip -l "${{ steps.vsix-info.outputs.vsix-filename }}" - name: Publish to VS Code Marketplace working-directory: apps/extension/vsix-build run: pnpm exec vsce publish --packagePath "${{ steps.vsix-info.outputs.vsix-filename }}" env: VSCE_PAT: ${{ secrets.VSCE_PAT }} FORCE_COLOR: 1 - name: Install Open VSX CLI run: npm install -g ovsx - name: Publish to Open VSX Registry working-directory: apps/extension/vsix-build run: ovsx publish "${{ steps.vsix-info.outputs.vsix-filename }}" env: OVSX_PAT: ${{ secrets.OVSX_PAT }} FORCE_COLOR: 1 - name: Create GitHub Release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: extension-v${{ needs.check-version.outputs.current-version }} release_name: Extension v${{ needs.check-version.outputs.current-version }} body: | VS Code Extension Release v${{ needs.check-version.outputs.current-version }} **Changes in this release:** - Published to VS Code Marketplace - Published to Open VSX Registry - Extension package: `${{ steps.vsix-info.outputs.vsix-filename }}` **Installation:** - Install from VS Code Marketplace: [Task Master Kanban](https://marketplace.visualstudio.com/items?itemName=[TBD]) - Install from Open VSX Registry: [Task Master Kanban](https://open-vsx.org/extension/[TBD]) - Or download the VSIX file below and install manually draft: false prerelease: false - name: Upload VSIX to Release uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: apps/extension/vsix-build/${{ steps.vsix-info.outputs.vsix-filename }} asset_name: ${{ steps.vsix-info.outputs.vsix-filename }} asset_content_type: application/zip - name: Upload Build Artifacts uses: actions/upload-artifact@v4 with: name: extension-release-v${{ needs.check-version.outputs.current-version }} path: | apps/extension/vsix-build/*.vsix apps/extension/dist/ retention-days: 90 notify-success: needs: [check-version, build-and-publish] if: success() && needs.check-version.outputs.should-publish == 'true' runs-on: ubuntu-latest steps: - name: Success Notification run: | echo "🎉 Extension v${{ needs.check-version.outputs.current-version }} successfully published!" echo "đŸ“Ļ Available on VS Code Marketplace" echo "🌍 Available on Open VSX Registry" echo "đŸˇī¸ GitHub release created: extension-v${{ needs.check-version.outputs.current-version }}" notify-skipped: needs: check-version if: needs.check-version.outputs.should-publish == 'false' runs-on: ubuntu-latest steps: - name: Skip Notification run: | echo "â„šī¸ Extension publish skipped - no version changes detected" echo "Current version: ${{ needs.check-version.outputs.current-version }}" echo "To force publish, use workflow_dispatch with force_publish=true"