Repository navigation
fix(web): require an available machine for SSH terminals #1639
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: Lint | |
| on: | |
| pull_request: | |
| push: | |
| branches: | |
| - main | |
| permissions: | |
| contents: read | |
| # A superseded push must not keep CI busy: pushing three times to a PR used to | |
| # queue three full sets of jobs, all but the last of them already irrelevant. | |
| # release.yml deliberately does the OPPOSITE (`cancel-in-progress: false`) — | |
| # cancelling a release mid-flight leaves a tag without a release — but CI has | |
| # nothing to protect. | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| lint: | |
| name: Linting | |
| # Bare on the runner rather than in the builder image: this job needs only | |
| # bun (via setup-bun below) and node, and a container would buy nothing — | |
| # nothing root-owns the workspace, so there is nothing to un-root. | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Use Bun | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 | |
| with: | |
| bun-version: 1.4.0 | |
| # tsdown/rolldown run under NODE, not bun — their bin shebang is | |
| # `#!/usr/bin/env node` — so the repo has always had a Node requirement | |
| # it never declared, and CI silently inherited whatever the host had. | |
| # the fleet once shipped node 18.19 while ubuntu-latest shipped 20+; rolldown needs | |
| # `styleText` from `node:util` (20.12+), so the build broke on the move. | |
| # | |
| # Pinned to the `engines.node` the root package.json now declares, NOT | |
| # to rolldown's floor. A hosted runner image ships a node and floats it | |
| # with each image refresh; the pinned version is the contract, so it | |
| # comes from the workflow rather than from the image. | |
| - name: Use Node | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: 24 | |
| - name: Cache Bun install | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }} | |
| restore-keys: ${{ runner.os }}-bun- | |
| - name: Cache Turbo | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| # Turbo v2's local cache is .turbo/cache at the repo root | |
| # (measured 2026-09-22 against turbo 2.10.11); the v1 path this | |
| # previously named is never written, so the cache restored nothing. | |
| path: .turbo | |
| key: ${{ runner.os }}-turbo-${{ github.sha }} | |
| restore-keys: ${{ runner.os }}-turbo- | |
| - name: Install Dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Build workspace packages | |
| run: bun run build | |
| - name: Run package checking | |
| run: bun run lint:packages | |
| # Bun records a version for each workspace in bun.lock and never resyncs | |
| # it, and `--frozen-lockfile` exits 0 when it is stale — so the release | |
| # flow silently drifted the lockfile a whole version behind before | |
| # anyone noticed. This is the only check that sees it. | |
| - name: Check the lockfile's workspace versions | |
| run: bun run lint:lockfile | |
| # Subshell is dual-licensed by path (apps/server/** is AGPL, the rest is | |
| # Apache). A new or moved package declaring the wrong `license` — or none | |
| # at all — is not a type error, a lint error or a test failure. This is | |
| # the only thing that sees it. | |
| - name: Check the per-path licence declarations | |
| run: bun run lint:licenses | |
| # The design system (docs/design-system.md): one type/colour vocabulary | |
| # across four surfaces, asserted from the token files. A stray | |
| # `text-[13px]`, `font-size: 14.5px` or `fontSize: 17` is not a type, | |
| # lint or test failure — this is the only thing that sees it. | |
| - name: Check the design tokens | |
| run: bun run lint:design | |
| # The voice rule (operator ruling 2026-09-25): no em dashes in authored | |
| # prose. The docs site enforces this through its content test; this is | |
| # the twin for the rest of the repository's prose (AGENTS.md files, | |
| # docs/, rules, READMEs, pending changesets). A dash is not a type, lint | |
| # or test failure, so this is the only thing that sees it. | |
| - name: Check the prose (no em dashes) | |
| run: bun run lint:prose | |
| - name: Run type checking | |
| run: bun run verify-types | |
| # Read-only: `lint` writes fixes and would pass on unformatted code. | |
| - name: Run linting | |
| run: bun run lint:check | |
| - name: "shellcheck (Proxmox helpers, image entrypoint, docker scenario)" | |
| run: | | |
| sudo apt-get update -q | |
| sudo apt-get install -y -q shellcheck | |
| shellcheck -S warning proxmox-server.sh proxmox-node.sh docker-entrypoint.sh scripts/cli-e2e/docker-image.sh | |
| # Dependency advisories, gated. `bun audit` on its own is informational: it | |
| # prints advisories and would have left this file green through every one of | |
| # them. dep-audit requires the live advisory set to be a subset of | |
| # scripts/dep-audit.ignore.json, so a NEW advisory fails the job naming its | |
| # GHSA id, and an allowlisted entry that has since been fixed warns, which is | |
| # what keeps the file recording reasons rather than history. A separate job | |
| # rather than a step: the audit is a statement about the lockfile, and it | |
| # fails for reasons no amount of linting fixes. | |
| dep-audit: | |
| name: Dependency audit | |
| # Bare like the lint job above: bun and the lockfile are the whole input. | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Use Bun | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 | |
| with: | |
| bun-version: 1.4.0 | |
| - name: Cache Bun install | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }} | |
| restore-keys: ${{ runner.os }}-bun- | |
| - name: Install Dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Audit dependencies | |
| run: bun run audit:deps | |
| # The website's install column reads the root releases.json, and release.yml | |
| # regenerates it after every cut. If that job's commit step ever breaks, | |
| # main moves on with a stale manifest: drift is a CI failure, not a | |
| # visitor's problem (spec 2026-09-23 §5). Bare on the runner like the Lint | |
| # job above for the same reason: bun and the checkout are the whole need. | |
| site-manifest-fresh: | |
| name: releases.json matches the tags | |
| # Push-only: tags land at cut START, PRs must not go red for a cut in flight; drift is caught "on the next push". | |
| if: github.event_name == 'push' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Use Bun | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 | |
| with: | |
| bun-version: 1.4.0 | |
| - name: Install Dependencies | |
| run: bun install --frozen-lockfile | |
| # ls-remote goes to the remote by protocol, so no fetch-depth: 0 here: | |
| # the checkout supplies the script and the committed file it compares | |
| # against, nothing more. | |
| - name: Check | |
| run: bun scripts/site-releases.ts --check |