mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-25 11:55:47 -06:00
fix(release): keep protected tooling foundation npm-only
This commit is contained in:
@@ -962,7 +962,6 @@ jobs:
|
||||
CHILD_WORKFLOW_REF: ${{ github.ref_name }}
|
||||
PARENT_WORKFLOW_SHA: ${{ github.sha }}
|
||||
PARENT_WORKFLOW_BRANCH: ${{ github.ref_name }}
|
||||
PARENT_WORKFLOW_FULL_REF: ${{ github.ref }}
|
||||
RELEASE_TAG: ${{ inputs.tag }}
|
||||
PREFLIGHT_RUN_ID: ${{ inputs.preflight_run_id }}
|
||||
FULL_RELEASE_VALIDATION_RUN_ID: ${{ inputs.full_release_validation_run_id }}
|
||||
@@ -2284,16 +2283,9 @@ jobs:
|
||||
if [[ "$(jq -r '.normal.shouldDispatch' "${clawhub_plan_path}")" == "true" ]]; then
|
||||
clawhub_dispatch_args=()
|
||||
append_clawhub_dispatch_args normal
|
||||
if [[ "${PARENT_WORKFLOW_FULL_REF}" == "refs/heads/main" ||
|
||||
"${PARENT_WORKFLOW_FULL_REF}" =~ ^refs/tags/release-publish/[a-f0-9]{12}-[1-9][0-9]*$ ]]; then
|
||||
clawhub_dispatch_args+=(
|
||||
-f release_publish_full_ref="${PARENT_WORKFLOW_FULL_REF}"
|
||||
-f release_publish_workflow_sha="${PARENT_WORKFLOW_SHA}"
|
||||
)
|
||||
fi
|
||||
plugin_clawhub_run_id="$(dispatch_workflow_at_ref \
|
||||
"$(jq -r '.normal.ref' "${clawhub_plan_path}")" \
|
||||
"${PARENT_WORKFLOW_SHA}" \
|
||||
"${TARGET_SHA}" \
|
||||
"$(jq -r '.normal.workflow' "${clawhub_plan_path}")" \
|
||||
"${clawhub_dispatch_args[@]}")"
|
||||
else
|
||||
@@ -2374,7 +2366,7 @@ jobs:
|
||||
if [[ -n "${plugin_clawhub_run_id}" ]]; then
|
||||
clawhub_result="$RUNNER_TEMP/clawhub-result.txt"
|
||||
wait_run_pid=""
|
||||
wait_for_run_background plugin-clawhub-release.yml "${plugin_clawhub_run_id}" "${PARENT_WORKFLOW_SHA}" "${clawhub_result}"
|
||||
wait_for_run_background plugin-clawhub-release.yml "${plugin_clawhub_run_id}" "${TARGET_SHA}" "${clawhub_result}"
|
||||
clawhub_pid="${wait_run_pid}"
|
||||
fi
|
||||
if [[ -n "${plugin_clawhub_bootstrap_run_id}" ]]; then
|
||||
|
||||
@@ -24,24 +24,10 @@ on:
|
||||
description: Approved OpenClaw Release Publish workflow run id
|
||||
required: false
|
||||
type: string
|
||||
release_publish_run_attempt:
|
||||
description: Exact approved OpenClaw Release Publish workflow run attempt
|
||||
required: false
|
||||
type: string
|
||||
release_publish_branch:
|
||||
description: Branch name of the approving OpenClaw Release Publish workflow run
|
||||
required: false
|
||||
type: string
|
||||
release_publish_full_ref:
|
||||
description: Exact full ref of the approving OpenClaw Release Publish workflow tooling
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
release_publish_workflow_sha:
|
||||
description: Exact workflow SHA of the approving OpenClaw Release Publish tooling
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
dry_run:
|
||||
description: Validate the full ClawHub artifact handoff without publishing.
|
||||
required: false
|
||||
@@ -75,7 +61,6 @@ jobs:
|
||||
matrix: ${{ steps.plan.outputs.matrix }}
|
||||
bootstrap_matrix: ${{ steps.plan.outputs.bootstrap_matrix }}
|
||||
missing_trusted_publisher_matrix: ${{ steps.plan.outputs.missing_trusted_publisher_matrix }}
|
||||
trusted_tooling_identity_json: ${{ steps.tooling_identity.outputs.json }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -107,89 +92,9 @@ jobs:
|
||||
fi
|
||||
echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Capture trusted tooling identity
|
||||
id: tooling_identity
|
||||
env:
|
||||
CALLER_FULL_REF: ${{ github.ref }}
|
||||
CALLER_REF: ${{ github.ref_name }}
|
||||
CALLER_RUN_ATTEMPT: ${{ github.run_attempt }}
|
||||
CALLER_RUN_ID: ${{ github.run_id }}
|
||||
CALLER_SHA: ${{ github.sha }}
|
||||
PARENT_RUN_ATTEMPT: ${{ inputs.release_publish_run_attempt }}
|
||||
PARENT_RUN_ID: ${{ inputs.release_publish_run_id }}
|
||||
PARENT_STATE_POLICY: ${{ inputs.release_publish_run_id != '' && (github.actor == 'github-actions[bot]' && 'active-or-success' || 'recovery-active-or-success-or-failure') || '' }}
|
||||
TOOLING_FULL_REF: ${{ inputs.release_publish_full_ref }}
|
||||
TOOLING_REF: ${{ inputs.release_publish_branch }}
|
||||
TOOLING_SHA: ${{ inputs.release_publish_workflow_sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "${TOOLING_FULL_REF}${TOOLING_SHA}" ]]; then
|
||||
echo "json=" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
[[ -n "$TOOLING_FULL_REF" && -n "$TOOLING_REF" && -n "$TOOLING_SHA" ]] || {
|
||||
echo "Trusted release tooling ref, full ref, and SHA must be provided together." >&2
|
||||
exit 1
|
||||
}
|
||||
[[ -n "$PARENT_RUN_ID" && -n "$PARENT_RUN_ATTEMPT" && -n "$PARENT_STATE_POLICY" ]] || {
|
||||
echo "Trusted release parent run id, attempt, and state policy must be provided together." >&2
|
||||
exit 1
|
||||
}
|
||||
identity="$(
|
||||
jq -cn \
|
||||
--arg repository "$GITHUB_REPOSITORY" \
|
||||
--arg workflow ".github/workflows/plugin-clawhub-release.yml" \
|
||||
--arg runId "$CALLER_RUN_ID" \
|
||||
--arg runAttempt "$CALLER_RUN_ATTEMPT" \
|
||||
--arg ref "$CALLER_REF" \
|
||||
--arg fullRef "$CALLER_FULL_REF" \
|
||||
--arg sha "$CALLER_SHA" \
|
||||
--arg toolingRef "$TOOLING_REF" \
|
||||
--arg toolingFullRef "$TOOLING_FULL_REF" \
|
||||
--arg toolingSha "$TOOLING_SHA" \
|
||||
--arg parentRepository "$GITHUB_REPOSITORY" \
|
||||
--arg parentWorkflow ".github/workflows/openclaw-release-publish.yml" \
|
||||
--arg parentRunId "$PARENT_RUN_ID" \
|
||||
--arg parentRunAttempt "$PARENT_RUN_ATTEMPT" \
|
||||
--arg parentRef "$TOOLING_REF" \
|
||||
--arg parentFullRef "$TOOLING_FULL_REF" \
|
||||
--arg parentSha "$TOOLING_SHA" \
|
||||
--arg parentStatePolicy "$PARENT_STATE_POLICY" \
|
||||
'{
|
||||
version: 2,
|
||||
repository: $repository,
|
||||
workflow: $workflow,
|
||||
runId: $runId,
|
||||
runAttempt: $runAttempt,
|
||||
ref: $ref,
|
||||
fullRef: $fullRef,
|
||||
sha: $sha,
|
||||
toolingRef: $toolingRef,
|
||||
toolingFullRef: $toolingFullRef,
|
||||
toolingSha: $toolingSha,
|
||||
parentRepository: $parentRepository,
|
||||
parentWorkflow: $parentWorkflow,
|
||||
parentRunId: $parentRunId,
|
||||
parentRunAttempt: $parentRunAttempt,
|
||||
parentRef: $parentRef,
|
||||
parentFullRef: $parentFullRef,
|
||||
parentSha: $parentSha,
|
||||
parentStatePolicy: $parentStatePolicy
|
||||
}'
|
||||
)"
|
||||
echo "json=${identity}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Validate OIDC source matches workflow ref
|
||||
env:
|
||||
RELEASE_PUBLISH_FULL_REF: ${{ inputs.release_publish_full_ref }}
|
||||
RELEASE_PUBLISH_RUN_ATTEMPT: ${{ inputs.release_publish_run_attempt }}
|
||||
RELEASE_PUBLISH_RUN_ID: ${{ inputs.release_publish_run_id }}
|
||||
RELEASE_PUBLISH_TOOLING_REF: ${{ inputs.release_publish_branch }}
|
||||
RELEASE_PUBLISH_TOOLING_SHA: ${{ inputs.release_publish_workflow_sha }}
|
||||
TARGET_REF: ${{ inputs.ref }}
|
||||
TARGET_SHA: ${{ steps.ref.outputs.sha }}
|
||||
WORKFLOW_FULL_REF: ${{ github.ref }}
|
||||
WORKFLOW_REF: ${{ github.ref_name }}
|
||||
WORKFLOW_SHA: ${{ github.sha }}
|
||||
DRY_RUN: ${{ inputs.dry_run && 'true' || 'false' }}
|
||||
run: |
|
||||
@@ -199,22 +104,10 @@ jobs:
|
||||
echo "Dry-run publish target differs from workflow ref; allowing validation-only dispatch."
|
||||
exit 0
|
||||
fi
|
||||
[[ "$TARGET_REF" =~ ^[a-f0-9]{40}$ && "$TARGET_REF" == "$TARGET_SHA" ]] || {
|
||||
echo "Split-ref ClawHub publication requires ref to be the exact candidate SHA." >&2
|
||||
exit 1
|
||||
}
|
||||
[[ "$RELEASE_PUBLISH_TOOLING_REF" == "$WORKFLOW_REF" &&
|
||||
"$RELEASE_PUBLISH_FULL_REF" == "$WORKFLOW_FULL_REF" &&
|
||||
"$RELEASE_PUBLISH_TOOLING_SHA" == "$WORKFLOW_SHA" ]] || {
|
||||
echo "Split-ref ClawHub publication tooling identity does not match the executing workflow." >&2
|
||||
exit 1
|
||||
}
|
||||
[[ "$RELEASE_PUBLISH_RUN_ID" =~ ^[1-9][0-9]*$ &&
|
||||
"$RELEASE_PUBLISH_RUN_ATTEMPT" =~ ^[1-9][0-9]*$ ]] || {
|
||||
echo "Split-ref ClawHub publication requires the exact parent run id and attempt." >&2
|
||||
exit 1
|
||||
}
|
||||
echo "Using trusted workflow tooling with separately bound candidate ${TARGET_SHA}."
|
||||
echo "Plugin ClawHub OIDC publishes must run from the same ref that is being published." >&2
|
||||
echo "The ref input is only supported for dry_run=true." >&2
|
||||
echo "For real publishes, dispatch this workflow with --ref pointing at the target release tag/ref and omit the ref input." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Validate ref is on a trusted publish branch
|
||||
@@ -392,9 +285,6 @@ jobs:
|
||||
ALLOW_COMPLETED_SUCCESSFUL_PARENT: "true"
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
RELEASE_PUBLISH_RUN_ID: ${{ inputs.release_publish_run_id }}
|
||||
EXPECTED_RUN_ATTEMPT: ${{ inputs.release_publish_run_attempt }}
|
||||
EXPECTED_WORKFLOW_FULL_REF: ${{ inputs.release_publish_full_ref || github.ref }}
|
||||
EXPECTED_WORKFLOW_SHA: ${{ inputs.release_publish_workflow_sha || github.sha }}
|
||||
EXPECTED_WORKFLOW_BRANCH: ${{ inputs.release_publish_branch || github.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -411,7 +301,7 @@ jobs:
|
||||
direct_recovery=true
|
||||
echo "Direct Plugin ClawHub Release recovery with release_publish_run_id; relying on this workflow's clawhub-plugin-release environment approval."
|
||||
fi
|
||||
RUN_JSON="$(gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${RELEASE_PUBLISH_RUN_ID}" --jq '{workflowName: .name, headBranch: .head_branch, headSha: .head_sha, event, status, conclusion, url: .html_url, runAttempt: .run_attempt, repository: .repository.full_name, path}')"
|
||||
RUN_JSON="$(gh run view "$RELEASE_PUBLISH_RUN_ID" --repo "$GITHUB_REPOSITORY" --json workflowName,headBranch,event,status,conclusion,url)"
|
||||
printf '%s' "$RUN_JSON" | DIRECT_RELEASE_RECOVERY="${direct_recovery}" node scripts/validate-release-publish-approval.mjs
|
||||
|
||||
pack_plugins_clawhub_artifacts:
|
||||
@@ -498,7 +388,7 @@ jobs:
|
||||
needs:
|
||||
[preview_plugins_clawhub, pack_plugins_clawhub_artifacts, approve_plugins_clawhub_release]
|
||||
if: always() && github.event_name == 'workflow_dispatch' && needs.preview_plugins_clawhub.outputs.has_candidates == 'true' && needs.pack_plugins_clawhub_artifacts.result == 'success' && (inputs.dry_run == true || needs.approve_plugins_clawhub_release.result == 'success')
|
||||
uses: openclaw/clawhub/.github/workflows/package-publish.yml@a42cd2f73d6afb769b271d463fc111669cb7a499
|
||||
uses: openclaw/clawhub/.github/workflows/package-publish.yml@d8096dfc039e86ab942ddf9ef117d04849fd84c1
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
@@ -521,7 +411,6 @@ jobs:
|
||||
source_path: ${{ matrix.plugin.packageDir }}
|
||||
inspector_artifact_name: ${{ matrix.plugin.artifactName }}-inspector
|
||||
publish_json_artifact_name: ${{ matrix.plugin.artifactName }}-publish-json
|
||||
trusted_tooling_identity_json: ${{ needs.preview_plugins_clawhub.outputs.trusted_tooling_identity_json }}
|
||||
|
||||
verify_published_clawhub_package:
|
||||
needs: [preview_plugins_clawhub, publish_plugins_clawhub]
|
||||
|
||||
@@ -353,17 +353,15 @@ export async function buildOpenClawReleaseClawHubPlan(
|
||||
|
||||
return {
|
||||
bootstrapWorkflowSha,
|
||||
clawHubWorkflowRef: bootstrapWorkflowRef,
|
||||
clawHubWorkflowRef: releaseTag,
|
||||
releasePublishBranch,
|
||||
normal: createDispatchTarget({
|
||||
workflow: "plugin-clawhub-release.yml",
|
||||
ref: bootstrapWorkflowRef,
|
||||
ref: releaseTag,
|
||||
packages: normalPackages,
|
||||
releasePublishRunId,
|
||||
releasePublishBranch,
|
||||
releasePublishRunAttempt,
|
||||
includePublishScope: true,
|
||||
targetRef: releaseSha,
|
||||
}),
|
||||
bootstrap: createDispatchTarget({
|
||||
workflow: "plugin-clawhub-new.yml",
|
||||
@@ -386,7 +384,7 @@ export async function buildOpenClawReleaseClawHubPlan(
|
||||
missingTrustedPlugins: joinPackageNames(missingTrustedPlugins),
|
||||
},
|
||||
verifier: {
|
||||
clawHubWorkflowRef: bootstrapWorkflowRef,
|
||||
clawHubWorkflowRef: releaseTag,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1315,19 +1315,17 @@ describe("buildOpenClawReleaseClawHubPlan", () => {
|
||||
},
|
||||
);
|
||||
|
||||
expect(plan.clawHubWorkflowRef).toBe(`release-publish/${"d".repeat(12)}-12345`);
|
||||
expect(plan.clawHubWorkflowRef).toBe("v2026.4.1-beta.1");
|
||||
expect(plan.bootstrapWorkflowSha).toBe("d".repeat(40));
|
||||
expect(plan.releasePublishBranch).toBe("main");
|
||||
expect(plan.normal).toEqual({
|
||||
workflow: "plugin-clawhub-release.yml",
|
||||
ref: `release-publish/${"d".repeat(12)}-12345`,
|
||||
ref: "v2026.4.1-beta.1",
|
||||
shouldDispatch: true,
|
||||
packages: ["@openclaw/demo-plugin"],
|
||||
inputs: {
|
||||
publish_scope: "selected",
|
||||
ref: "a".repeat(40),
|
||||
plugins: "@openclaw/demo-plugin",
|
||||
release_publish_run_attempt: "2",
|
||||
release_publish_run_id: "12345",
|
||||
release_publish_branch: "main",
|
||||
},
|
||||
@@ -1357,7 +1355,7 @@ describe("buildOpenClawReleaseClawHubPlan", () => {
|
||||
missingTrustedPlugins: "@openclaw/demo-three",
|
||||
});
|
||||
expect(plan.verifier).toEqual({
|
||||
clawHubWorkflowRef: `release-publish/${"d".repeat(12)}-12345`,
|
||||
clawHubWorkflowRef: "v2026.4.1-beta.1",
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1963,35 +1963,6 @@ describe("package acceptance workflow", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("binds normal ClawHub dispatch, approval, and waiting to tooling SHA", () => {
|
||||
const publishRun =
|
||||
workflowStep(workflowJob(RELEASE_PUBLISH_WORKFLOW, "publish"), "Dispatch publish workflows")
|
||||
.run ?? "";
|
||||
const waitForRun = shellFunctionSource(publishRun, "wait_for_run");
|
||||
const appendClawHubArgs = shellFunctionSource(publishRun, "append_clawhub_dispatch_args");
|
||||
const normalDispatch = publishRun.match(
|
||||
/plugin_clawhub_run_id="\$\(dispatch_workflow_at_ref[\s\S]*?\)"\n/u,
|
||||
)?.[0];
|
||||
|
||||
expect(normalDispatch).toContain('"${PARENT_WORKFLOW_SHA}"');
|
||||
expect(normalDispatch).not.toContain('"${TARGET_SHA}"');
|
||||
expect(publishRun).toContain(
|
||||
'wait_for_run_background plugin-clawhub-release.yml "${plugin_clawhub_run_id}" "${PARENT_WORKFLOW_SHA}"',
|
||||
);
|
||||
expect(publishRun).not.toContain(
|
||||
'wait_for_run_background plugin-clawhub-release.yml "${plugin_clawhub_run_id}" "${TARGET_SHA}"',
|
||||
);
|
||||
expect(waitForRun).toContain(
|
||||
'approve_pending_deployments "${workflow}" "${run_id}" "${expected_sha}"',
|
||||
);
|
||||
expect(appendClawHubArgs).toContain(
|
||||
"'.[$target].inputs | to_entries[] | [.key, .value] | @tsv'",
|
||||
);
|
||||
expect(readFileSync("scripts/lib/openclaw-release-clawhub-plan.ts", "utf8")).toMatch(
|
||||
/normal: createDispatchTarget\(\{[\s\S]*?ref: bootstrapWorkflowRef,[\s\S]*?targetRef: releaseSha,/u,
|
||||
);
|
||||
});
|
||||
|
||||
it("compares dependency evidence zip contents independently of archive timestamps", () => {
|
||||
const orchestration = workflowStep(
|
||||
workflowJob(RELEASE_PUBLISH_WORKFLOW, "publish"),
|
||||
@@ -7170,7 +7141,6 @@ describe("package artifact reuse", () => {
|
||||
".github/workflows/plugin-clawhub-new.yml",
|
||||
"publish_bootstrap_plugins",
|
||||
);
|
||||
const publishOrchestration = workflowStep(releasePublishJob, "Dispatch publish workflows");
|
||||
const postpublishEvidence = workflowStep(releasePublishJob, "Upload postpublish evidence");
|
||||
|
||||
expect(packageJson.scripts).toMatchObject({
|
||||
@@ -7197,103 +7167,35 @@ describe("package artifact reuse", () => {
|
||||
"approve_plugins_clawhub_release",
|
||||
]);
|
||||
expect(clawHubPublish.uses).toBe(
|
||||
"openclaw/clawhub/.github/workflows/package-publish.yml@a42cd2f73d6afb769b271d463fc111669cb7a499",
|
||||
"openclaw/clawhub/.github/workflows/package-publish.yml@d8096dfc039e86ab942ddf9ef117d04849fd84c1",
|
||||
);
|
||||
expect(clawHubPublish.permissions).toMatchObject({
|
||||
actions: "read",
|
||||
contents: "read",
|
||||
"id-token": "write",
|
||||
});
|
||||
expect(clawHubPublish.with?.trusted_tooling_identity_json).toBe(
|
||||
"${{ needs.preview_plugins_clawhub.outputs.trusted_tooling_identity_json }}",
|
||||
);
|
||||
expect(clawHubPublish.with?.trusted_tooling_identity_json).toBeUndefined();
|
||||
const clawHubPreview = workflowJob(PLUGIN_CLAWHUB_RELEASE_WORKFLOW, "preview_plugins_clawhub");
|
||||
expect(clawHubPreview.outputs?.trusted_tooling_identity_json).toBe(
|
||||
"${{ steps.tooling_identity.outputs.json }}",
|
||||
);
|
||||
const toolingIdentity = workflowStep(clawHubPreview, "Capture trusted tooling identity");
|
||||
expect(toolingIdentity.env).toMatchObject({
|
||||
CALLER_FULL_REF: "${{ github.ref }}",
|
||||
CALLER_REF: "${{ github.ref_name }}",
|
||||
CALLER_RUN_ATTEMPT: "${{ github.run_attempt }}",
|
||||
CALLER_RUN_ID: "${{ github.run_id }}",
|
||||
CALLER_SHA: "${{ github.sha }}",
|
||||
PARENT_RUN_ATTEMPT: "${{ inputs.release_publish_run_attempt }}",
|
||||
PARENT_RUN_ID: "${{ inputs.release_publish_run_id }}",
|
||||
PARENT_STATE_POLICY:
|
||||
"${{ inputs.release_publish_run_id != '' && (github.actor == 'github-actions[bot]' && 'active-or-success' || 'recovery-active-or-success-or-failure') || '' }}",
|
||||
TOOLING_FULL_REF: "${{ inputs.release_publish_full_ref }}",
|
||||
TOOLING_REF: "${{ inputs.release_publish_branch }}",
|
||||
TOOLING_SHA: "${{ inputs.release_publish_workflow_sha }}",
|
||||
});
|
||||
for (const field of [
|
||||
"version: 2",
|
||||
"repository: $repository",
|
||||
"workflow: $workflow",
|
||||
"runId: $runId",
|
||||
"runAttempt: $runAttempt",
|
||||
"ref: $ref",
|
||||
"fullRef: $fullRef",
|
||||
"sha: $sha",
|
||||
"toolingRef: $toolingRef",
|
||||
"toolingFullRef: $toolingFullRef",
|
||||
"toolingSha: $toolingSha",
|
||||
"parentRepository: $parentRepository",
|
||||
"parentWorkflow: $parentWorkflow",
|
||||
"parentRunId: $parentRunId",
|
||||
"parentRunAttempt: $parentRunAttempt",
|
||||
"parentRef: $parentRef",
|
||||
"parentFullRef: $parentFullRef",
|
||||
"parentSha: $parentSha",
|
||||
"parentStatePolicy: $parentStatePolicy",
|
||||
]) {
|
||||
expect(toolingIdentity.run).toContain(field);
|
||||
}
|
||||
expect(toolingIdentity.run).toContain(
|
||||
"Trusted release parent run id, attempt, and state policy must be provided together.",
|
||||
);
|
||||
expect(publishOrchestration.env?.PARENT_WORKFLOW_FULL_REF).toBe("${{ github.ref }}");
|
||||
expect(publishOrchestration.run).toContain(
|
||||
'-f release_publish_full_ref="${PARENT_WORKFLOW_FULL_REF}"',
|
||||
);
|
||||
expect(publishOrchestration.run).toContain(
|
||||
'-f release_publish_workflow_sha="${PARENT_WORKFLOW_SHA}"',
|
||||
);
|
||||
expect(publishOrchestration.run).toContain(
|
||||
'-f release_publish_run_attempt="${GITHUB_RUN_ATTEMPT}"',
|
||||
);
|
||||
expect(
|
||||
readWorkflow(PLUGIN_CLAWHUB_RELEASE_WORKFLOW).on?.workflow_dispatch?.inputs
|
||||
?.release_publish_run_attempt,
|
||||
).toMatchObject({ required: false, type: "string" });
|
||||
const oidcSourceValidation = workflowStep(
|
||||
clawHubPreview,
|
||||
"Validate OIDC source matches workflow ref",
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
readWorkflow(PLUGIN_CLAWHUB_RELEASE_WORKFLOW).on?.workflow_dispatch?.inputs
|
||||
?.release_publish_full_ref,
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
readWorkflow(PLUGIN_CLAWHUB_RELEASE_WORKFLOW).on?.workflow_dispatch?.inputs
|
||||
?.release_publish_workflow_sha,
|
||||
).toBeUndefined();
|
||||
expect(clawHubPreview.outputs?.trusted_tooling_identity_json).toBeUndefined();
|
||||
const publishOrchestration = workflowStep(releasePublishJob, "Dispatch publish workflows");
|
||||
expect(publishOrchestration.env?.PARENT_WORKFLOW_FULL_REF).toBeUndefined();
|
||||
expect(publishOrchestration.run).toContain(
|
||||
'wait_for_run_background plugin-clawhub-release.yml "${plugin_clawhub_run_id}" "${TARGET_SHA}"',
|
||||
);
|
||||
expectTextToIncludeAll(oidcSourceValidation.run, [
|
||||
"Split-ref ClawHub publication requires ref to be the exact candidate SHA.",
|
||||
"Split-ref ClawHub publication tooling identity does not match the executing workflow.",
|
||||
"Split-ref ClawHub publication requires the exact parent run id and attempt.",
|
||||
]);
|
||||
const clawHubPlanSource = readFileSync("scripts/lib/openclaw-release-clawhub-plan.ts", "utf8");
|
||||
expect(clawHubPlanSource).toContain("clawHubWorkflowRef: bootstrapWorkflowRef");
|
||||
expect(clawHubPlanSource).toMatch(
|
||||
/normal: createDispatchTarget\(\{[\s\S]*?ref: bootstrapWorkflowRef,[\s\S]*?targetRef: releaseSha,/u,
|
||||
);
|
||||
const frozenCandidateWorkflow = parse(
|
||||
execFileSync("git", ["show", "2d25f59b4a5:.github/workflows/plugin-clawhub-release.yml"], {
|
||||
encoding: "utf8",
|
||||
}),
|
||||
) as Workflow;
|
||||
expect(
|
||||
frozenCandidateWorkflow.on?.workflow_dispatch?.inputs?.release_publish_full_ref,
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
frozenCandidateWorkflow.on?.workflow_dispatch?.inputs?.release_publish_workflow_sha,
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
frozenCandidateWorkflow.on?.workflow_dispatch?.inputs?.release_publish_run_attempt,
|
||||
).toBeUndefined();
|
||||
expect(publishOrchestration.run).not.toContain("release_publish_full_ref");
|
||||
expect(publishOrchestration.run).not.toContain("release_publish_workflow_sha");
|
||||
expect(clawHubBootstrapValidation.environment).toBe("clawhub-plugin-bootstrap");
|
||||
expect(clawHubBootstrapPublish.environment).toBe("clawhub-plugin-bootstrap");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user