run_prepare_push_retry_gates() { local docs_only="${1:-false}" bootstrap_deps_if_needed run_quiet_logged "pnpm build (lease-retry)" ".local/lease-retry-build.log" pnpm build run_quiet_logged "pnpm check (lease-retry)" ".local/lease-retry-check.log" pnpm check if [ "$docs_only" != "true" ]; then run_quiet_logged "pnpm test (lease-retry)" ".local/lease-retry-test.log" pnpm test fi } prepare_gates() { local pr="$1" enter_worktree "$pr" false checkout_prep_branch "$pr" bootstrap_deps_if_needed require_artifact .local/pr-meta.env # shellcheck disable=SC1091 source .local/pr-meta.env local changed_files changed_files=$(git diff --name-only origin/main...HEAD) local non_docs non_docs=$(printf '%s\n' "$changed_files" | while IFS= read -r path; do [ -n "$path" ] || continue if ! path_is_docsish "$path"; then printf '%s\n' "$path" fi done) local docs_only=false if [ -n "$changed_files" ] && [ -z "$non_docs" ]; then docs_only=true fi local changelog_required=false if changelog_required_for_changed_files "$changed_files"; then changelog_required=true fi local has_changelog_update=false if printf '%s\n' "$changed_files" | rg -q '^CHANGELOG\.md$'; then has_changelog_update=true fi local unsupported_changelog_fragments unsupported_changelog_fragments=$(printf '%s\n' "$changed_files" | rg '^changelog/fragments/' || true) if [ -n "$unsupported_changelog_fragments" ]; then echo "Unsupported changelog fragment files detected:" printf '%s\n' "$unsupported_changelog_fragments" echo "Move changelog fragment content into CHANGELOG.md and remove changelog/fragments files." exit 1 fi if [ "$changelog_required" = "true" ] && [ "$has_changelog_update" = "false" ]; then echo "Missing changelog update. Add CHANGELOG.md changes." exit 1 fi if [ "$has_changelog_update" = "true" ]; then normalize_pr_changelog_entries "$pr" fi if [ "$changelog_required" = "true" ]; then local contrib="${PR_AUTHOR:-}" validate_changelog_merge_hygiene validate_changelog_entry_for_pr "$pr" "$contrib" else echo "Changelog not required for this changed-file set." fi local current_head current_head=$(git rev-parse HEAD) local previous_last_verified_head="" local previous_full_gates_head="" if [ -s .local/gates.env ]; then # shellcheck disable=SC1091 source .local/gates.env previous_last_verified_head="${LAST_VERIFIED_HEAD_SHA:-}" previous_full_gates_head="${FULL_GATES_HEAD_SHA:-}" fi local gates_mode="full" local reuse_gates=false if [ "$docs_only" = "true" ] && [ -n "$previous_last_verified_head" ] && git merge-base --is-ancestor "$previous_last_verified_head" HEAD 2>/dev/null; then local delta_since_verified delta_since_verified=$(git diff --name-only "$previous_last_verified_head"..HEAD) if [ -z "$delta_since_verified" ] || file_list_is_docsish_only "$delta_since_verified"; then reuse_gates=true fi fi if [ "$reuse_gates" = "true" ]; then gates_mode="reused_docs_only" echo "Docs/changelog-only delta since last verified head $previous_last_verified_head; reusing prior gates." else run_quiet_logged "pnpm build" ".local/gates-build.log" pnpm build run_quiet_logged "pnpm check" ".local/gates-check.log" pnpm check if [ "$docs_only" = "true" ]; then gates_mode="docs_only" echo "Docs-only change detected with high confidence; skipping pnpm test." else gates_mode="full" local prepare_unit_fast_batch_target_ms prepare_unit_fast_batch_target_ms="${OPENCLAW_PREPARE_TEST_UNIT_FAST_BATCH_TARGET_MS:-5000}" echo "Running pnpm test with OPENCLAW_TEST_UNIT_FAST_BATCH_TARGET_MS=$prepare_unit_fast_batch_target_ms for shorter-lived unit-fast workers." run_quiet_logged \ "pnpm test" \ ".local/gates-test.log" \ env OPENCLAW_TEST_UNIT_FAST_BATCH_TARGET_MS="$prepare_unit_fast_batch_target_ms" pnpm test previous_full_gates_head="$current_head" fi fi # Security: shell-escape values to prevent command injection when sourced. printf '%s=%q\n' \ PR_NUMBER "$pr" \ DOCS_ONLY "$docs_only" \ CHANGELOG_REQUIRED "$changelog_required" \ GATES_MODE "$gates_mode" \ LAST_VERIFIED_HEAD_SHA "$current_head" \ FULL_GATES_HEAD_SHA "${previous_full_gates_head:-}" \ GATES_PASSED_AT "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ > .local/gates.env echo "docs_only=$docs_only" echo "changelog_required=$changelog_required" echo "gates_mode=$gates_mode" echo "wrote=.local/gates.env" }