Skip to content

build(deps): bump the actions group with 3 updates #162

build(deps): bump the actions group with 3 updates

build(deps): bump the actions group with 3 updates #162

Workflow file for this run

# Identical in every *-le repo. The artifact name is derived from the repo
# rather than hardcoded, so this file is byte-for-byte the same everywhere and
# a change can be copied across without a per-repo edit.
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
# Least privilege: CI reads the repo and nothing else.
permissions:
contents: read
# A newer push supersedes an in-flight run instead of both burning a 3-OS matrix.
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# A prose commit cannot behave differently on Windows, so repeating the whole
# matrix for one is three runners answering a question with one answer. This
# narrows the matrix rather than skipping anything: on a docs-only push every
# check still runs, once, on the leg that carries the checks the other two do
# not — the README coverage gate, the integration suite and the installed
# VSIX end-to-end are all Linux-only already.
#
# "Docs" is deliberately narrow: `*.md` and `LICENSE`, nothing else.
# Anything unrecognised counts as code, and an unreadable diff counts as
# code — the default is always to run more, never less.
#
# Note what this is NOT: `GEMINI.md` is documentation by that rule and is
# also read by `src/agent-files.test.ts`. That is fine precisely because
# nothing is skipped. `.cursorrules` and the other non-`.md` mirrors count
# as code and widen the matrix; a `.md` one narrows it, and the suite that
# covers it still runs on the leg that remains.
changes:
name: What changed
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
code: ${{ steps.classify.outputs.code }}
matrix: ${{ steps.classify.outputs.matrix }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- id: classify
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "pull_request" ]; then
range="origin/${{ github.base_ref }}...HEAD"
else
before="${{ github.event.before }}"
if [ -z "$before" ] || [ "$before" = "0000000000000000000000000000000000000000" ]; then
before="$(git rev-list --max-parents=0 HEAD | tail -1)"
fi
range="$before..HEAD"
fi
# An unreadable range is not evidence of a docs-only push. Fall back
# to the full matrix rather than quietly checking less.
if ! files="$(git diff --name-only "$range")"; then files=""; fi
code=false
if [ -z "$files" ]; then code=true; fi
while IFS= read -r file; do
[ -z "$file" ] && continue
case "$file" in
*.md | LICENSE) ;;
*) code=true; break ;;
esac
done <<EOF
$files
EOF
if [ "$code" = "true" ]; then
echo 'matrix=["ubuntu-latest","macos-latest","windows-latest"]' >> "$GITHUB_OUTPUT"
else
echo 'matrix=["ubuntu-latest"]' >> "$GITHUB_OUTPUT"
fi
echo "code=$code" >> "$GITHUB_OUTPUT"
echo "code=$code, files changed:"
echo "$files"
commits:
name: Commit messages
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
# The full history of the pushed range, so every new subject is checked
# rather than only the tip.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
# The local commit-msg hook is skippable with --no-verify; this is not.
- name: Validate conventional commits
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
RANGE="origin/${{ github.base_ref }}..HEAD"
else
RANGE="${{ github.event.before }}..${{ github.sha }}"
fi
node scripts/commit-lint.js --range "$RANGE"
ci:
name: CI on ${{ matrix.os }}
needs: changes
runs-on: ${{ matrix.os }}
# Integration tests drive a real extension host; without a cap a hung
# vscode-test sits for the 6h runner default.
timeout-minutes: 20
strategy:
matrix:
os: ${{ fromJSON(needs.changes.outputs.matrix) }}
fail-fast: false
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.13
- name: Install dependencies
run: bun install --frozen-lockfile
# PR-only: shows what a dependency change actually pulls in, and fails on
# a known-vulnerable addition — before Dependabot's auto-merge can act.
- name: Dependency review
if: github.event_name == 'pull_request' && runner.os == 'Linux'
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
with:
fail-on-severity: high
- name: Lint
run: bun run lint
- name: Typecheck
run: bun run typecheck
- name: Unit tests with coverage
run: bun run test:coverage
# The README's Testing section is generated from the coverage summary.
# Failing here means the committed numbers no longer match a real run —
# which is exactly how the pre-2.0 READMEs drifted into fiction.
- name: README coverage section is current
if: runner.os == 'Linux'
run: bun run coverage:readme:check
- name: Build bundle
run: bun run build
- name: Bundle gate
run: bun run check:bundle
- name: Package VSIX
run: bun run package
- name: Integration tests (Linux)
if: runner.os == 'Linux'
run: xvfb-run -a bun run test:integration
- name: Integration tests (macOS/Windows)
if: runner.os != 'Linux'
run: bun run test:integration
# The only test that exercises the artifact users actually install.
# Linux only: it drives a second VS Code instance and needs xvfb.
- name: Installed-VSIX end-to-end (Linux)
if: runner.os == 'Linux'
run: xvfb-run -a bun run test:e2e-vsix
- name: Upload VSIX artifact
if: runner.os == 'Linux'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ github.event.repository.name }}-vsix
path: release/*.vsix
if-no-files-found: error
retention-days: 14
# The Zed extension is a separate toolchain and would otherwise only break at
# submission time, days after the change that broke it. It is a thin launcher
# for the same npm package, so building it is the whole check — there is no
# extraction logic in the crate to test.
zed:
name: Zed extension
needs: changes
# A wasm build and a version-agreement check over package.json, server.json
# and the Zed manifests. Every input is a code file, so a docs-only push
# cannot move it.
if: needs.changes.outputs.code == 'true'
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# Ubuntu runners ship a Rust toolchain; adding an action to install one
# would be a new dependency for a target this already has.
- name: Add the wasm target
run: rustup target add wasm32-wasip2
- name: Build
working-directory: zed
run: cargo build --release --target wasm32-wasip2 --locked
- name: Clippy
working-directory: zed
run: rustup component add clippy && cargo clippy --release --target wasm32-wasip2 --locked -- -D warnings
- name: Formatting
working-directory: zed
run: cargo fmt --check
# One version across five files, and the registry identity across two more.
# build-npm.js writes most of these, but only when it is run — CI is where
# a hand-edit that skipped it gets caught.
- name: Versions and registry identity agree
run: |
extension_version=$(node -p "require('./package.json').version")
zed_version=$(grep -m1 '^version' zed/extension.toml | cut -d'"' -f2)
crate_version=$(grep -m1 '^version' zed/Cargo.toml | cut -d'"' -f2)
npm_version=$(node -p "require('./mcp/package.json').version")
npm_name=$(node -p "require('./mcp/package.json').name")
mcp_name=$(node -p "require('./mcp/package.json').mcpName || ''")
registry_name=$(node -p "require('./server.json').name")
registry_version=$(node -p "require('./server.json').version")
registry_identifier=$(node -p "require('./server.json').packages[0].identifier")
registry_pkg_version=$(node -p "require('./server.json').packages[0].version")
fail=0
for pair in \
"zed/extension.toml:$zed_version" \
"zed/Cargo.toml:$crate_version" \
"mcp/package.json:$npm_version" \
"server.json:$registry_version" \
"server.json packages[0]:$registry_pkg_version"; do
file=${pair%:*}
value=${pair##*:}
if [ "$value" != "$extension_version" ]; then
echo "::error::$file is $value, package.json is $extension_version"
fail=1
fi
done
# The registry verifies ownership by reading mcpName out of the
# PUBLISHED package, so a mismatch is only discoverable after the
# version is spent and can never be republished.
if [ -z "$mcp_name" ]; then
echo "::error::mcp/package.json has no mcpName"
fail=1
fi
if [ "$registry_name" != "$mcp_name" ]; then
echo "::error::server.json is $registry_name, mcpName is $mcp_name"
fail=1
fi
if [ "$registry_identifier" != "$npm_name" ]; then
echo "::error::server.json publishes $registry_identifier, expected $npm_name"
fail=1
fi
if ! grep -q "\"$npm_name\"" zed/src/lib.rs; then
echo "::error::zed/src/lib.rs does not install $npm_name"
fail=1
fi
exit $fail