Publish Nexpath VS Code Extension #2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Publish Nexpath VS Code Extension | |
| # Manual trigger (workflow_dispatch) AND automatic trigger on tag push. | |
| # The build step always runs on every supported OS; the publish step only | |
| # runs when triggered with publish=true OR by a tag matching vsix-v*. | |
| # | |
| # Required repository secrets for publishing: | |
| # VSCE_PAT — Azure DevOps Personal Access Token (Marketplace: Manage) | |
| # OVSX_PAT — Open VSX namespace access token | |
| # | |
| # Both should be created via Settings → Secrets and variables → Actions. | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| publish: | |
| description: "Publish to marketplaces (false = artefacts only)" | |
| type: boolean | |
| required: true | |
| default: false | |
| push: | |
| tags: | |
| - "vsix-v*" | |
| jobs: | |
| # ────────────────────────────────────────────────────────────────────────── | |
| # Matrix: build one .vsix per supported (os, arch) pair. | |
| # better-sqlite3 ships per-platform prebuilds; each runner naturally has | |
| # the right binary in node_modules after `npm install`. | |
| # ────────────────────────────────────────────────────────────────────────── | |
| package: | |
| name: Package (${{ matrix.target }}) | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # Pin every runner to a specific version so the matrix is reproducible | |
| # across runs; otherwise GitHub's `*-latest` labels drift to new minor | |
| # versions without warning (and our better-sqlite3 prebuilds are | |
| # node-abi keyed, which can desync with the runner's default node). | |
| - target: linux-x64 | |
| runner: ubuntu-22.04 | |
| - target: darwin-x64 | |
| runner: macos-13 # Intel mac for x64 prebuild | |
| - target: darwin-arm64 | |
| runner: macos-14 # Apple Silicon (pinned; previously macos-latest) | |
| - target: win32-x64 | |
| runner: windows-2022 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "20" | |
| cache: "npm" | |
| cache-dependency-path: src/ext-vscode/package-lock.json | |
| - name: Install sub-package deps | |
| working-directory: src/ext-vscode | |
| run: npm ci | |
| - name: Typecheck | |
| working-directory: src/ext-vscode | |
| run: npx tsc --noEmit | |
| - name: Unit tests | |
| # Run on Linux + both macOS jobs. Skipped ONLY on win32: a set of host-path | |
| # tests (host-detector / cursor-state-dump-helpers / advisory-store-reader / | |
| # path-enumerator / resolve-db-workspace) assert POSIX '/' separators and rely | |
| # on POSIX realpath semantics, so they false-fail on the Windows runner | |
| # (path.join uses the host separator; Windows uses 8.3 short names like | |
| # RUNNER~1). They validate platform-agnostic LOGIC and pass on Linux + macOS. | |
| # The win32 job still typechecks, builds, and packages the native binary — | |
| # which is the OS-specific part — validated separately by the build + manual | |
| # cross-OS install testing. | |
| if: matrix.target != 'win32-x64' | |
| working-directory: src/ext-vscode | |
| run: npm test | |
| - name: Build esbuild bundle | |
| working-directory: src/ext-vscode | |
| run: npm run build | |
| - name: Package .vsix (with better-sqlite3 rebuilt for Cursor's Electron ABI) | |
| working-directory: src/ext-vscode | |
| run: | | |
| mkdir -p dist-vsix | |
| # package-with-electron-abi.mjs rebuilds better-sqlite3 against the | |
| # Electron version pinned in package.json#nexpathTargets.electron, | |
| # runs vsce package, then restores the Node-ABI binary. Skipping | |
| # this wrapper would ship a Node-ABI binding in the .vsix and Cursor | |
| # would fail to activate with NODE_MODULE_VERSION mismatch. | |
| node scripts/package-with-electron-abi.mjs --target ${{ matrix.target }} --out dist-vsix/ | |
| - name: Upload .vsix artefact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: vsix-${{ matrix.target }} | |
| path: src/ext-vscode/dist-vsix/*.vsix | |
| if-no-files-found: error | |
| retention-days: 30 | |
| # Linux ARM64 builds via QEMU emulation — separate job because the | |
| # ubuntu-latest runner is x64. Slower, but the prebuilt better-sqlite3 | |
| # is available on npm for linux-arm64. | |
| package-linux-arm64: | |
| name: Package (linux-arm64) | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| with: | |
| platforms: arm64 | |
| - name: Build + package inside arm64 container | |
| run: | | |
| docker run --rm --platform linux/arm64 \ | |
| -v "${{ github.workspace }}":/work -w /work/src/ext-vscode \ | |
| node:20-bullseye bash -lc " | |
| npm ci && | |
| npx tsc --noEmit && | |
| npm test && | |
| npm run build && | |
| mkdir -p dist-vsix && | |
| node scripts/package-with-electron-abi.mjs --target linux-arm64 --out dist-vsix/ | |
| " | |
| - name: Upload .vsix artefact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: vsix-linux-arm64 | |
| path: src/ext-vscode/dist-vsix/*.vsix | |
| if-no-files-found: error | |
| retention-days: 30 | |
| # ────────────────────────────────────────────────────────────────────────── | |
| # Publish — only runs on tag push or when manually triggered with publish=true. | |
| # Pulls every matrix .vsix as an artefact, then loops them through vsce + ovsx. | |
| # ────────────────────────────────────────────────────────────────────────── | |
| publish: | |
| name: Publish to marketplaces | |
| needs: [package, package-linux-arm64] | |
| if: ${{ github.event_name == 'push' || inputs.publish == true }} | |
| runs-on: ubuntu-22.04 | |
| # PATs are lifted to job level so the per-step `if: env.* != ''` guards can | |
| # actually see them — a step's OWN step-level env is NOT in scope for that | |
| # step's `if`, so guarding on a step-defined env silently skips the step. | |
| env: | |
| VSCE_PAT: ${{ secrets.VSCE_PAT }} | |
| OVSX_PAT: ${{ secrets.OVSX_PAT }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "20" | |
| cache: "npm" | |
| cache-dependency-path: src/ext-vscode/package-lock.json | |
| - name: Install sub-package deps (for vsce + ovsx) | |
| working-directory: src/ext-vscode | |
| run: npm ci | |
| - name: Download all .vsix artefacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: vsix-* | |
| path: dist-vsix-all | |
| merge-multiple: true | |
| - name: List downloaded .vsix files | |
| run: ls -la dist-vsix-all/ | |
| - name: Publish to VS Code Marketplace (vsce) | |
| if: ${{ env.VSCE_PAT != '' }} | |
| working-directory: src/ext-vscode | |
| run: | | |
| for vsix in ../../dist-vsix-all/*.vsix ; do | |
| echo "Publishing $vsix to VS Code Marketplace..." | |
| npx vsce publish --packagePath "$vsix" | |
| done | |
| - name: Publish to Open VSX (ovsx) | |
| if: ${{ env.OVSX_PAT != '' }} | |
| working-directory: src/ext-vscode | |
| run: | | |
| for vsix in ../../dist-vsix-all/*.vsix ; do | |
| echo "Publishing $vsix to Open VSX..." | |
| npx ovsx publish "$vsix" | |
| done | |
| - name: Sanity-check publication | |
| run: | | |
| echo "If the steps above succeeded:" | |
| echo " - https://marketplace.visualstudio.com/items?itemName=nexpath.nexpath-vscode" | |
| echo " - https://open-vsx.org/extension/nexpath/nexpath-vscode" | |
| echo "" | |
| echo "Note: marketplace ingestion may lag a few minutes after publish." |