From eeac2aa0f94f852fd8f906c9e9748510a2f08dba Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Sat, 8 Aug 2026 11:50:44 -0500 Subject: [PATCH] test(DEN-2278): certify VS Code inspect v1 interoperability Pin the exact current inspect CLI candidate and VS Code adapter, build and test both products, and require real CLI JSON to flow through the adapter without mutating a pending-transaction fixture or weakening action risk metadata. --- .../workflows/vscode-inspect-v1-interop.yml | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 .github/workflows/vscode-inspect-v1-interop.yml diff --git a/.github/workflows/vscode-inspect-v1-interop.yml b/.github/workflows/vscode-inspect-v1-interop.yml new file mode 100644 index 00000000..2fb34aa8 --- /dev/null +++ b/.github/workflows/vscode-inspect-v1-interop.yml @@ -0,0 +1,155 @@ +name: VS Code inspect v1 interop + +on: + pull_request: + paths: + - ".github/workflows/vscode-inspect-v1-interop.yml" + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: vscode-inspect-v1-${{ github.event.pull_request.number || github.ref || github.run_id }} + cancel-in-progress: true + +env: + ZED_CLI_REF: b7036935ce3711563f1527472fc64e92bc1341aa + ZED_VSCODE_REF: c30cfe8c483ba8ae45c18abbf714f858f7f4d419 + +jobs: + interop: + runs-on: ubuntu-24.04 + timeout-minutes: 40 + defaults: + run: + shell: bash + steps: + - name: Validate exact product pins + run: | + set -euo pipefail + [[ "$ZED_CLI_REF" =~ ^[0-9a-f]{40}$ ]] + [[ "$ZED_VSCODE_REF" =~ ^[0-9a-f]{40}$ ]] + + - name: Check out exact zed-cli candidate + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: zed-pkg/zed-cli + ref: ${{ env.ZED_CLI_REF }} + path: zed-cli + fetch-depth: 1 + persist-credentials: false + show-progress: false + + - name: Check out exact VS Code adapter candidate + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: zed-pkg/zed-vscode + ref: ${{ env.ZED_VSCODE_REF }} + path: zed-vscode + fetch-depth: 1 + persist-credentials: false + show-progress: false + + - name: Install declared Rust toolchain + run: | + set -euo pipefail + rustup toolchain install stable --profile minimal + rustup default stable + + - name: Build exact CLI candidate + run: | + set -euo pipefail + test "$(git -C zed-cli rev-parse HEAD)" = "$ZED_CLI_REF" + cargo build --locked --release --manifest-path zed-cli/Cargo.toml --bin zed + + - name: Set up Node.js 22 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: '22' + cache: npm + cache-dependency-path: zed-vscode/package-lock.json + + - name: Run exact VS Code adapter unit tests + working-directory: zed-vscode + run: | + set -euo pipefail + test "$(git rev-parse HEAD)" = "$ZED_VSCODE_REF" + npm ci --ignore-scripts --no-audit --no-fund + npm test + + - name: Exercise real CLI JSON through real VS Code adapter + env: + ZED_BINARY: ${{ github.workspace }}/zed-cli/target/release/zed + run: | + set -euo pipefail + node <<'NODE' + 'use strict'; + const assert = require('node:assert/strict'); + const crypto = require('node:crypto'); + const fs = require('node:fs'); + const os = require('node:os'); + const path = require('node:path'); + const {inspectRoot} = require('./zed-vscode/src/inspector'); + + function snapshot(root) { + const rows = []; + function walk(directory) { + for (const name of fs.readdirSync(directory).sort()) { + const absolute = path.join(directory, name); + const relative = path.relative(root, absolute); + const stat = fs.lstatSync(absolute); + if (stat.isDirectory()) { + rows.push([relative, 'dir']); + walk(absolute); + } else if (stat.isSymbolicLink()) { + rows.push([relative, 'symlink', fs.readlinkSync(absolute)]); + } else { + rows.push([relative, 'file', crypto.createHash('sha256').update(fs.readFileSync(absolute)).digest('hex')]); + } + } + } + walk(root); + return rows; + } + + (async () => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'zed-vscode-inspect-v1-')); + fs.writeFileSync(path.join(root, '.zpkg.toml'), '[package]\norg = "acme"\nname = "widget"\nversion = "1.0.0"\n\n[package.repository]\nvcs = "git"\nurl = "https://example.invalid/acme/widget"\n'); + fs.writeFileSync(path.join(root, '.zpkg.lock'), 'version = 1\n'); + fs.mkdirSync(path.join(root, '.zpkg-staging')); + fs.writeFileSync(path.join(root, '.zpkg-staging', 'sentinel'), 'must-survive'); + const before = snapshot(root); + + const report = await inspectRoot(root, { + executable: process.env.ZED_BINARY, + timeoutMs: 10000, + }); + + assert.equal(report.source, 'cli', JSON.stringify(report)); + assert.equal(path.resolve(report.workspaceRoot), path.resolve(root)); + const recovery = report.issues.find((issue) => issue.id === 'RECOVERY_PENDING'); + assert.ok(recovery, JSON.stringify(report)); + assert.equal(recovery.severity, 'warning'); + assert.equal(recovery.actions.length, 1); + assert.deepEqual(recovery.actions[0], { + id: 'recover-frozen', + title: 'Recover with the locked graph', + kind: 'command', + command: 'zed', + arguments: ['install', '--frozen'], + requiresConfirmation: true, + workingDirectory: fs.realpathSync.native(root), + mutatesProject: true, + requiresNetwork: true, + executesPackageCode: true, + }); + assert.deepEqual(snapshot(root), before); + assert.equal(fs.readFileSync(path.join(root, '.zpkg-staging', 'sentinel'), 'utf8'), 'must-survive'); + assert.equal(fs.existsSync(path.join(root, 'zed_modules')), false); + console.log(`certified cli=${process.env.ZED_CLI_REF} vscode=${process.env.ZED_VSCODE_REF}`); + })().catch((error) => { + console.error(error); + process.exitCode = 1; + }); + NODE