ci(quality-gate): route checks by import graph and add offline agent QA

This commit is contained in:
程序员阿江(Relakkes)
2026-08-03 21:46:54 +08:00
parent 1cc76e15c5
commit 4f9fec8760
32 changed files with 2829 additions and 35 deletions
+2
View File
@@ -4,6 +4,8 @@ These rules apply to `.github/` changes in addition to the root instructions.
- Treat workflow changes as product changes. Run `bun run check:policy`; run `actionlint` when available.
- `scripts/pr/change-policy.ts` is the source of truth for path-to-check routing. Do not duplicate the routing graph in advisory automation.
- Routing is path prefixes plus the import graph from `scripts/pr/module-graph.ts`. Prefixes decide areas and every blocking rule; the graph only widens which surface checks run. When the graph cannot be built the run selects every surface rather than silently falling back to prefixes.
- `nightly-quality.yml` runs every deterministic lane unconditionally and re-proves the module graph. It exists because per-PR selection can only ever cover what a diff reaches; do not move its jobs into the required PR gate.
- Keep `pr-quality-gate` as the stable required status. Selected jobs must succeed and unselected jobs must be explicitly skipped; never convert failures into success.
- Required PR jobs must remain offline and must not receive provider credentials or depend on paid/live services.
- A `pull_request_target` workflow may inspect PR metadata using trusted base code, but must never execute the PR head, install PR-controlled dependencies, or expose secrets to contributor code.
+114
View File
@@ -0,0 +1,114 @@
name: Nightly Quality
# The PR gate is intentionally scoped: it runs only the surfaces a diff can reach.
# That leaves two blind spots no per-PR run can close — regressions that only appear
# when the whole suite runs together, and drift in checks no recent PR happened to
# select. This workflow closes them on a schedule, off the contributor's critical
# path, and still without any model, provider, or repository secret.
on:
schedule:
# 18:00 UTC = 02:00 Asia/Shanghai, after the working day.
- cron: '0 18 * * *'
workflow_dispatch:
inputs:
skip_coverage:
description: 'Skip the coverage ratchet (faster smoke of the rest)'
type: boolean
default: false
permissions:
contents: read
concurrency:
group: nightly-quality
cancel-in-progress: false
jobs:
full-deterministic:
name: full-deterministic
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: package.json
- name: Install root dependencies
run: bun install --frozen-lockfile
- name: Install desktop dependencies
working-directory: desktop
run: bun install --frozen-lockfile
- name: Install adapter dependencies
working-directory: adapters
run: bun install --frozen-lockfile
# Every deterministic lane, unconditionally — no path routing, no dependency
# graph. This is the run that catches a check the router stopped selecting.
- name: Policy and gate regressions
run: bun run check:policy
- name: Deterministic agent flow
run: bun run check:agent-flow
- name: Root runtime tests
run: bun run check:server
- name: Provider contracts
run: bun run check:provider-contract
- name: Desktop/server chat contracts
run: bun run check:chat-contract
- name: Adapter tests
run: bun run check:adapters
- name: Desktop lint, tests, and build
run: bun run check:desktop
- name: Electron host checks
run: bun run check:electron
- name: Persistence upgrade contracts
run: bun run check:persistence-upgrade
- name: Quarantine governance
run: bun run check:quarantine
- name: Coverage ratchet
if: ${{ !inputs.skip_coverage }}
env:
COVERAGE_BASE_REF: origin/main
run: bun run check:coverage
# Real desktop UI, real permission dialog, mock runtime. Skips with a printed
# reason when agent-browser is unavailable on the runner rather than failing
# the whole nightly run.
- name: Deterministic desktop UI smoke
run: bun run check:desktop-ui-smoke
- name: Upload nightly artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: nightly-quality
path: |
artifacts/agent-flow/
artifacts/desktop-ui-smoke/
artifacts/coverage/
retention-days: 14
selection-drift:
name: selection-drift
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: package.json
- name: Install root dependencies
run: bun install --frozen-lockfile
# A dependency graph that silently stops resolving would quietly downgrade the
# PR gate to prefix-only routing, which is the failure this repository already
# shipped. Re-prove the graph nightly against the real tree.
- name: Module graph health
run: bun test ./scripts/pr/module-graph.test.ts
- name: Impact report on the full tree
run: bun run check:impact --files "$(git ls-files 'src/*' 'desktop/*' 'adapters/*' | head -400 | tr '\n' ',')"
+27
View File
@@ -27,6 +27,7 @@ jobs:
desktop_native_checks: ${{ steps.policy.outputs.desktop_native_checks }}
provider_contract_checks: ${{ steps.policy.outputs.provider_contract_checks }}
chat_contract_checks: ${{ steps.policy.outputs.chat_contract_checks }}
agent_flow_checks: ${{ steps.policy.outputs.agent_flow_checks }}
persistence_checks: ${{ steps.policy.outputs.persistence_checks }}
policy_checks: ${{ steps.policy.outputs.policy_checks }}
docs_checks: ${{ steps.policy.outputs.docs_checks }}
@@ -167,6 +168,30 @@ jobs:
- name: Run desktop-server chat contracts
run: bun run check:chat-contract
agent-flow-checks:
name: agent-flow-checks
needs: scope-plan
if: needs.scope-plan.outputs.agent_flow_checks == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: package.json
- name: Install root dependencies
run: bun install --frozen-lockfile
- name: Run deterministic agent flow
run: bun run check:agent-flow
- name: Upload agent flow artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: agent-flow
path: artifacts/agent-flow/
retention-days: 7
adapter-checks:
name: adapter-checks
needs: scope-plan
@@ -298,6 +323,7 @@ jobs:
- server-checks
- provider-contract-checks
- chat-contract-checks
- agent-flow-checks
- adapter-checks
- desktop-native-checks
- persistence-checks
@@ -341,6 +367,7 @@ jobs:
require_selected "server-checks" "${{ needs.scope-plan.outputs.server_checks }}" "${{ needs.server-checks.result }}"
require_selected "provider-contract-checks" "${{ needs.scope-plan.outputs.provider_contract_checks }}" "${{ needs.provider-contract-checks.result }}"
require_selected "chat-contract-checks" "${{ needs.scope-plan.outputs.chat_contract_checks }}" "${{ needs.chat-contract-checks.result }}"
require_selected "agent-flow-checks" "${{ needs.scope-plan.outputs.agent_flow_checks }}" "${{ needs.agent-flow-checks.result }}"
require_selected "adapter-checks" "${{ needs.scope-plan.outputs.adapter_checks }}" "${{ needs.adapter-checks.result }}"
require_selected "desktop-native-checks" "${{ needs.scope-plan.outputs.desktop_native_checks }}" "${{ needs.desktop-native-checks.result }}"
require_selected "persistence-checks" "${{ needs.scope-plan.outputs.persistence_checks }}" "${{ needs.persistence-checks.result }}"