Skip to content

release: 6.0.3-bridge.15.tsgo.7.0.2 #279

release: 6.0.3-bridge.15.tsgo.7.0.2

release: 6.0.3-bridge.15.tsgo.7.0.2 #279

Workflow file for this run

name: ci
on:
push:
branches: [master]
pull_request:
permissions:
contents: read
env:
VOLAR_BRANCH: master
VOLAR_SHA: fc9b2d67cfb569d267d81061b643ee55d4b4c38e # vuejs/language-tools@master
BASELINE: test/baselines/nav-results-8c26673-t1.json # sim-nav baseline gate (same as nightly)
jobs:
prepare:
runs-on: macos-latest
timeout-minutes: 5
outputs:
matrix: ${{ steps.groups.outputs.matrix }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
# tools/ci-witness-groups.mjs is the single source of truth for the
# witness matrix — it validates the table (dupes, missing scripts,
# count) on every run, so a bad edit fails here before six jobs spawn.
- id: groups
run: echo "matrix=$(node tools/ci-witness-groups.mjs matrix)" >> "$GITHUB_OUTPUT"
build:
runs-on: macos-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Submodule SHAs
id: sub-sha
# The nested typescript-go/_submodules/TypeScript pin is a function of
# the typescript-go gitlink, so two SHAs key all three checkouts.
run: echo "sha=$(git ls-tree HEAD typescript typescript-go | awk '{print $3}' | paste -sd- -)" >> "$GITHUB_OUTPUT"
- name: Restore submodules (cache)
id: sub-cache
uses: actions/cache/restore@v4
with:
path: |
typescript
typescript-go
.git/modules
key: submodules-v1-${{ steps.sub-sha.outputs.sha }}
- name: Fetch submodules
if: steps.sub-cache.outputs.cache-hit != 'true'
run: git submodule update --init --force --recursive --depth 1
# The save runs before patch/npm-ci/build steps touch the worktrees, so
# the cached entry is always the pristine pinned tree. Keep this block
# in sync with the vet job's (GitHub Actions has no step reuse).
- name: Save submodules (cache)
if: steps.sub-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
typescript
typescript-go
.git/modules
key: submodules-v1-${{ steps.sub-sha.outputs.sha }}
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
cache-dependency-path: |
package-lock.json
typescript/package-lock.json
typescript-go/package-lock.json
- uses: actions/setup-go@v5
with:
go-version: "1.26" # typescript-go/go.mod
cache-dependency-path: typescript-go/go.sum
- name: Install dependencies
run: npm ci
- name: Install typescript submodule dependencies
run: npm ci
working-directory: typescript
- name: Install typescript-go submodule dependencies
run: npm ci
working-directory: typescript-go
- name: Build js (tsgo native-preview -> vendor)
run: npm run build:js
- name: Build lib (patched TypeScript fork)
run: npm run build:lib
- name: Build bridge (cgo dylib)
run: npm run build:bridge
- name: Gates
run: |
npm run check:lib
npm run check:enums
# V8-sandbox failure class: the bridge's binary path must work under
# Electron (VS Code's tsserver host) — invisible to every Node-only gate
# (2026-07-20 incident). The probe spawns itself under Electron and
# round-trips callBinary payloads.
- name: Electron sandbox ABI probe
run: |
npm i --no-save electron@42
node tools/triage-electron-abi.mjs
# This job is the only place the volar cache is populated: downstream
# jobs (volar-test, witnesses, sim-nav-shard) restore it with
# fail-on-cache-miss, and their needs: build guarantees this job's
# post-job save has landed. The tree is BUILT (install + pnpm run build,
# same as nightly) — the sim-nav shards need the compiled plugin; v4
# splits off stale install-only v2 entries so a shard never restores an
# unbuilt tree.
- name: Clone volar (cache)
id: volar-cache
uses: actions/cache@v4
with:
path: |
${{ runner.temp }}/volar
${{ runner.temp }}/volar-stock
key: volar-${{ env.VOLAR_SHA }}-v4
- name: Clone volar
if: steps.volar-cache.outputs.cache-hit != 'true'
run: |
git clone --depth 50 --branch "$VOLAR_BRANCH" https://github.com/vuejs/language-tools.git "$RUNNER_TEMP/volar"
git -C "$RUNNER_TEMP/volar" checkout "$VOLAR_SHA" 2>/dev/null || {
git -C "$RUNNER_TEMP/volar" fetch --deepen 50 origin "$VOLAR_BRANCH"
git -C "$RUNNER_TEMP/volar" checkout "$VOLAR_SHA"
}
# Point volar's typescript override at the CI-built TNB — volar
# master's override is `npm:typescript-native-bridge@<release>`, which
# would fetch the released package instead of the commit under test.
cd "$RUNNER_TEMP/volar"
node -e "const fs=require('fs');const p='pnpm-workspace.yaml';let s=fs.readFileSync(p,'utf8');s=s.replace(/typescript: npm:typescript-native-bridge@.*/,'typescript: link:'+process.env.GITHUB_WORKSPACE);fs.writeFileSync(p,s);console.log(s.match(/overrides:[\s\S]*/)[0])"
- name: Install + build volar
if: steps.volar-cache.outputs.cache-hit != 'true'
run: |
cd "$RUNNER_TEMP/volar"
corepack enable
pnpm install --no-frozen-lockfile
pnpm run build
- name: Pack stock typescript
if: steps.volar-cache.outputs.cache-hit != 'true'
run: |
mkdir "$RUNNER_TEMP/volar-stock"
cd "$RUNNER_TEMP/volar-stock"
npm pack typescript@6.0.3 --silent
tar -xzf typescript-6.0.3.tgz
- name: sourcefile-guard
env:
VOLAR_ROOT: ${{ runner.temp }}/volar
run: npm run check:sourcefile-guard
- name: Upload built outputs
uses: actions/upload-artifact@v4
with:
name: built-outputs
path: |
lib/
native/
vendor/
# lib/.gitattributes is hidden; v4.4+ skips hidden files by default.
include-hidden-files: true
retention-days: 1
- name: Cleanup harness processes
if: always()
run: node tools/kill-leaked-harness.mjs || true
vet:
runs-on: macos-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Submodule SHAs
id: sub-sha
# The nested typescript-go/_submodules/TypeScript pin is a function of
# the typescript-go gitlink, so two SHAs key all three checkouts.
run: echo "sha=$(git ls-tree HEAD typescript typescript-go | awk '{print $3}' | paste -sd- -)" >> "$GITHUB_OUTPUT"
- name: Restore submodules (cache)
id: sub-cache
uses: actions/cache/restore@v4
with:
path: |
typescript
typescript-go
.git/modules
key: submodules-v1-${{ steps.sub-sha.outputs.sha }}
- name: Fetch submodules
if: steps.sub-cache.outputs.cache-hit != 'true'
run: git submodule update --init --force --recursive --depth 1
# The save runs before patch steps touch the worktree, so the cached
# entry is always the pristine pinned tree. Keep this block in sync
# with the build job's (GitHub Actions has no step reuse).
- name: Save submodules (cache)
if: steps.sub-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
typescript
typescript-go
.git/modules
key: submodules-v1-${{ steps.sub-sha.outputs.sha }}
- uses: actions/setup-node@v4
with:
node-version: 24
- uses: actions/setup-go@v5
with:
go-version: "1.26" # typescript-go/go.mod
cache-dependency-path: typescript-go/go.sum
- name: Patch tsgo
run: npm run patch:tsgo
- name: go vet
# Scoped to packages TNB patches touch — vetting all of typescript-go
# (plus every test file) costs ~6min/run; upstream code is not our
# surface. Keep in sync with patches/typescript-go/.
run: go vet ./internal/api/... ./internal/ls/... ./internal/checker/... ./internal/compiler/... ./internal/bundled/... ./internal/project/... ./internal/module/...
working-directory: typescript-go
volar-test:
needs: build
runs-on: macos-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci
- name: Download built outputs
uses: actions/download-artifact@v4
with:
name: built-outputs
path: .
- name: Restore volar (cache)
uses: actions/cache/restore@v4
with:
path: |
${{ runner.temp }}/volar
${{ runner.temp }}/volar-stock
key: volar-${{ env.VOLAR_SHA }}-v4
fail-on-cache-miss: true
# Runs on every CI run: the cached node_modules links
# typescript -> $GITHUB_WORKSPACE, i.e. the commit under test.
- name: Test volar
run: |
# Volar's tsserver harness resolves typescript/lib/tsserver via a
# fresh module lookup from dirname(realpath(typescript/package.json)).
# With the link: override that realpath is this repo, so `typescript`
# must resolve from here too — self-link it (TNB has no typescript
# dependency of its own; node_modules is CI-local state).
# node_modules may not exist at all: the root package has no
# dependencies, and unlike the old single job this job never installs
# Electron. Create it before self-linking.
mkdir -p "$GITHUB_WORKSPACE/node_modules"
ln -sfn "$GITHUB_WORKSPACE" "$GITHUB_WORKSPACE/node_modules/typescript"
cd "$RUNNER_TEMP/volar"
npm test
- name: Cleanup harness processes
if: always()
run: node tools/kill-leaked-harness.mjs || true
witnesses:
needs: [prepare, build]
runs-on: macos-latest
timeout-minutes: 15
strategy:
# One group's failure must not cancel the others — every commit keeps
# full witness coverage in a single run.
fail-fast: false
matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }}
name: witnesses (wg${{ matrix.index }})
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- uses: actions/setup-node@v4
with:
node-version: 24
- name: Download built outputs
uses: actions/download-artifact@v4
with:
name: built-outputs
path: .
- name: Restore volar (cache)
uses: actions/cache/restore@v4
with:
path: |
${{ runner.temp }}/volar
${{ runner.temp }}/volar-stock
key: volar-${{ env.VOLAR_SHA }}-v4
fail-on-cache-miss: true
- name: sweep-ls-throws
if: matrix.sweep
env:
VOLAR_ROOT: ${{ runner.temp }}/volar
run: |
# Runs before this group's witnesses: it regenerates
# /tmp/tnb-sweep-fixtures that triage-quickinfo-emptyparity and
# triage-refs-exportspec read. /tmp is per-runner, so the three must
# share one job — ci-witness-groups.mjs flags this group via sweep.
set -o pipefail
TNB_TRACE_THROW=1 TNB_TRACE_THROW_FILE=/tmp/tnb-throw-ci.jsonl \
node tools/sweep-ls-throws.mjs 2>&1 | tee /tmp/tnb-sweep-ci.log
grep -q "correlated throw hits: 0" /tmp/tnb-sweep-ci.log \
|| { echo "sweep correlated hits != 0"; exit 1; }
- name: Regression witnesses
env:
VOLAR_ROOT: ${{ runner.temp }}/volar
STOCK_TSSERVER_PATH: ${{ runner.temp }}/volar-stock/package/lib/tsserver.js
WITNESSES: ${{ matrix.witnesses }}
run: |
# Isolated tools copy: the harness lock lives at
# <toolsDir>/../.tnb-harness.lock, and this group's witnesses run
# sequentially under one lock. vendor/ lib/ native/ are symlinked
# into the copy for tools that boot the bridge in-process (they
# resolve the repo from import.meta.dirname/..); README.md +
# patches/ too — the ledger gate reads them for the patch<->README
# reconciliation; bin/ too — triage-nuxtui-exportstar shells out to
# repoRoot/bin/tsc. pipefail is set explicitly so the tee below does
# not mask a group failure (the step shell's -eo pipefail default
# must not be load-bearing).
i=${{ matrix.index }}
set -o pipefail
rm -rf "/tmp/tnb-wg$i"
mkdir -p "/tmp/tnb-wg$i"
cp -R tools "/tmp/tnb-wg$i/tools"
ln -sfn "$GITHUB_WORKSPACE/vendor" "/tmp/tnb-wg$i/vendor"
ln -sfn "$GITHUB_WORKSPACE/lib" "/tmp/tnb-wg$i/lib"
ln -sfn "$GITHUB_WORKSPACE/native" "/tmp/tnb-wg$i/native"
ln -sfn "$GITHUB_WORKSPACE/README.md" "/tmp/tnb-wg$i/README.md"
ln -sfn "$GITHUB_WORKSPACE/patches" "/tmp/tnb-wg$i/patches"
ln -sfn "$GITHUB_WORKSPACE/bin" "/tmp/tnb-wg$i/bin"
rc=0
{
failed=()
for w in $WITNESSES; do
echo "=== [wg$i] $w ==="
(cd "/tmp/tnb-wg$i/tools" && node "$w.mjs") || failed+=("$w")
done
if ((${#failed[@]})); then
echo "WG$i FAILURES (${#failed[@]}): ${failed[*]}"
exit 1
fi
} 2>&1 | tee "/tmp/tnb-wg$i.log" || rc=$?
if ((rc)); then
# On failure, surface diff lines with their stock/tnb context —
# the streamed log can be thousands of lines, and a bare tail can
# land on a KNOWN-exemption pair and hide the real failure keys
# (run 30062511367 misread this way).
echo "=== witness group $i (failure lines) ==="
grep -E -A2 "^DIFF |^FAIL |VERDICT: FAIL|FAILURES \(|verdict=DIFF" "/tmp/tnb-wg$i.log" || true
fi
exit $rc
- name: Upload witness log on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: witness-log-wg${{ matrix.index }}
path: |
/tmp/tnb-wg${{ matrix.index }}.log
/tmp/tnb-sweep-ci.log
retention-days: 30
- name: Cleanup harness processes
if: always()
run: node tools/kill-leaked-harness.mjs || true
# sim-nav mirrors nightly's shard mechanism (nightly.yml sim-nav-shard +
# merge): same 4-shard matrix, merge, and --baseline gate, so PR CI, nightly
# and local `npm run check:sim-nav` all run the same full pipeline. No
# SIM_NAV_SKIP_CLASSIFY here — the classify replay runs, isomorphic with the
# local full gate.
sim-nav-shard:
needs: build
runs-on: macos-latest
timeout-minutes: 30
strategy:
# One shard's failure must not cancel the others.
fail-fast: false
matrix:
index: [0, 1, 2, 3]
name: sim-nav (shard ${{ matrix.index }})
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- uses: actions/setup-node@v4
with:
node-version: 24
- name: Download built outputs
uses: actions/download-artifact@v4
with:
name: built-outputs
path: .
- name: Restore volar (cache)
uses: actions/cache/restore@v4
with:
path: |
${{ runner.temp }}/volar
${{ runner.temp }}/volar-stock
key: volar-${{ env.VOLAR_SHA }}-v4
fail-on-cache-miss: true
- name: Run sim-nav shard
env:
VOLAR_ROOT: ${{ runner.temp }}/volar
STOCK_TSSERVER_PATH: ${{ runner.temp }}/volar-stock/package/lib/tsserver.js
SIM_NAV_BASELINE: ${{ github.workspace }}/${{ env.BASELINE }}
run: |
set -u
# Isolated tools copy, same shape as the old single-job shards: the
# harness lock lives at <toolsDir>/../.tnb-harness.lock — one shard
# per runner now, but the shard script still expects to run from a
# tools copy it owns.
i=${{ matrix.index }}
rm -rf "/tmp/tnb-shard$i"
mkdir -p "/tmp/tnb-shard$i"
cp -R tools "/tmp/tnb-shard$i/tools"
rc=0
(cd "/tmp/tnb-shard$i/tools" && \
SIM_NAV_SHARD_INDEX=$i SIM_NAV_SHARD_COUNT=4 \
SIM_NAV_OUT_JSON="/tmp/tnb-sim-nav-shard$i.json" \
SIM_NAV_THROW_FILE="/tmp/tnb-sim-nav-shard$i.throws.jsonl" \
node triage-sim-nav-shard.mjs > "/tmp/tnb-sim-nav-shard$i.log" 2>&1) || rc=$?
echo "=== shard $i (tail) ==="
tail -5 "/tmp/tnb-sim-nav-shard$i.log" || true
exit $rc
- name: Upload shard result
uses: actions/upload-artifact@v4
with:
name: sim-nav-shard-json-${{ matrix.index }}
path: /tmp/tnb-sim-nav-shard${{ matrix.index }}.json
retention-days: 1
- name: Upload shard logs on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: sim-nav-shard-logs-${{ matrix.index }}
path: |
/tmp/tnb-sim-nav-shard${{ matrix.index }}.log
/tmp/tnb-sim-nav-shard${{ matrix.index }}.throws.jsonl
retention-days: 30
- name: Cleanup harness processes
if: always()
run: node tools/kill-leaked-harness.mjs || true
merge:
needs: sim-nav-shard
runs-on: macos-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- uses: actions/setup-node@v4
with:
node-version: 24
- name: Download shard results
uses: actions/download-artifact@v4
with:
pattern: sim-nav-shard-json-*
path: /tmp/tnb-shards
merge-multiple: true
- name: Merge shard results
run: node tools/sim-nav-merge.mjs --out /tmp/tnb-sim-nav-merged.json /tmp/tnb-shards/tnb-sim-nav-shard0.json /tmp/tnb-shards/tnb-sim-nav-shard1.json /tmp/tnb-shards/tnb-sim-nav-shard2.json /tmp/tnb-shards/tnb-sim-nav-shard3.json
- name: Check against baseline
run: node tools/sim-nav-merge.mjs --baseline "$BASELINE" /tmp/tnb-sim-nav-merged.json
- name: Upload sim-nav results
if: always()
uses: actions/upload-artifact@v4
with:
name: sim-nav-results
path: /tmp/tnb-sim-nav-merged.json
retention-days: 30