From d9c9eeb8cdbba81ac1f2d9563aa4adf55ab6899e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 19 Jul 2026 14:45:56 +0100 Subject: [PATCH] fix(ci): resolve manual protocol baseline --- .github/workflows/ci.yml | 70 +++++++++++++++++++------ test/scripts/ci-workflow-guards.test.ts | 18 +++++++ 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a22b392f3896..ebf82f3dc59d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1429,10 +1429,37 @@ jobs: sticky-disk: ${{ github.event_name != 'workflow_dispatch' && github.repository == 'openclaw/openclaw' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'openclaw/openclaw') && 'true' || 'false' }} use-actions-cache: ${{ github.event_name != 'workflow_dispatch' && github.repository == 'openclaw/openclaw' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'openclaw/openclaw') && 'false' || 'true' }} + - name: Resolve manual protocol base + id: protocol_manual_base + if: matrix.task == 'bundled-protocol' && github.event_name == 'workflow_dispatch' && !inputs.release_gate + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_TOKEN: ${{ github.token }} + TARGET_SHA: ${{ needs.preflight.outputs.checkout_revision }} + shell: bash + run: | + set -euo pipefail + default_sha="$(git ls-remote origin "refs/heads/${DEFAULT_BRANCH}" | awk 'NR == 1 { print $1 }')" + if [[ ! "$default_sha" =~ ^[0-9a-f]{40}$ ]]; then + echo "Could not resolve the default branch head for the manual protocol target." >&2 + exit 1 + fi + merge_base_sha="$( + gh api --method GET \ + "repos/${GITHUB_REPOSITORY}/compare/${default_sha}...${TARGET_SHA}" \ + --jq '.merge_base_commit.sha' + )" + if [[ ! "$merge_base_sha" =~ ^[0-9a-f]{40}$ ]]; then + echo "Could not resolve the manual protocol target merge base." >&2 + exit 1 + fi + echo "sha=${merge_base_sha}" >> "$GITHUB_OUTPUT" + - name: Run ${{ matrix.task }} (${{ matrix.runtime }}) env: GH_TOKEN: ${{ matrix.task == 'max-lines-ratchet' && github.token || '' }} OPENCLAW_TEST_PROJECTS_PARALLEL: 3 + PROTOCOL_MANUAL_BASE_SHA: ${{ steps.protocol_manual_base.outputs.sha }} PROTOCOL_SINCE_BASE_SHA: ${{ needs.preflight.outputs.diff_base_revision }} RATCHET_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} RATCHET_EVENT_BASE_SHA: ${{ github.event_name == 'push' && github.event.before || '' }} @@ -1448,12 +1475,37 @@ jobs: process.exit(Object.hasOwn(scripts, process.argv[1]) ? 0 : 1); ' "$1" } + resolve_manual_merge_base() { + local default_branch="${RATCHET_DEFAULT_BRANCH:-main}" + local default_sha + local merge_base_sha + default_sha="$(git ls-remote origin "refs/heads/${default_branch}" | awk 'NR == 1 { print $1 }')" + if [[ ! "$default_sha" =~ ^[0-9a-f]{40}$ ]]; then + echo "Could not resolve the default branch head for the manual target." >&2 + return 1 + fi + merge_base_sha="$( + gh api --method GET \ + "repos/${GITHUB_REPOSITORY}/compare/${default_sha}...${RATCHET_MANUAL_TARGET_SHA}" \ + --jq '.merge_base_commit.sha' + )" + if [[ ! "$merge_base_sha" =~ ^[0-9a-f]{40}$ ]]; then + echo "Could not resolve the manual target merge base." >&2 + return 1 + fi + printf '%s\n' "$merge_base_sha" + } case "$TASK" in bundled-protocol) pnpm test:bundled if [[ -n "${PROTOCOL_SINCE_BASE_SHA:-}" ]]; then git fetch --no-tags --no-recurse-submodules --depth=1 origin \ "+${PROTOCOL_SINCE_BASE_SHA}:refs/remotes/origin/protocol-since-base" + elif [[ -n "${PROTOCOL_MANUAL_BASE_SHA:-}" ]]; then + PROTOCOL_SINCE_BASE_SHA="$PROTOCOL_MANUAL_BASE_SHA" + export PROTOCOL_SINCE_BASE_SHA + git fetch --no-tags --no-recurse-submodules --depth=1 origin \ + "+${PROTOCOL_SINCE_BASE_SHA}:refs/remotes/origin/protocol-since-base" else git fetch --no-tags --no-recurse-submodules --depth=1 origin \ "+refs/heads/main:refs/remotes/origin/main" @@ -1492,23 +1544,7 @@ jobs: "+${base_sha}:refs/remotes/origin/ci-max-lines-base" base_ref="refs/remotes/origin/ci-max-lines-base" elif [[ -n "${RATCHET_MANUAL_TARGET_SHA:-}" ]]; then - default_branch="${RATCHET_DEFAULT_BRANCH:-main}" - default_sha="$( - git ls-remote origin "refs/heads/${default_branch}" | awk 'NR == 1 { print $1 }' - )" - if [[ ! "$default_sha" =~ ^[0-9a-f]{40}$ ]]; then - echo "Could not resolve the default branch head for the max-lines ratchet." >&2 - exit 1 - fi - merge_base_sha="$( - gh api --method GET \ - "repos/${GITHUB_REPOSITORY}/compare/${default_sha}...${RATCHET_MANUAL_TARGET_SHA}" \ - --jq '.merge_base_commit.sha' - )" - if [[ ! "$merge_base_sha" =~ ^[0-9a-f]{40}$ ]]; then - echo "Could not resolve the manual target merge base for the max-lines ratchet." >&2 - exit 1 - fi + merge_base_sha="$(resolve_manual_merge_base)" timeout --signal=TERM --kill-after=10s 120s git fetch --no-tags --depth=1 origin \ "+${merge_base_sha}:refs/remotes/origin/ci-max-lines-base" base_ref="refs/remotes/origin/ci-max-lines-base" diff --git a/test/scripts/ci-workflow-guards.test.ts b/test/scripts/ci-workflow-guards.test.ts index 9dc11419fd4f..41110c59bb1d 100644 --- a/test/scripts/ci-workflow-guards.test.ts +++ b/test/scripts/ci-workflow-guards.test.ts @@ -3556,6 +3556,9 @@ printf '%s\n' "\${CURL_SUCCESS_IP:-203.0.113.7}" const releaseGateMerge = checksFastSteps.find( (step: WorkflowStep) => step.name === "Prepare release-gate max-lines merge tree", ); + const protocolManualBase = checksFastSteps.find( + (step: WorkflowStep) => step.name === "Resolve manual protocol base", + ); expect(workflow.jobs["checks-fast-core"].permissions).toEqual({ contents: "read", @@ -3578,6 +3581,17 @@ printf '%s\n' "\${CURL_SUCCESS_IP:-203.0.113.7}" expect(checksFastRun.env.GH_TOKEN).toBe( "${{ matrix.task == 'max-lines-ratchet' && github.token || '' }}", ); + expect(protocolManualBase.if).toBe( + "matrix.task == 'bundled-protocol' && github.event_name == 'workflow_dispatch' && !inputs.release_gate", + ); + expect(protocolManualBase.env.GH_TOKEN).toBe("${{ github.token }}"); + expect(protocolManualBase.run).toContain( + '"repos/${GITHUB_REPOSITORY}/compare/${default_sha}...${TARGET_SHA}"', + ); + expect(protocolManualBase.run).toContain('echo "sha=${merge_base_sha}" >> "$GITHUB_OUTPUT"'); + expect(checksFastRun.env.PROTOCOL_MANUAL_BASE_SHA).toBe( + "${{ steps.protocol_manual_base.outputs.sha }}", + ); expect(releaseGateMerge.run).toContain( 'gh api --method GET "repos/${GITHUB_REPOSITORY}/pulls/${PULL_REQUEST_NUMBER}"', ); @@ -3619,6 +3633,10 @@ printf '%s\n' "\${CURL_SUCCESS_IP:-203.0.113.7}" expect(checksFastRun.run).toContain( '"repos/${GITHUB_REPOSITORY}/compare/${default_sha}...${RATCHET_MANUAL_TARGET_SHA}"', ); + expect(checksFastRun.run).toContain('PROTOCOL_SINCE_BASE_SHA="$PROTOCOL_MANUAL_BASE_SHA"'); + expect(checksFastRun.run).toContain( + '"+${PROTOCOL_SINCE_BASE_SHA}:refs/remotes/origin/protocol-since-base"', + ); expect(checksFastRun.run).toContain("--jq '.merge_base_commit.sha'"); expect(checksFastRun.run).toContain( '"+${merge_base_sha}:refs/remotes/origin/ci-max-lines-base"',