Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 3 additions & 13 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
# The bun setup and the dependency install of every repo-owned workflow job; the caller keeps its own checkout and
# setup-node, whose options differ per job.
# install -> --ignore-scripts: scripts.prepare installs lefthook, a git hook no runner uses; "false" (any letter
# case, as GitHub compares) skips the install for a job that runs a bare script or resolves the lockfile itself
# yamllint -> "true" installs the pinned yamllint behind `bun run lint:yaml`, which fails a CI run where it is missing
# install -> --ignore-scripts: scripts.prepare installs lefthook, a git hook no runner uses; "false" (any letter
# case, as GitHub compares) skips the install for a job that runs a bare script or resolves the lockfile itself
name: Set up bun
description: The pinned bun, the locked dependencies unless told not to, and yamllint for the jobs that lint YAML
description: The pinned bun, and the locked dependencies unless told not to

inputs:
install:
description: '"false" sets up bun alone; anything else runs bun install --frozen-lockfile --ignore-scripts'
default: "true"
yamllint:
description: '"true" installs the pinned yamllint for lint:yaml'
default: "false"

runs:
using: composite
Expand All @@ -24,9 +20,3 @@ runs:
if: inputs.install != 'false'
shell: bash
run: bun install --frozen-lockfile --ignore-scripts
# pipx ships on the ubuntu runner image with its bin directory on PATH; a venv of its own leaves the runner's
# python untouched.
- name: Install yamllint
if: inputs.yamllint == 'true'
shell: bash
run: pipx install yamllint==1.38.0
4 changes: 2 additions & 2 deletions .github/repo-platform-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
".github/copilot-instructions.md": {"class": "mirror", "kind": "symlink", "hash": "79909577a70fc4971a7fcfd3cbec6a1af7182ca2dadc87f2979dce5e28f93ca0"},
".github/dependabot.yml": {"class": "managed", "hash": "a9e955fa9fd485a2d4cd9c86113252a6176d841223e6846c3f091c4317675223"},
".github/instructions/review.instructions.md": {"class": "managed", "hash": "89d5c9bc2bea185a076b37a4cefb5ffea25a37f050c4e39512b875b95e2db380"},
".github/repo-platform-manifest.json": {"class": "managed", "hash": null, "commit": "5c9df351f3ee2a145d49f62481f3687d49caec47"},
".github/repo-platform-manifest.json": {"class": "managed", "hash": null, "commit": "c81f6ac157538498b02b50ee37846e4656f6a578"},
".github/settings.local.yml": {"class": "starter"},
".github/settings.yml": {"class": "managed", "hash": "4f32ad98113f837b6ba7723973a6f534af7239a092fa2faab56b41b034a9c96d"},
".github/settings.yml": {"class": "managed", "hash": "9a128071b1207cccdd42bb5731afbe5e7bf7aac12ad76293f27939fa571e5445"},
".github/workflows/auto-assign.yml": {"class": "managed", "hash": "bd512e0e114675a95f42468802fc9e8bb118215f38ed7c7b70d4235a88592f54"},
".github/workflows/auto-format.yml": {"class": "starter"},
".github/workflows/checks.yml": {"class": "starter"},
Expand Down
7 changes: 0 additions & 7 deletions .github/settings.local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,6 @@ repository:
topics: github-action, repository-settings, settings-as-code, configuration-as-code, probot-settings, rulesets, branch-protection, labels
private: false

labels:
# e2e-nightly.yml files its tracking issue under this label, so it must
# survive the label sync.
- name: e2e-fuzz
color: "B60205"
description: Automated e2e nightly failure

rulesets:
# NARROWS the release-please module's release-tags ruleset: the fleet
# declares it over `v*`, which would also freeze the moving major tag
Expand Down
3 changes: 0 additions & 3 deletions .github/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@ labels:
- name: docs-link-rot
color: D4A72C
description: Automated docs-site link-rot report
- name: e2e-fuzz
color: B60205
description: Automated e2e nightly failure
- name: enhancement
color: a2eeef
description: New feature or request
Expand Down
6 changes: 0 additions & 6 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,15 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup
with:
yamllint: "true"
# bun test loads the fetched, gitignored OpenAPI spec and GraphQL
# schema; the composite restores each from cache or fetches on a miss.
- uses: ./.github/actions/fetch-test-artifacts
- name: Lint (biome)
run: bun run lint
- name: Lint (yaml)
run: bun run lint:yaml
- name: Lint (architecture)
run: bun run lint:arch
- name: Typecheck
run: bun run typecheck
- name: Dead code (knip)
run: bun run knip
- name: Compat markers
run: bun run check:compat
- name: Test
Expand Down
91 changes: 0 additions & 91 deletions .github/workflows/e2e-nightly.yml

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/nightly-fuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
schedule:
# Off-peak, off the top of the hour, and distinct from the fleet's other
# nightlies (chromium-bridge 47 4, litellm-vscode-chat 59 7, this repo's
# e2e-nightly 28 10).
# nightly.yml 47 2).
- cron: "41 5 * * *"
workflow_dispatch:
inputs:
Expand Down Expand Up @@ -59,7 +59,7 @@ jobs:

# The trimmed OpenAPI spec is a fetched, gitignored artifact the mock
# validates responses against. Always fetched fresh (no cache), same as
# e2e-nightly: the fetch doubles as an upstream-drift tripwire.
# nightly.yml's e2e job: the fetch doubles as an upstream-drift tripwire.
- name: Fetch the trimmed OpenAPI spec
run: bun .github/scripts/trim-openapi.ts

Expand Down
58 changes: 43 additions & 15 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# Nightly upstream-freshness probes. Generated from the fleet sync's nightly
# starter and never overwritten by a later sync. The checks job re-cuts the
# trimmed OpenAPI spec from upstream HEAD (a path-level staleness check) and
# typechecks against the latest @octokit/types, so pinned-dependency staleness
# fails a night instead of surprising the next manual bump; the float-canary
# job re-resolves the lockfile from scratch the way the Dependabot lockfile
# workflow does, so a breaking upstream release fails a night instead of
# reddening every open Dependabot PR; the report job below files or updates
# one label-deduplicated tracking issue on a red night and closes it on a
# green one (see the platform repository's docs/nightly.md).
# Nightly upstream-freshness probes and the whole-corpus e2e run. Generated
# from the fleet sync's nightly starter and never overwritten by a later
# sync. The checks job re-cuts the trimmed OpenAPI spec from upstream HEAD
# (a path-level staleness check) and typechecks against the latest
# @octokit/types, so pinned-dependency staleness fails a night instead of
# surprising the next manual bump; the float-canary job re-resolves the
# lockfile from scratch the way the Dependabot lockfile workflow does, so a
# breaking upstream release fails a night instead of reddening every open
# Dependabot PR; the e2e job runs the curated corpus and the endpoint-coverage
# tripwire against a freshly fetched spec; the report job below files or
# updates one label-deduplicated tracking issue on a red night and closes it
# on a green one (see the platform repository's docs/nightly.md).
name: Nightly

on:
Expand Down Expand Up @@ -110,11 +112,10 @@ jobs:
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# The gate below runs lint:yaml; the from-scratch resolve is this job's install.
# The from-scratch resolve is this job's install.
- uses: ./.github/actions/setup
with:
install: "false"
yamllint: "true"
# Delete before resolving, exactly like the Dependabot workflow: bun
# keeps a stale lockfile as a valid resolution, and only a
# from-scratch resolve floats what that workflow would float.
Expand All @@ -130,11 +131,38 @@ jobs:
- name: Run the gate on the floated resolution
run: bun run check

# The whole curated corpus (PR CI runs only the sections a PR changed) plus the endpoint-coverage tripwire,
# against the pinned spec fetched fresh: PR CI restores a cached spec for speed, so this fetch is where a used
# path GitHub stopped documenting surfaces. The bundle runs under node24, so node is installed beside bun.
e2e:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24
- name: Fetch the trimmed OpenAPI spec (drift tripwire)
run: bun .github/scripts/trim-openapi.ts
- name: Curated corpus
run: bun test/e2e/run.ts
- name: Endpoint-coverage tripwire
run: bun .github/scripts/check-endpoint-coverage.ts
# The tracking issue points at the run; the failing scenarios' reports and request logs are here.
- name: Upload failure artifacts
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-artifacts-${{ github.run_attempt }}
path: test/e2e/.artifacts/
if-no-files-found: ignore

# Runs whatever happened to the probe jobs, and treats a CANCELLED probe
# as red: a job that hits its timeout is cancelled, not failed, and a
# hang is exactly what a nightly run exists to catch.
report:
needs: [checks, float-canary]
needs: [checks, float-canary, e2e]
if: always()
runs-on: ubuntu-latest
# A few gh calls behind a bun setup; a hung reporter is the residual
Expand All @@ -148,7 +176,7 @@ jobs:
steps:
- name: File or update the nightly issue
id: file-issue
if: needs.checks.result != 'success' || needs.float-canary.result != 'success'
if: needs.checks.result != 'success' || needs.float-canary.result != 'success' || needs.e2e.result != 'success'
uses: Vivswan/repo-platform/actions/fuzz-issue@stable
# This job checks nothing out (kept tight), so gh has no git
# context; GH_REPO points it at this repository (run 31563375394
Expand Down Expand Up @@ -178,7 +206,7 @@ jobs:
run: gh workflow run auto-assign.yml -f "issue=$ISSUE_NUMBER" || echo "::warning::could not dispatch auto-assign.yml"

- name: Close the nightly issue on a green night
if: needs.checks.result == 'success' && needs.float-canary.result == 'success'
if: needs.checks.result == 'success' && needs.float-canary.result == 'success' && needs.e2e.result == 'success'
uses: Vivswan/repo-platform/actions/fuzz-issue@stable
env:
GH_REPO: ${{ github.repository }}
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ The end-to-end tests build the bundle to a temp path and run it as a subprocess
- Every section ships the standard scenario set under `src/sections/<key>/scenarios/`, named after the section's dashed key: `<slug>-apply-converges`, `<slug>-check-drift` (a section with a planning read), `<slug>-snapshot-roundtrip` (a section with snapshot()), and for a section under the undeclared policy `<slug>-undeclared-delete` and `<slug>-undeclared-keep-note`; `test/sections/scenario-set.test.ts` derives the set from the registry.
- `bun run fuzz` runs seeded property fuzzing: random scenarios, each checked against an oracle that predicts the outcome class from the token mask, policy, and mode.
- The mock serves the section endpoints plus the core routes the action calls outside the sections. A request that matches no registered route fails loudly; the mock never invents a response.
- PR CI runs the sections a pull request changed. Two nightly workflows run the full corpus and the full fuzz, filing issues labeled `e2e-fuzz` and `fuzz-nightly` that carry a replay command.
- PR CI runs the sections a pull request changed. The nightly workflow's `e2e` job runs the full corpus and files a red night under the `nightly-failure` issue; the fuzz nightly runs the full fuzz and files under `fuzz-nightly` with a replay command.

The fuzzer is deterministic. It prints a master seed and a per-iteration seed:

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@
"access": "public"
},
"scripts": {
"check": "bun run lint && bun run lint:yaml && bun run lint:arch && bun run check:compat && bun run typecheck && bun run knip && bun run test && bun run build:check",
"check": "bun run lint && bun run lint:arch && bun run check:compat && bun run typecheck && bun run test && bun run build:check",
"check:compat": "bun .github/scripts/check-compat-markers.ts",
"lint": "bun x biome ci --error-on-warnings .",
"lint:yaml": "if command -v yamllint >/dev/null 2>&1; then git ls-files -z '*.yml' '*.yaml' | xargs -0 yamllint -s; elif [ -n \"$CI\" ]; then echo 'lint:yaml: yamllint is missing on this runner; the job needs ./.github/actions/setup with yamllint: \"true\"' >&2; exit 1; else echo 'lint:yaml: yamllint not installed, skipping (CI runs it; install with pip install yamllint or brew install yamllint)'; fi",
"lint:yaml": "git ls-files -z '*.yml' '*.yaml' | xargs -0 yamllint -s",
"lint:fix": "bun x biome check --write .",
"lint:arch": "bun .github/scripts/arch-lint.ts",
"lint:package": "bun x publint --strict && bun x attw --pack . --profile esm-only",
Expand Down
Loading
Loading