diff --git a/CHANGELOG.md b/CHANGELOG.md index d2aad1dea42..fbd7e71311d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Maintainer workflow: push prepared PR heads through GitHub's verified commit API by default and require an explicit override before git-protocol pushes can publish unsigned commits. Thanks @BunsDev. - Gateway/responses: emit every client tool call from `/v1/responses` JSON and SSE responses when the agent invokes multiple client tools in a single turn, so multi-tool plans, graph orchestration calls, and similar batched flows no longer drop every call but the last. Fixes #52288. Thanks @CharZhou and @bonelli. - Slack/reactions: treat missing no_reaction remove responses as idempotent success and route own-reaction cleanup through the remove helper, so concurrent cleanup no longer surfaces Slack race errors. Fixes #50733. (#76304) Thanks @martingarramon and @Hollychou924. - Control UI/Gateway: avoid full session-list reloads for locally applied message-phase session updates, carry known session keys through transcript-file update events, and defer media provider listing when explicit generation model config is present. Refs #76236, #76203, #76188, #76107, and #76166. Thanks @BunsDev. diff --git a/scripts/pr-lib/push.sh b/scripts/pr-lib/push.sh index 34075207a76..ed2b4cf4566 100644 --- a/scripts/pr-lib/push.sh +++ b/scripts/pr-lib/push.sh @@ -202,6 +202,27 @@ resolve_prhead_remote_sha() { printf '%s\n' "$remote_sha" } +push_prep_head_once() { + local pr_head="$1" + local lease_sha="$2" + local prep_head_sha="$3" + + if [ -n "${PR_HEAD_OWNER:-}" ] && [ -n "${PR_HEAD_REPO_NAME:-}" ] && [ "${OPENCLAW_PR_PUSH_MODE:-graphql}" != "git" ]; then + echo "Pushing PR branch through GitHub createCommitOnBranch so the prepared commit is verified." >&2 + graphql_push_to_fork "${PR_HEAD_OWNER}/${PR_HEAD_REPO_NAME}" "$pr_head" "$lease_sha" + return $? + fi + + if [ "${OPENCLAW_ALLOW_UNSIGNED_GIT_PUSH:-}" != "1" ]; then + echo "Refusing git-protocol PR branch push because it can publish unsigned commits." >&2 + echo "Use the default GitHub createCommitOnBranch path, or set OPENCLAW_ALLOW_UNSIGNED_GIT_PUSH=1 for an explicit manual override." >&2 + return 2 + fi + + git push --force-with-lease=refs/heads/$pr_head:$lease_sha prhead HEAD:$pr_head >&2 + printf '%s\n' "$prep_head_sha" +} + push_prep_head_to_pr_branch() { local pr="$1" local pr_head="$2" @@ -226,9 +247,7 @@ push_prep_head_to_pr_branch() { fi pushed_from_sha="$lease_sha" local push_output - if ! push_output=$( - git push --force-with-lease=refs/heads/$pr_head:$lease_sha prhead HEAD:$pr_head 2>&1 - ); then + if ! push_output=$(push_prep_head_once "$pr_head" "$lease_sha" "$prep_head_sha" 2>&1); then echo "Push failed: $push_output" if printf '%s' "$push_output" | grep -qiE '(permission|denied|403|forbidden)'; then @@ -253,9 +272,7 @@ push_prep_head_to_pr_branch() { run_prepare_push_retry_gates "$docs_only" fi - if ! push_output=$( - git push --force-with-lease=refs/heads/$pr_head:$lease_sha prhead HEAD:$pr_head 2>&1 - ); then + if ! push_output=$(push_prep_head_once "$pr_head" "$lease_sha" "$prep_head_sha" 2>&1); then echo "Retry push failed: $push_output" if [ -n "${PR_HEAD_OWNER:-}" ] && [ -n "${PR_HEAD_REPO_NAME:-}" ]; then echo "Retry failed; trying GraphQL createCommitOnBranch fallback..." @@ -266,8 +283,12 @@ push_prep_head_to_pr_branch() { echo "Git push failed and no fork owner/repo info for GraphQL fallback." exit 1 fi + else + prep_head_sha=$(printf '%s\n' "$push_output" | tail -n 1) fi fi + else + prep_head_sha=$(printf '%s\n' "$push_output" | tail -n 1) fi fi