mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
ci: run QA smoke profile in CI (#94291)
* ci: add qa lab smoke profile dispatch * ci: prove qa lab smoke profile on prs * ci: preserve manual qa lab profile dispatch * ci: run qa lab smoke profile on pull requests * ci: keep QA smoke mock lane bounded * ci: run QA smoke PR proof through crabline * ci: keep mock QA timeouts on caller fallbacks * ci: prebuild QA smoke runtime * ci: delegate smoke QA evidence workflow * ci: trust release branch smoke evidence refs * ci: trim smoke evidence workflow comments * ci: align smoke evidence wrapper with QA profile contract * ci: keep smoke profile evidence mock-only * ci: make smoke profile evidence manual * ci: shard qa smoke profile in ci * ci: drop qa-channel-only smoke shard * ci: derive qa smoke shards from taxonomy * ci: keep qa smoke planner legacy-safe * ci: enforce qa smoke shard failures * ci: run qa smoke in existing fast shard * ci: opt qa smoke into crabline concurrency * test(ci): align qa smoke guard with taxonomy cleanup * ci: split qa smoke into dedicated check --------- Co-authored-by: Dallin Romney <dallinromney@gmail.com>
This commit is contained in:
@@ -251,7 +251,6 @@ jobs:
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
const createMatrix = (include) => ({ include });
|
||||
const outputPath = process.env.GITHUB_OUTPUT;
|
||||
const isCanonicalRepository = process.env.OPENCLAW_CI_REPOSITORY === "openclaw/openclaw";
|
||||
@@ -285,6 +284,7 @@ jobs:
|
||||
if (runNodeFull) {
|
||||
checksFastCoreTasks.push(
|
||||
{ check_name: "checks-fast-bundled-protocol", runtime: "node", task: "bundled-protocol" },
|
||||
{ check_name: "QA Smoke CI", runtime: "node", task: "qa-smoke-ci" },
|
||||
{ check_name: "checks-fast-bun-launcher", runtime: "bun", task: "bun-launcher" },
|
||||
);
|
||||
} else {
|
||||
@@ -922,6 +922,26 @@ jobs:
|
||||
pnpm test:bundled
|
||||
pnpm protocol:check
|
||||
;;
|
||||
qa-smoke-ci)
|
||||
output_dir=".artifacts/qa-e2e/smoke-ci-profile"
|
||||
export OPENCLAW_BUILD_PRIVATE_QA=1
|
||||
export OPENCLAW_ENABLE_PRIVATE_QA_CLI=1
|
||||
export OPENCLAW_DISABLE_BUNDLED_PLUGINS=0
|
||||
export OPENCLAW_QA_REDACT_PUBLIC_METADATA=1
|
||||
export OPENCLAW_QA_TRANSPORT_READY_TIMEOUT_MS=180000
|
||||
NODE_OPTIONS=--max-old-space-size=8192 node scripts/build-all.mjs qaRuntime
|
||||
qa_exit_code=0
|
||||
pnpm openclaw qa run \
|
||||
--repo-root . \
|
||||
--qa-profile smoke-ci \
|
||||
--concurrency 8 \
|
||||
--output-dir "$output_dir" || qa_exit_code=$?
|
||||
echo "QA smoke profile evidence: \`${output_dir}\`" >> "$GITHUB_STEP_SUMMARY"
|
||||
if [ "$qa_exit_code" -ne 0 ]; then
|
||||
echo "::error title=QA smoke profile failed::smoke-ci exited ${qa_exit_code}; evidence upload will still run"
|
||||
exit "$qa_exit_code"
|
||||
fi
|
||||
;;
|
||||
contracts-plugins-ci-routing)
|
||||
pnpm test:contracts:plugins
|
||||
pnpm test src/commands/status.scan-result.test.ts src/scripts/ci-changed-scope.test.ts test/scripts/changed-lanes.test.ts test/scripts/ci-workflow-guards.test.ts test/scripts/run-vitest.test.ts test/scripts/test-projects.test.ts
|
||||
@@ -938,6 +958,15 @@ jobs:
|
||||
;;
|
||||
esac
|
||||
|
||||
- name: Upload QA smoke profile evidence
|
||||
if: always() && matrix.task == 'qa-smoke-ci'
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
||||
with:
|
||||
name: qa-smoke-profile-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
path: .artifacts/qa-e2e/smoke-ci-profile/
|
||||
if-no-files-found: warn
|
||||
retention-days: 7
|
||||
|
||||
checks-fast-plugin-contracts-shard:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ or an explicit manual dispatch.
|
||||
| `security-fast` | Private key detection, changed-workflow audit via `zizmor`, and production lockfile audit | Always on non-draft pushes and PRs |
|
||||
| `check-dependencies` | Production Knip dependency-only pass plus the unused-file allowlist guard | Node-relevant changes |
|
||||
| `build-artifacts` | Build `dist/`, Control UI, built-CLI smoke checks, embedded built-artifact checks, and reusable artifacts | Node-relevant changes |
|
||||
| `checks-fast-core` | Fast Linux correctness lanes such as bundled, protocol, and CI-routing checks | Node-relevant changes |
|
||||
| `checks-fast-core` | Fast Linux correctness lanes such as bundled, protocol, QA Smoke CI, and CI-routing checks | Node-relevant changes |
|
||||
| `checks-fast-contracts-plugins-*` | Two sharded plugin contract checks | Node-relevant changes |
|
||||
| `checks-fast-contracts-channels-*` | Two sharded channel contract checks | Node-relevant changes |
|
||||
| `checks-node-core-*` | Core Node test shards, excluding channel, bundled, contract, and extension lanes | Node-relevant changes |
|
||||
|
||||
@@ -795,13 +795,55 @@ describe("ci workflow guards", () => {
|
||||
|
||||
it("keeps workflow guards in fast CI-routing checks", () => {
|
||||
const workflow = readCiWorkflow();
|
||||
const preflightStep = workflow.jobs.preflight.steps.find(
|
||||
(step) => step.name === "Build CI manifest",
|
||||
);
|
||||
const taxonomy = parse(readFileSync("taxonomy.yaml", "utf8")) as {
|
||||
profiles: Array<{ id: string; categoryIds: string[] }>;
|
||||
};
|
||||
const smokeProfile = taxonomy.profiles.find((profile) => profile.id === "smoke-ci");
|
||||
if (!smokeProfile) {
|
||||
throw new Error("taxonomy.yaml is missing the smoke-ci profile");
|
||||
}
|
||||
const fastCoreJob = workflow.jobs["checks-fast-core"];
|
||||
const runStep = fastCoreJob.steps.find(
|
||||
(step) => step.name === "Run ${{ matrix.task }} (${{ matrix.runtime }})",
|
||||
);
|
||||
const uploadStep = fastCoreJob.steps.find(
|
||||
(step) => step.name === "Upload QA smoke profile evidence",
|
||||
);
|
||||
|
||||
const ciWorkflowText = readFileSync(".github/workflows/ci.yml", "utf8");
|
||||
|
||||
expect(preflightStep.run).not.toContain("qa-smoke-profile");
|
||||
expect(preflightStep.run).not.toContain("qa_category");
|
||||
expect(smokeProfile.categoryIds).toHaveLength(30);
|
||||
for (const categoryId of smokeProfile.categoryIds) {
|
||||
expect(ciWorkflowText).not.toContain(`"${categoryId}"`);
|
||||
}
|
||||
expect(runStep.run).toContain("bundled-protocol)");
|
||||
expect(runStep.run).toContain("qa-smoke-ci)");
|
||||
expect(runStep.run).toContain("contracts-plugins-ci-routing)");
|
||||
expect(runStep.run).toContain("ci-routing)");
|
||||
expect(ciWorkflowText).toContain(
|
||||
'{ check_name: "QA Smoke CI", runtime: "node", task: "qa-smoke-ci" }',
|
||||
);
|
||||
expect(runStep.run).toContain("--qa-profile smoke-ci");
|
||||
expect(runStep.run).toContain("--concurrency 8");
|
||||
expect(runStep.run).not.toContain("--category");
|
||||
expect(runStep.run).not.toContain("--allow-failures");
|
||||
expect(runStep.run).toContain("qa_exit_code=0");
|
||||
expect(runStep.run).toContain('exit "$qa_exit_code"');
|
||||
expect(runStep.run).toContain("scripts/build-all.mjs qaRuntime");
|
||||
expect(runStep.run).not.toContain("OPENAI_API_KEY");
|
||||
expect(runStep.run).toMatch(
|
||||
/bundled-protocol\)\s+pnpm test:bundled\s+pnpm protocol:check\s+;;\s+qa-smoke-ci\)/,
|
||||
);
|
||||
expect(uploadStep.if).toBe("always() && matrix.task == 'qa-smoke-ci'");
|
||||
expect(uploadStep.with).toMatchObject({
|
||||
path: ".artifacts/qa-e2e/smoke-ci-profile/",
|
||||
"if-no-files-found": "warn",
|
||||
});
|
||||
expect(runStep.run.match(/test\/scripts\/ci-workflow-guards\.test\.ts/g)?.length).toBe(2);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user