mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
d07b837621
Every declared AgentDeviceRunnerUITests method now belongs to a lane, and the #if guard is the classification: AGENT_DEVICE_RUNNER_UNIT_TESTS alone means a pure runner decision (runs on the macOS host on every PR — ci.yml's existing compile job now executes the bundle it builds), '&& os(iOS)' means runner/XCTest semantics (simulator lanes only). check:xctest-selection evaluates the guards per platform, derives each lane's reach, and fails on a flagged identifier that is undeclared or uncompiled on that lane, on a declared test no lane reaches (found the two tvOS-only tests, dark since birth — widened to os(tvOS) || os(macOS)), and on testCommand reaching any lane. The host and nightly lanes assert executed == derived reach, so a missing -D flag or a guard that compiles a file out reads red, not as a smaller green. One duplicate test deleted (sparse-verdict assertions folded into its twin).
564 lines
23 KiB
YAML
564 lines
23 KiB
YAML
name: CI
|
|
|
|
on:
|
|
pull_request:
|
|
paths-ignore:
|
|
- 'docs/**'
|
|
- 'website/**'
|
|
- 'README.md'
|
|
- 'AGENTS.md'
|
|
- 'CHANGELOG.md'
|
|
- 'CONTEXT.md'
|
|
- 'CONTRIBUTING.md'
|
|
- 'LICENSE'
|
|
- 'SECURITY.md'
|
|
- '.github/actions/build-docs/action.yml'
|
|
- '.github/workflows/deploy.yml'
|
|
- '.github/workflows/pr-preview.yml'
|
|
- '.github/workflows/pr-preview-cleanup.yml'
|
|
push:
|
|
branches:
|
|
- main
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
# Two single-`rg`-assertion jobs (formerly `ios-runner-swift-compat`,
|
|
# `no-test-di-seams`, added independently in b79bd8601 / 9eb060406) folded
|
|
# into steps here: each was checkout + one grep, paying full job
|
|
# scheduling/checkout overhead and its own PR status-check line for what is
|
|
# a single assertion. Each step keeps its own failure message. See #1462.
|
|
static-checks:
|
|
name: Static Checks
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- name: Disallow trailing commas before closing parenthesis in Swift
|
|
run: |
|
|
if rg -nU --glob '*.swift' ',\s*\n\s*\)' apple/runner; then
|
|
echo "Found trailing commas before ')' in Swift files. This syntax requires Swift 6.1+ and breaks older Xcode toolchains."
|
|
exit 1
|
|
fi
|
|
|
|
- name: Fail if test-only DI seams reappear in production code
|
|
run: |
|
|
if rg '\?\s*:\s*typeof\s+' src/ --glob '!**/__tests__/**' --glob '!*.test.ts'; then
|
|
echo "Found test-only DI seams (optional typeof params) in production code."
|
|
exit 1
|
|
fi
|
|
|
|
# The runner's pure-decision XCTests, on the macOS host with no simulator (#1781 A7). This
|
|
# job already compiled the macOS runner with the unit-test flag on every PR (as "Swift
|
|
# Runner Unit Compile") and threw the bundle away; running it costs one
|
|
# `test-without-building` on the host. Which tests that reaches is not a list: it is
|
|
# everything the macOS build compiles, and the simulator-only tests keep themselves out
|
|
# with an `os(iOS)` guard (see the classification note in RunnerTests.swift). The
|
|
# `-skip-testing:` entry is validated by `pnpm check:xctest-selection` for the same
|
|
# reason the nightly's is: `RunnerTests/testCommand` is the runner's 24-hour server
|
|
# entry point, and a typo re-arms the hang. The lane's reporter asserts the executed
|
|
# count equals the reach the check derives from source, so a build without the compile
|
|
# flag or a guard that compiles a file out reads as red rather than as a smaller green.
|
|
#
|
|
# - Catches: regressions in the ~130 host-runnable tests on every PR, in about a
|
|
# minute, independent of ios.yml — which is fifteen minutes long, cancelled ~19% of
|
|
# the time, and names only a subset of them.
|
|
# - Evidence: the nightly's first execution found #1812 in exactly this class of test
|
|
# (a geometry guard); the same tests pass on this lane's platform.
|
|
# - Cost: ~1 minute more on a job that already occupies a macOS slot for the build;
|
|
# no simulator boot; no new job.
|
|
# - Kill criterion: if the host run proves flaky where the simulator run of the same
|
|
# tests is not (a platform-branch difference this classification missed), gate the
|
|
# offender `os(iOS)` and it returns to the simulator lanes; if that happens to more
|
|
# than a handful, the host lane is the wrong tool and goes.
|
|
swift-runner-host-tests:
|
|
name: Swift Runner Host XCTests
|
|
runs-on: macos-26
|
|
timeout-minutes: 20
|
|
# Was an inline `VAR=1 pnpm gate …` prefix on the action's build-command input. The
|
|
# input is a gate id now, so the variable lives where ios.yml already puts it: the job.
|
|
env:
|
|
AGENT_DEVICE_XCUITEST_INCLUDE_UNIT_TESTS: '1'
|
|
AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH: ${{ github.workspace }}/.tmp/swift-runner-unit-derived
|
|
RESULT_BUNDLE_PATH: ${{ github.workspace }}/.tmp/xctest-host/RunnerTests.xcresult
|
|
RESULT_SUMMARY_PATH: ${{ github.workspace }}/.tmp/xctest-host/test-results-summary.json
|
|
XCTEST_LANE: host
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
- name: Restore and compile Swift runner unit-test surface
|
|
uses: ./.github/actions/setup-apple-runner-build
|
|
with:
|
|
derived-path: ${{ env.AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH }}
|
|
cache-key-prefix: swift-runner-unit
|
|
gate: swift-runner-macos
|
|
xcuitest-platform: macos
|
|
xcuitest-destination: platform=macOS,arch=arm64
|
|
|
|
- name: Run the host-runnable runner XCTests
|
|
run: |
|
|
set -euo pipefail
|
|
XCTESTRUN_PATH="$(find "$AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH/Build/Products" -maxdepth 1 -name '*.xctestrun' -print -quit)"
|
|
test -n "$XCTESTRUN_PATH"
|
|
mkdir -p "$(dirname "$RESULT_BUNDLE_PATH")"
|
|
xcodebuild test-without-building \
|
|
-xctestrun "$XCTESTRUN_PATH" \
|
|
-destination 'platform=macOS,arch=arm64' \
|
|
-skip-testing:AgentDeviceRunnerUITests/RunnerTests/testCommand \
|
|
-resultBundlePath "$RESULT_BUNDLE_PATH"
|
|
|
|
# Same shape as xctest-nightly.yml: extract is best-effort, the report step asserts.
|
|
- name: Extract the test-results summary
|
|
if: always()
|
|
run: |
|
|
set -uo pipefail
|
|
[ -d "$RESULT_BUNDLE_PATH" ] || exit 0
|
|
xcrun xcresulttool get test-results summary --path "$RESULT_BUNDLE_PATH" --compact \
|
|
> "$RESULT_SUMMARY_PATH" 2>/dev/null ||
|
|
xcrun xcresulttool get test-results summary --path "$RESULT_BUNDLE_PATH" \
|
|
> "$RESULT_SUMMARY_PATH" 2>/dev/null ||
|
|
rm -f "$RESULT_SUMMARY_PATH"
|
|
exit 0
|
|
|
|
- name: Report the run and assert it executed the source-derived set
|
|
if: always()
|
|
run: |
|
|
set -euo pipefail
|
|
if [ ! -s "$RESULT_SUMMARY_PATH" ]; then
|
|
echo 'No usable test-results summary was produced, so nothing here can show a test ran.'
|
|
echo 'The suite step above failed before or during the run; read its log first.'
|
|
echo '### iOS runner host XCTest lane' >> "$GITHUB_STEP_SUMMARY"
|
|
echo 'No result-bundle summary; see the run log and the uploaded bundle.' >> "$GITHUB_STEP_SUMMARY"
|
|
exit 1
|
|
fi
|
|
node --experimental-strip-types scripts/xctest-run-summary.ts
|
|
|
|
- name: Upload result bundle
|
|
if: always()
|
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
with:
|
|
name: xctest-host-results-${{ github.run_id }}-${{ github.run_attempt }}
|
|
path: .tmp/xctest-host
|
|
if-no-files-found: warn
|
|
|
|
lint:
|
|
name: Lint & Format
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
- name: Run oxlint
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: lint }
|
|
|
|
- name: Check formatting
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: format }
|
|
|
|
layering-guard:
|
|
name: Layering Guard
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
# This job used to run with install-deps: false. It opted out when R7
|
|
# (SessionState ownership) started parsing the daemon with `oxc-parser` instead
|
|
# of matching assignment operators with a regex: a regex cannot see `??=` or a
|
|
# computed `session[key] =` write, so the choice was a real parser or a rule with
|
|
# holes in it. It was the last such job, so R8 zero-dep-job-closure retired for
|
|
# want of subjects (#1781 A6). Keep install-deps enabled.
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
- name: Check import-direction DAG
|
|
# Generalizes the former inline commands/-import grep into a structured
|
|
# import-direction lint over the resolved graph. See scripts/layering/check.ts
|
|
# and CONTEXT.md (Architecture: folder DAG + layering lint).
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: layering }
|
|
|
|
- name: Check the depgraph report agrees with the gate
|
|
# scripts/depgraph reads the same model as the gate, so its inversion count must
|
|
# reproduce TYPE_INVERSION_BASELINE. Free two-sources check: if the tree changes
|
|
# and only one side is updated, this fails and names the difference. Runs here
|
|
# rather than in its own job so the two can never be green independently.
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: depgraph }
|
|
|
|
# Tests for the TMPDIR redirection itself, hidden the same way as the check above.
|
|
#
|
|
# Deliberately NOT in Coverage next to `check:tmpdir-leaks`, where the subject matter
|
|
# would put it: vitest-tmpdir-global-setup.test.ts proves the lifecycle by spawning a
|
|
# real nested `vitest run`, and the Coverage lane already loses runs to
|
|
# `[vitest-pool]: Worker forks emitted error` when a fork is slow to terminate.
|
|
# Starting a nested Vitest seconds before the full instrumented suite is a contention
|
|
# risk with nothing to gain.
|
|
- name: Check the tmpdir redirection model
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: tmpdir-leaks-model }
|
|
|
|
affected-selector:
|
|
name: Affected-check Selector
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
# The selector's entry closure reaches `@agent-device/kernel` workspace
|
|
# specifiers through src/utils/exec.ts and diagnostics.ts (#1490 W0), and
|
|
# workspace package resolution needs the pnpm link in node_modules. R11
|
|
# grants no relative route into a package, so this job installs
|
|
# dependencies instead.
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
# The selector is fail-open and advisory (GitHub CI stays authoritative),
|
|
# so the gate only guards the derivation model.
|
|
- name: Check affected-selector model
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: affected-selector }
|
|
|
|
# The gate-of-gates (#1429). It shares this job because it validates the
|
|
# same artifact the selector is built on — CHECK_CATALOG's `ciJobs` — and
|
|
# because a gate that proves the other gates are wired must not be the one
|
|
# gate sitting in its own job, green on its own. Deterministic and
|
|
# network-free: every input is a file in the checkout.
|
|
- name: Check the gate manifest model
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: gate-manifest-model }
|
|
|
|
- name: Check every gate is owned, wired, and reachable
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: gate-manifest }
|
|
|
|
# Same family as the manifest above — a CI selection that has stopped selecting what
|
|
# it claims. ios.yml runs a hand-written subset of the runner XCTest methods through an
|
|
# `-only-testing:` list, and xcodebuild treats an identifier that matches nothing as
|
|
# an empty selection rather than an error, so a rename drops a test with no signal —
|
|
# in both directions, since a typo in xctest-nightly.yml's `-skip-testing:` entry
|
|
# re-arms a 24-hour hang. Parse-only, no Xcode (#1781 A7).
|
|
- name: Check the PR XCTest selection still names real tests
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: xctest-selection }
|
|
|
|
maestro-conformance:
|
|
name: Maestro Conformance Oracle
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
# Unlike the layering/affected guards, this job DOES install deps: the
|
|
# verifier parses corpus flows with the live engine, and the Maestro parser
|
|
# imports the `yaml` package. Keep install-deps enabled.
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
# Layers 1-2 of the conformance oracle: replay the JVM-generated fixtures
|
|
# against the live engine. Deterministic and Java-free — the generated
|
|
# fixtures are checked in and only regenerated on an upstream-pin bump. The
|
|
# device-backed layer 3 runs on the scheduled conformance-differential
|
|
# workflow. See scripts/maestro-conformance/README.md.
|
|
- name: Verify Maestro conformance fixtures
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: maestro-conformance }
|
|
|
|
packaged-cli-node-22-12:
|
|
name: Packaged CLI Node 22.12
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 15
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- name: Setup build toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
- name: Build CLI
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: build }
|
|
|
|
- name: Verify emitted chunk ownership
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: bundle-owner-files }
|
|
|
|
# The build runs on the default toolchain Node and the package is verified on the minimum
|
|
# supported Node, so this job covers what a user on `engines.node` floor actually installs.
|
|
- name: Setup Node.js 22.12
|
|
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
|
with:
|
|
node-version: '22.12'
|
|
|
|
# Packs, lints the tarball with publint/attw, installs it outside the workspace, and imports
|
|
# every published entry point before running the CLI. See scripts/check-package.ts.
|
|
#
|
|
# Runs the script directly rather than through `pnpm check:package`: the repo's pinned pnpm
|
|
# requires Node >= 22.13 and refuses to start on the 22.12 floor this job exists to cover. The
|
|
# gate itself only needs `node` and `npm`, so it is the package.json script minus the launcher.
|
|
- name: Verify the published package on Node.js 22.12
|
|
run: node --experimental-strip-types scripts/check-package.ts
|
|
|
|
fallow:
|
|
name: Fallow Code Quality
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
- name: Run Fallow audit
|
|
env:
|
|
FALLOW_BASE: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
|
|
uses: ./.github/actions/run-gate
|
|
with:
|
|
gate: fallow
|
|
args: |
|
|
--base
|
|
${{ env.FALLOW_BASE }}
|
|
|
|
- name: Check for production-unused exports
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: production-exports }
|
|
|
|
replay-compat-provenance:
|
|
# The frozen replay-compat corpus (#1417) claims each entry was published by
|
|
# a released tag. Only a full-history checkout can re-derive that claim, so
|
|
# this job exists separately from the shallow-clone-safe unit lane.
|
|
name: Replay-Compat Provenance
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
fetch-depth: 0
|
|
fetch-tags: true
|
|
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
- name: Verify corpus entries against their released blobs
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: replay-compat }
|
|
|
|
released-surface-compat:
|
|
# The daemon RPC wire ledger (#1432) is compared against the ledger as it
|
|
# stood at the last RELEASED tag, which only a full-history checkout can
|
|
# read. Same split as the replay-compat corpus above: the shallow unit lane
|
|
# holds the ledger to its source, this job holds it to the last release.
|
|
name: Released-Surface Compatibility
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
fetch-depth: 0
|
|
fetch-tags: true
|
|
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
- name: Verify the wire-compat rules
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: wire-compat-model }
|
|
|
|
- name: Compare the daemon RPC wire surface against the last released tag
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: daemon-wire-compat }
|
|
|
|
coverage:
|
|
# Runs the full unit + provider-integration suites under coverage with
|
|
# thresholds, so a separate unit-tests job would rerun the same tests.
|
|
name: Coverage
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
- name: Test changed-line coverage gate
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: coverage-model }
|
|
|
|
- name: Run coverage
|
|
id: run-coverage
|
|
env:
|
|
OUTPUT_ECONOMY_BASE: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: unit-ci }
|
|
# The TMPDIR redirection both test lanes depend on (#1593/#1595). The check is a real
|
|
# package script that no workflow ran: it is reachable only through `check:unit`, an
|
|
# aggregate CI never invokes, so a leak regression could not fail a PR. Placed here
|
|
# because this is the lane whose instrumented suite would leak a run directory.
|
|
- name: Check for leaked temp directories
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: tmpdir-leaks }
|
|
|
|
# Reuses the lcov the coverage step just wrote (never runs coverage twice)
|
|
# and fails when changed-line coverage < the threshold in
|
|
# scripts/coverage-changed/model.ts. The `coverage-waiver` PR label maps to
|
|
# the waiver env, which skips the failure but still prints the numbers.
|
|
# Gated on the coverage step's own outcome (#1781 A5): when `Run coverage`
|
|
# fails, lcov.info is never written, so this step would just re-report that
|
|
# failure as its own red ("no lcov report") instead of a coverage verdict.
|
|
- name: Enforce changed-line coverage gate
|
|
if: steps.run-coverage.outcome == 'success' && github.event_name == 'pull_request'
|
|
env:
|
|
AGENT_DEVICE_COVERAGE_WAIVER: ${{ contains(github.event.pull_request.labels.*.name, 'coverage-waiver') }}
|
|
uses: ./.github/actions/run-gate
|
|
with:
|
|
gate: coverage
|
|
args: |
|
|
--base
|
|
${{ github.event.pull_request.base.sha }}
|
|
|
|
typecheck:
|
|
name: Typecheck
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 20
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
- name: Run typecheck
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: typecheck }
|
|
|
|
# CHECK_CATALOG has always claimed this job mirrors the `mcp-metadata`
|
|
# check; until #1429 checked the claim, no PR job ran it at all, so
|
|
# server.json/smithery.yaml drift only surfaced at publish time (where
|
|
# publish-mcp-registry.yml duplicates the same command). Parse-only.
|
|
- name: Check MCP registry metadata is in sync
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: mcp-metadata }
|
|
|
|
freerange:
|
|
name: FreeRange
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 20
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
|
|
|
- name: Check numeric ranges
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: freerange }
|
|
|
|
integration:
|
|
name: Integration Tests
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 60
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
|
|
- name: Run integration tests
|
|
run: pnpm clean:daemon
|
|
|
|
- name: Execute integration tests
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: integration-node }
|
|
|
|
- name: Run seeded concurrency torture lane (fast PR sweep)
|
|
# #1416's nightly torture lane lives under test/integration/nightly/, out
|
|
# of the test:integration:node glob, so this is a *deliberate* fast PR
|
|
# sweep (TORTURE_RUNS default 128 seeds, ~sub-second) — not an accidental
|
|
# glob inclusion. The Concurrency Torture Nightly workflow sweeps a much
|
|
# larger seed range on schedule.
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: concurrency-torture }
|
|
|
|
- name: Run provider-backed integration tests
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: provider-integration }
|
|
|
|
- name: Check Provider-backed integration architecture progress
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: integration-progress }
|
|
|
|
# A build-cache lookup outage must degrade setup-fixture-app to an inline
|
|
# build, not fail the caller. This drives that step's real shell against a
|
|
# failing `gh`.
|
|
- name: Setup-fixture-app cache-failure fallback
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: fixture-fallback }
|
|
# The trusted-artifact contract the device lanes rely on to decide a cached fixture
|
|
# app is the one this commit expects. A real test file that no workflow ran.
|
|
- name: Check the trusted fixture-artifact contract
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: fixture-cache }
|
|
|
|
web-smoke:
|
|
name: Web Platform Smoke
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
env:
|
|
AGENT_DEVICE_WEB_E2E: '1'
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- name: Setup toolchain
|
|
uses: ./.github/actions/setup-node-pnpm
|
|
with:
|
|
node-version: '24.13'
|
|
|
|
- name: Run live web smoke
|
|
run: pnpm clean:daemon
|
|
|
|
- name: Execute live web smoke
|
|
uses: ./.github/actions/run-gate
|
|
with: { gate: web-smoke }
|
|
|
|
- name: Upload web smoke artifacts
|
|
if: always()
|
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
with:
|
|
name: web-smoke-artifacts
|
|
if-no-files-found: ignore
|
|
path: |
|
|
test/artifacts/web/**
|