From 1c2fb9c745a34d8ee517638f1ce1613b85bbaf71 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Thu, 20 Aug 2026 23:47:04 -0700 Subject: [PATCH] fix(release): keep protected tooling foundation npm-only --- .../workflows/openclaw-release-publish.yml | 12 +- .github/workflows/plugin-clawhub-release.yml | 123 +--------------- scripts/lib/openclaw-release-clawhub-plan.ts | 8 +- test/plugin-clawhub-release.test.ts | 8 +- .../package-acceptance-workflow.test.ts | 134 +++--------------- 5 files changed, 32 insertions(+), 253 deletions(-) diff --git a/.github/workflows/openclaw-release-publish.yml b/.github/workflows/openclaw-release-publish.yml index c20a4685d21d..b3325d9f32e4 100644 --- a/.github/workflows/openclaw-release-publish.yml +++ b/.github/workflows/openclaw-release-publish.yml @@ -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 diff --git a/.github/workflows/plugin-clawhub-release.yml b/.github/workflows/plugin-clawhub-release.yml index 11edaa6f7f89..142c82687f77 100644 --- a/.github/workflows/plugin-clawhub-release.yml +++ b/.github/workflows/plugin-clawhub-release.yml @@ -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] diff --git a/scripts/lib/openclaw-release-clawhub-plan.ts b/scripts/lib/openclaw-release-clawhub-plan.ts index e3e73c2488d4..a4620b8cc8ca 100644 --- a/scripts/lib/openclaw-release-clawhub-plan.ts +++ b/scripts/lib/openclaw-release-clawhub-plan.ts @@ -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, }, }; } diff --git a/test/plugin-clawhub-release.test.ts b/test/plugin-clawhub-release.test.ts index 47252141bd93..f65e0df6a8e2 100644 --- a/test/plugin-clawhub-release.test.ts +++ b/test/plugin-clawhub-release.test.ts @@ -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", }); }); diff --git a/test/scripts/package-acceptance-workflow.test.ts b/test/scripts/package-acceptance-workflow.test.ts index 29442569c0fc..52badb04603b 100644 --- a/test/scripts/package-acceptance-workflow.test.ts +++ b/test/scripts/package-acceptance-workflow.test.ts @@ -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");