mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-16 12:31:36 +00:00
* chore(types): add declaration files for scripts/lib and scripts/e2e modules
* chore(types): add declaration files for top-level script modules (a-m)
* chore(types): add declaration files for top-level script modules (n-z)
* test: use a non-secret-shaped gateway token fixture
* test: type ci workflow guard helpers for the root test lane
* chore(tooling): typecheck root test/** with a dedicated tsgo lane
- test/tsconfig/tsconfig.test.root.json: root-test program (strict unused checks,
fixtures excluded; two Docker E2E clients that import built dist/** stay out,
same rationale as the scripts/e2e exclusion in tsconfig.scripts.json)
- tsgo:test:root wired into tsgo:test, check:test-types, scripts/check.mjs, and
the ci.yml test-types shard, mirroring the tsgo:scripts lane (#104348)
- changed-lane routing: test/**/*.ts (excluding fixtures) and the lane tsconfig
now trigger 'typecheck test root' in check:changed; previously test/ paths ran
lint only, so harness type errors surfaced first in CI (#104287 envDir case)
- burn down all 1071 latent type errors in the program: precise param/local
types across test/scripts, test/vitest, test/e2e, and transitive scripts/e2e
program members; 205 sibling .d.mts declaration files for imported .mjs
modules (committed separately); zero any, zero ts-expect-error
- resolve the pre-existing testing star-export ambiguity in
scripts/e2e/parallels/common.ts with an explicit re-export
Closes #104388
* chore(types): correct declaration fidelity per structured review
- re-derive 51 .d.mts files from implementation data flow instead of
initializers: fix a wrong never return (runTestProjectsDelegation returns
the child), add encoding-sensitive exec/spawn overloads (plain-gh), restore
the full release profile union, make parsed paths string | null, add missing
parseArgs fields via help/non-help unions, add a missing sibling declaration
(budget-number-args), drop 15 unused lint directives
- precise install-record/tuple typing removes the type-aware oxlint
regressions the first declarations caused in scripts/e2e implementations
- route .mts declaration edits under test/ to the testRoot lane and reference
the test-root project from tsconfig.projects.json so tsgo:all covers it
(closes both review findings against the lane wiring)
* chore(scripts): keep telegram runner dist typing structural for the boundary guard
* chore(types): declare runtime pack and gateway readiness exports added on main
* test: pin the importTargetPlan form of the plugin-contract plan import
The guard expectation still referenced the raw await import( form that
7ae5996bb3 (#103975) replaced with the importTargetPlan fallback helper;
the assertion fails on current main.
110 lines
3.8 KiB
TypeScript
110 lines
3.8 KiB
TypeScript
import { spawnSync } from "node:child_process";
|
|
import { readFileSync } from "node:fs";
|
|
import { describe, expect, it } from "vitest";
|
|
import { parse } from "yaml";
|
|
|
|
const fullValidationPath = ".github/workflows/full-release-validation.yml";
|
|
const releaseChecksPath = ".github/workflows/openclaw-release-checks.yml";
|
|
|
|
type Step = { name?: string; run?: string };
|
|
type Job = { steps?: Step[] };
|
|
type Workflow = { jobs?: Record<string, Job> };
|
|
|
|
function workflow(path: string): Workflow {
|
|
return parse(readFileSync(path, "utf8")) as Workflow;
|
|
}
|
|
|
|
function stepRun(path: string, jobName: string, stepName: string): string {
|
|
const job = workflow(path).jobs?.[jobName];
|
|
const step = job?.steps?.find((candidate) => candidate.name === stepName);
|
|
if (!step?.run) {
|
|
throw new Error(`Missing workflow step: ${jobName} / ${stepName}`);
|
|
}
|
|
return step.run;
|
|
}
|
|
|
|
function runReleaseChecksTrustedRefGuard(workflowRef: string): ReturnType<typeof spawnSync> {
|
|
const guard = stepRun(
|
|
releaseChecksPath,
|
|
"resolve_target",
|
|
"Require trusted workflow ref for release checks",
|
|
);
|
|
return spawnSync("bash", ["-euo", "pipefail", "-c", guard], {
|
|
encoding: "utf8",
|
|
env: {
|
|
...process.env,
|
|
RELEASE_REF: "extended-stable/2026.6.33",
|
|
WORKFLOW_REF: workflowRef,
|
|
},
|
|
});
|
|
}
|
|
|
|
describe("extended-stable Full Release Validation workflow", () => {
|
|
it("lets the exact extended-stable branch reach every child at the target SHA", () => {
|
|
const fullValidation = readFileSync(fullValidationPath, "utf8");
|
|
const childDispatches = [
|
|
{
|
|
job: "normal_ci",
|
|
step: "Dispatch and monitor CI",
|
|
workflow: "ci.yml",
|
|
target: '-f target_ref="$TARGET_SHA"',
|
|
},
|
|
{
|
|
job: "plugin_prerelease",
|
|
step: "Dispatch and monitor plugin prerelease",
|
|
workflow: "plugin-prerelease.yml",
|
|
target: '-f target_ref="$TARGET_SHA" -f expected_sha="$TARGET_SHA"',
|
|
},
|
|
{
|
|
job: "release_checks",
|
|
step: "Dispatch and monitor release checks",
|
|
workflow: "openclaw-release-checks.yml",
|
|
target: '-f expected_sha="$TARGET_SHA"',
|
|
},
|
|
{
|
|
job: "performance",
|
|
step: "Dispatch and monitor OpenClaw Performance",
|
|
workflow: "openclaw-performance.yml",
|
|
target: '-f target_ref="$TARGET_SHA"',
|
|
},
|
|
];
|
|
|
|
for (const child of childDispatches) {
|
|
const run = stepRun(fullValidationPath, child.job, child.step);
|
|
expect(run).toContain(child.workflow);
|
|
expect(run).toContain('--ref "$CHILD_WORKFLOW_REF"');
|
|
expect(run).toContain(child.target);
|
|
}
|
|
|
|
expect(fullValidation).toContain("PARENT_WORKFLOW_SHA: ${{ github.sha }}");
|
|
expect(fullValidation).toContain('if [[ "$head_sha" != "$PARENT_WORKFLOW_SHA" ]]');
|
|
expect(fullValidation).toContain(
|
|
"child run used workflow SHA ${head_sha}, expected parent workflow SHA ${PARENT_WORKFLOW_SHA}",
|
|
);
|
|
});
|
|
|
|
it("accepts only the exact extended-stable/YYYY.M.33 workflow-ref shape", () => {
|
|
for (const valid of [
|
|
"refs/heads/extended-stable/2026.6.33",
|
|
"refs/heads/extended-stable/2026.12.33",
|
|
]) {
|
|
const result = runReleaseChecksTrustedRefGuard(valid);
|
|
expect(result.status, String(result.stderr)).toBe(0);
|
|
}
|
|
|
|
for (const invalid of [
|
|
"refs/heads/extended-stable/2026.0.33",
|
|
"refs/heads/extended-stable/2026.01.33",
|
|
"refs/heads/extended-stable/2026.13.33",
|
|
"refs/heads/extended-stable/2026.6.32",
|
|
"refs/heads/extended-stable/2026.6.34",
|
|
"refs/heads/extended-stable/2026.6.33/extra",
|
|
"refs/heads/extended-stable/not-a-release",
|
|
]) {
|
|
const result = runReleaseChecksTrustedRefGuard(invalid);
|
|
expect(result.status, invalid).not.toBe(0);
|
|
expect(result.stderr).toContain("extended-stable/YYYY.M.33");
|
|
}
|
|
});
|
|
});
|