fix(release): bootstrap typed Docker planner (#121088)

* fix(release): bootstrap typed Docker planner

* test(release): handle optional workflow steps

* fix(release): isolate trusted planner dependencies

Punchcard-Session: amber-workshop-workshop-36

* test(release): update trusted harness contract

Punchcard-Session: amber-workshop-workshop-36

* fix(release): bootstrap every trusted Docker planner

Punchcard-Session: amber-workshop-workshop-36

* fix(release): centralize trusted harness bootstrap

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
Peter Steinberger
2026-08-09 11:14:23 -07:00
committed by GitHub
parent b0a1a2ab5c
commit a828bfe04e
4 changed files with 144 additions and 31 deletions
@@ -0,0 +1,23 @@
name: Setup trusted release harness
description: Prepare the trusted release harness package manager and dependencies.
inputs:
node-version:
description: Node.js version required by the release harness.
required: true
runs:
using: composite
steps:
- name: Setup trusted release harness package manager
uses: ./.release-harness/.github/actions/setup-pnpm-store-cache
with:
node-version: ${{ inputs.node-version }}
package-manager-file: .release-harness/package.json
use-actions-cache: "false"
- name: Install trusted release harness dependencies
shell: bash
working-directory: .release-harness
env:
CI: "true"
# Corepack resolves packageManager from cwd before pnpm processes --dir.
run: pnpm install --frozen-lockfile --prefer-offline --ignore-scripts
@@ -1256,6 +1256,12 @@ jobs:
fetch-depth: 1
path: .release-harness
- name: Setup trusted release harness
if: contains(matrix.profiles, inputs.release_test_profile)
uses: ./.release-harness/.github/actions/setup-release-harness
with:
node-version: ${{ env.NODE_VERSION }}
- name: Log in to GHCR for shared Docker E2E image
if: contains(matrix.profiles, inputs.release_test_profile) && inputs.shared_image_policy != 'no-push-artifact'
run: bash .release-harness/scripts/ci-docker-login-ghcr.sh
@@ -1632,6 +1638,11 @@ jobs:
fetch-depth: 1
path: .release-harness
- name: Setup trusted release harness
uses: ./.release-harness/.github/actions/setup-release-harness
with:
node-version: ${{ env.NODE_VERSION }}
- name: Log in to GHCR for shared Docker E2E image
if: inputs.shared_image_policy != 'no-push-artifact'
run: bash .release-harness/scripts/ci-docker-login-ghcr.sh
@@ -1919,6 +1930,11 @@ jobs:
path: .release-harness
persist-credentials: false
- name: Setup trusted release harness
uses: ./.release-harness/.github/actions/setup-release-harness
with:
node-version: ${{ env.NODE_VERSION }}
- name: Log in to GHCR for shared Docker E2E image
if: inputs.shared_image_policy != 'no-push-artifact'
run: bash .release-harness/scripts/ci-docker-login-ghcr.sh
@@ -2141,6 +2157,11 @@ jobs:
path: .release-harness
persist-credentials: false
- name: Setup trusted release harness
uses: ./.release-harness/.github/actions/setup-release-harness
with:
node-version: ${{ env.NODE_VERSION }}
- name: Plan Docker E2E images
id: plan
shell: bash
@@ -2187,24 +2208,6 @@ jobs:
node-version: ${{ env.NODE_VERSION }}
install-bun: "true"
- name: Setup artifact package validation environment
if: steps.plan.outputs.needs_package == '1' && inputs.package_artifact_id != ''
uses: ./.release-harness/.github/actions/setup-pnpm-store-cache
with:
node-version: ${{ env.NODE_VERSION }}
package-manager-file: .release-harness/package.json
use-actions-cache: "false"
- name: Install trusted package validation dependencies
if: steps.plan.outputs.needs_package == '1' && inputs.package_artifact_id != ''
env:
CI: "true"
# Corepack resolves packageManager from the process cwd before pnpm can
# process --dir. Keep this in the trusted harness so a frozen candidate
# pin cannot select a different pnpm binary for its harness install.
working-directory: .release-harness
run: pnpm install --frozen-lockfile --prefer-offline --ignore-scripts
- name: Validate OpenClaw package artifact identity
id: input_package_artifact
if: steps.plan.outputs.needs_package == '1' && inputs.package_artifact_id != ''
@@ -31,6 +31,7 @@ const MANTIS_TELEGRAM_LIVE_WORKFLOW = ".github/workflows/mantis-telegram-live.ym
const MANTIS_WEB_UI_CHAT_PROOF_WORKFLOW = ".github/workflows/mantis-web-ui-chat-proof.yml";
const PACKAGE_JSON = "package.json";
const SETUP_PNPM_STORE_CACHE_ACTION = ".github/actions/setup-pnpm-store-cache/action.yml";
const SETUP_RELEASE_HARNESS_ACTION = ".github/actions/setup-release-harness/action.yml";
const RELEASE_CHECKS_WORKFLOW = ".github/workflows/openclaw-release-checks.yml";
const RELEASE_TELEGRAM_QA_WORKFLOW = ".github/workflows/openclaw-release-telegram-qa.yml";
const RELEASE_PUBLISH_WORKFLOW = ".github/workflows/openclaw-release-publish.yml";
@@ -118,6 +119,7 @@ type WorkflowStep = {
shell?: string;
uses?: string;
with?: Record<string, string>;
"working-directory"?: string;
};
type WorkflowMatrixEntry = {
@@ -1350,6 +1352,26 @@ describe("package acceptance workflow", () => {
expect(setupPnpmAction).toContain('corepack enable --install-directory "$PNPM_HOME"');
expect(setupPnpmAction).toContain('echo "PNPM_HOME=$PNPM_HOME" >> "$GITHUB_ENV"');
const setupReleaseHarnessAction = readFileSync(SETUP_RELEASE_HARNESS_ACTION, "utf8");
const setupHarnessPackageManagerIndex = setupReleaseHarnessAction.indexOf(
"Setup trusted release harness package manager",
);
const installHarnessDependenciesIndex = setupReleaseHarnessAction.indexOf(
"Install trusted release harness dependencies",
);
expect(setupHarnessPackageManagerIndex).toBeGreaterThan(-1);
expect(installHarnessDependenciesIndex).toBeGreaterThan(setupHarnessPackageManagerIndex);
expect(setupReleaseHarnessAction).toContain(
"uses: ./.release-harness/.github/actions/setup-pnpm-store-cache",
);
expect(setupReleaseHarnessAction).toContain(
"package-manager-file: .release-harness/package.json",
);
expect(setupReleaseHarnessAction).toContain("working-directory: .release-harness");
expect(setupReleaseHarnessAction).toContain(
"pnpm install --frozen-lockfile --prefer-offline --ignore-scripts",
);
const setupNodeAction = readFileSync(".github/actions/setup-node-env/action.yml", "utf8");
expect(setupNodeAction).toContain("Normalize container toolcache");
expect(setupNodeAction).toContain("ln -s /__t /opt/hostedtoolcache");
@@ -2408,6 +2430,7 @@ describe("package artifact reuse", () => {
it("lets reusable Docker E2E consume an already resolved package artifact", () => {
const workflow = readFileSync(LIVE_E2E_WORKFLOW, "utf8");
const parsedWorkflow = parse(workflow) as {
jobs?: Record<string, WorkflowJob>;
on?: { workflow_call?: { inputs?: Record<string, unknown> } };
};
const packageJson = readFileSync(PACKAGE_JSON, "utf8");
@@ -2495,8 +2518,80 @@ describe("package artifact reuse", () => {
?.prepublish_plugin_registry_artifact_id,
).toContain("inputs.enable_prepublish_plugin_registry");
expect(workflow).toContain("bash .release-harness/scripts/ci-docker-pull-retry.sh");
const setupHarnessStepName = "Setup trusted release harness";
const harnessJobCases = [
{
jobId: "validate_docker_e2e",
planStepName: "Plan Docker E2E chunk",
setupIf: "contains(matrix.profiles, inputs.release_test_profile)",
},
{
jobId: "validate_docker_lanes",
planStepName: "Plan targeted Docker E2E lanes",
setupIf: undefined,
},
{
jobId: "validate_docker_openwebui",
planStepName: "Plan Open WebUI Docker E2E chunk",
setupIf: undefined,
},
{
jobId: "prepare_docker_e2e_image",
planStepName: "Plan Docker E2E images",
setupIf: undefined,
},
] as const;
const typedHarnessJobIds = Object.entries(parsedWorkflow.jobs ?? {})
.filter(([, job]) =>
(job.steps ?? []).some(
(step) =>
step.run?.includes("node .release-harness/scripts/test-docker-all.mjs") ||
step.run?.includes("node .release-harness/scripts/docker-e2e.mjs"),
),
)
.map(([jobId]) => jobId)
.sort();
expect(typedHarnessJobIds).toEqual(harnessJobCases.map(({ jobId }) => jobId).sort());
for (const { jobId, planStepName, setupIf } of harnessJobCases) {
const harnessJob = workflowJob(LIVE_E2E_WORKFLOW, jobId);
const harnessJobSteps = harnessJob.steps ?? [];
const harnessJobStepNames = harnessJobSteps.map((step) => step.name);
const checkoutIndex = harnessJobStepNames.indexOf("Checkout trusted release harness");
const setupIndex = harnessJobStepNames.indexOf(setupHarnessStepName);
const typedHarnessIndex = harnessJobSteps.findIndex(
(step) =>
step.run?.includes("node .release-harness/scripts/test-docker-all.mjs") ||
step.run?.includes("node .release-harness/scripts/docker-e2e.mjs"),
);
expect(harnessJobStepNames.filter((name) => name === setupHarnessStepName)).toHaveLength(1);
expect(checkoutIndex).toBeGreaterThan(-1);
expect(setupIndex).toBeGreaterThan(checkoutIndex);
expect(typedHarnessIndex).toBeGreaterThan(setupIndex);
expect(workflowStep(harnessJob, planStepName)).toBeDefined();
const setupHarnessStep = workflowStep(harnessJob, setupHarnessStepName);
expect(setupHarnessStep).toMatchObject({
uses: "./.release-harness/.github/actions/setup-release-harness",
with: { "node-version": "${{ env.NODE_VERSION }}" },
});
expect(setupHarnessStep.if).toBe(setupIf);
}
const prepareDockerImage = workflowJob(LIVE_E2E_WORKFLOW, "prepare_docker_e2e_image");
expect(workflowStep(prepareDockerImage, "Plan Docker E2E images").env).toEqual({
const prepareDockerImageStepNames = (prepareDockerImage.steps ?? []).map((step) => step.name);
const planStepName = "Plan Docker E2E images";
const setupCandidateStepName = "Setup Node environment";
expect(
prepareDockerImageStepNames.filter((name) => name === setupCandidateStepName),
).toHaveLength(1);
expect(prepareDockerImageStepNames.indexOf(setupCandidateStepName)).toBeGreaterThan(
prepareDockerImageStepNames.indexOf(planStepName),
);
expect(workflowStep(prepareDockerImage, setupCandidateStepName)).toMatchObject({
if: "(steps.plan.outputs.needs_package == '1' && inputs.package_artifact_name == '' && inputs.package_artifact_run_id == '') || (inputs.enable_prepublish_plugin_registry && steps.plan.outputs.needs_prepublish_plugin_registry == '1' && inputs.prepublish_plugin_registry_artifact_id == '')",
uses: "./.github/actions/setup-node-env",
});
expect(workflowStep(prepareDockerImage, planStepName).env).toEqual({
INCLUDE_OPENWEBUI: "${{ inputs.include_openwebui }}",
INCLUDE_RELEASE_PATH_SUITES: "${{ inputs.include_release_path_suites }}",
LANES: "${{ inputs.docker_lanes }}",
+4 -12
View File
@@ -693,19 +693,11 @@ describe("release validation no-push transport", () => {
);
expect(packDockerArtifact.run).toContain("archive_sha256=");
const validatePackage = step(dockerProducer, "Validate OpenClaw Docker E2E package");
expect(step(dockerProducer, "Setup artifact package validation environment")).toMatchObject({
if: "steps.plan.outputs.needs_package == '1' && inputs.package_artifact_id != ''",
uses: "./.release-harness/.github/actions/setup-pnpm-store-cache",
with: {
"package-manager-file": ".release-harness/package.json",
"use-actions-cache": "false",
},
});
expect(step(dockerProducer, "Install trusted package validation dependencies")).toMatchObject({
if: "steps.plan.outputs.needs_package == '1' && inputs.package_artifact_id != ''",
"working-directory": ".release-harness",
run: "pnpm install --frozen-lockfile --prefer-offline --ignore-scripts",
expect(step(dockerProducer, "Setup trusted release harness")).toMatchObject({
uses: "./.release-harness/.github/actions/setup-release-harness",
with: { "node-version": "${{ env.NODE_VERSION }}" },
});
expect(step(dockerProducer, "Setup trusted release harness").if).toBeUndefined();
expect(validatePackage.env).toMatchObject({
EXPECTED_PACKAGE_FILE_NAME: "${{ inputs.package_file_name }}",
EXPECTED_PACKAGE_SHA256: "${{ inputs.package_sha256 }}",