# Workflow that validates the VSCode extension builds correctly name: VSCode Extension CI # * Always run on "main" # * Run on PRs that have changes in the VSCode extension folder or this workflow # * Run on tags that start with "ext-v" on: push: branches: - main tags: - 'ext-v*' pull_request: paths: - 'openhands/integrations/vscode/**' - 'build_vscode.py' - '.github/workflows/vscode-extension-build.yml' # If triggered by a PR, it will be in the same group. However, each commit on main will be in its own unique group concurrency: group: ${{ github.workflow }}-${{ (github.head_ref && github.ref) || github.run_id }} cancel-in-progress: true jobs: # Validate VSCode extension builds correctly validate-vscode-extension: name: Validate VSCode Extension Build runs-on: blacksmith-4vcpu-ubuntu-2204 steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Node.js uses: useblacksmith/setup-node@v5 with: node-version: '22' - name: Set up Python uses: actions/setup-python@v6 with: python-version: '3.12' - name: Install VSCode extension dependencies working-directory: ./openhands/integrations/vscode run: npm ci - name: Build VSCode extension via build_vscode.py run: python build_vscode.py env: # Ensure we don't skip the build SKIP_VSCODE_BUILD: "" - name: Validate .vsix file run: | # Verify the .vsix was created and is valid if [ -f "openhands/integrations/vscode/openhands-vscode-0.0.1.vsix" ]; then echo "✅ VSCode extension built successfully" ls -la openhands/integrations/vscode/openhands-vscode-0.0.1.vsix # Basic validation that the .vsix is a valid zip file echo "🔍 Validating .vsix structure..." file openhands/integrations/vscode/openhands-vscode-0.0.1.vsix unzip -t openhands/integrations/vscode/openhands-vscode-0.0.1.vsix echo "✅ VSCode extension validation passed" else echo "❌ VSCode extension build failed - .vsix not found" exit 1 fi - name: Upload VSCode extension artifact uses: actions/upload-artifact@v6 with: name: vscode-extension path: openhands/integrations/vscode/openhands-vscode-0.0.1.vsix retention-days: 7 - name: Comment on PR with artifact link if: github.event_name == 'pull_request' uses: actions/github-script@v7 with: script: | const fs = require('fs'); const path = require('path'); // Get file size for display const vsixPath = 'openhands/integrations/vscode/openhands-vscode-0.0.1.vsix'; const stats = fs.statSync(vsixPath); const fileSizeKB = Math.round(stats.size / 1024); const comment = `## 🔧 VSCode Extension Built Successfully! The VSCode extension has been built and is ready for testing. **📦 Download**: [openhands-vscode-0.0.1.vsix](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) (${fileSizeKB} KB) **🚀 To install**: 1. Download the artifact from the workflow run above 2. In VSCode: \`Ctrl+Shift+P\` → "Extensions: Install from VSIX..." 3. Select the downloaded \`.vsix\` file **✅ Tested with**: Node.js 22 **🔍 Validation**: File structure and integrity verified --- *Built from commit ${{ github.sha }}*`; // Check if we already commented on this PR and delete it const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, }); const botComment = comments.find(comment => comment.user.login === 'github-actions[bot]' && comment.body.includes('VSCode Extension Built Successfully') ); if (botComment) { await github.rest.issues.deleteComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: botComment.id, }); } // Create a new comment await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body: comment }); release: name: Create GitHub Release runs-on: blacksmith-4vcpu-ubuntu-2204 needs: validate-vscode-extension if: startsWith(github.ref, 'refs/tags/ext-v') steps: - name: Download .vsix artifact uses: actions/download-artifact@v6 with: name: vscode-extension path: ./ - name: Create Release uses: ncipollo/release-action@v1.20.0 with: artifacts: "*.vsix" token: ${{ secrets.GITHUB_TOKEN }} draft: true allowUpdates: true