From 879acd96d137927983dc9f2672a4769feb2d18d6 Mon Sep 17 00:00:00 2001 From: hongming-codex-laptop Date: Wed, 13 May 2026 13:58:18 -0700 Subject: [PATCH 1/2] fix(ci): skip main gates for non-default-base prs --- .gitea/scripts/review-check.sh | 11 ++++-- .gitea/scripts/tests/_review_check_fixture.py | 3 ++ .gitea/scripts/tests/test_review_check.sh | 21 +++++++++--- .gitea/workflows/gate-check-v3.yml | 2 ++ .gitea/workflows/qa-review.yml | 1 + .gitea/workflows/security-review.yml | 1 + tools/gate-check-v3/gate_check.py | 15 ++++++++ tools/gate-check-v3/test_gate_check.py | 34 +++++++++++++++++++ 8 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 tools/gate-check-v3/test_gate_check.py diff --git a/.gitea/scripts/review-check.sh b/.gitea/scripts/review-check.sh index b946b172..24a6e94e 100755 --- a/.gitea/scripts/review-check.sh +++ b/.gitea/scripts/review-check.sh @@ -60,6 +60,7 @@ # Optional: # REVIEW_CHECK_DEBUG=1 — per-API-call diagnostic lines # REVIEW_CHECK_STRICT=1 — also require review.commit_id == pr.head.sha +# DEFAULT_BRANCH=main — branch this gate protects; non-default-base PRs no-op set -euo pipefail @@ -91,7 +92,7 @@ API="https://${GITEA_HOST}/api/v1" # secret token value in the process table for any process to read via # /proc//cmdline or ps -ef). The curl config file is read by curl # itself and never appears in the argv of the curl subprocess. -CURL_AUTH_FILE=$(mktemp -p /tmp curl-auth.XXXXXX) +CURL_AUTH_FILE=$(mktemp "${TMPDIR:-/tmp}/curl-auth.XXXXXX") chmod 600 "$CURL_AUTH_FILE" printf 'header = "Authorization: token %s"\n' "$GITEA_TOKEN" > "$CURL_AUTH_FILE" @@ -124,13 +125,19 @@ if [ "$HTTP_CODE" != "200" ]; then fi PR_AUTHOR=$(jq -r '.user.login // ""' "$PR_JSON") PR_HEAD_SHA=$(jq -r '.head.sha // ""' "$PR_JSON") +PR_BASE_REF=$(jq -r '.base.ref // ""' "$PR_JSON") PR_STATE=$(jq -r '.state // ""' "$PR_JSON") -debug "pr_author=${PR_AUTHOR} pr_head=${PR_HEAD_SHA:0:7} pr_state=${PR_STATE}" +DEFAULT_BRANCH="${DEFAULT_BRANCH:-main}" +debug "pr_author=${PR_AUTHOR} pr_head=${PR_HEAD_SHA:0:7} pr_base=${PR_BASE_REF} pr_state=${PR_STATE}" if [ "$PR_STATE" != "open" ]; then echo "::notice::PR ${PR_NUMBER} is ${PR_STATE} — exiting 0 (closed PRs do not gate)" exit 0 fi +if [ "$PR_BASE_REF" != "$DEFAULT_BRANCH" ]; then + echo "::notice::PR ${PR_NUMBER} targets ${PR_BASE_REF:-} not ${DEFAULT_BRANCH} — ${TEAM}-review gate not applicable" + exit 0 +fi if [ -z "$PR_AUTHOR" ] || [ -z "$PR_HEAD_SHA" ]; then echo "::error::PR ${PR_NUMBER} missing user.login or head.sha — webhook payload malformed" exit 1 diff --git a/.gitea/scripts/tests/_review_check_fixture.py b/.gitea/scripts/tests/_review_check_fixture.py index e48a70c2..51cc423f 100644 --- a/.gitea/scripts/tests/_review_check_fixture.py +++ b/.gitea/scripts/tests/_review_check_fixture.py @@ -16,6 +16,7 @@ Scenarios: T7_team_member — team membership → 204 (member) → exit 0 T8_team_not_member — team membership → 404 (not a member) → exit 1 T9_team_403 — team membership → 403 (token not in team) → exit 1 + T14_non_default_base — open PR targeting staging → script exits 0 (no-op) Usage: FIXTURE_STATE_DIR=/tmp/x python3 _review_check_fixture.py 8080 @@ -82,12 +83,14 @@ class Handler(http.server.BaseHTTPRequestHandler): "number": int(pr_num), "state": "closed", "head": {"sha": "deadbeef0000111122223333444455556666"}, + "base": {"ref": "main"}, "user": {"login": "alice"}, }) return self._json(200, { "number": int(pr_num), "state": "open", "head": {"sha": "deadbeef0000111122223333444455556666"}, + "base": {"ref": "staging" if sc == "T14_non_default_base" else "main"}, "user": {"login": "alice"}, }) diff --git a/.gitea/scripts/tests/test_review_check.sh b/.gitea/scripts/tests/test_review_check.sh index 793089b5..ed6169bf 100755 --- a/.gitea/scripts/tests/test_review_check.sh +++ b/.gitea/scripts/tests/test_review_check.sh @@ -15,6 +15,7 @@ # T11 — bash syntax check (bash -n passes) # T12 — jq filter: non-author APPROVED → in candidate list; dismissed → excluded # T13 — missing required env GITEA_TOKEN → exits 1 with error +# T14 — non-default-base PR exits 0 without requiring review # # Hostile-self-review (per feedback_assert_exact_not_substring): # this test MUST FAIL if the script is absent. Verified by running @@ -73,7 +74,7 @@ assert_file_mode() { return fi local got_mode - got_mode=$(stat -c '%a' "$path" 2>/dev/null || echo "000") + got_mode=$(stat -c '%a' "$path" 2>/dev/null || stat -f '%Lp' "$path" 2>/dev/null || echo "000") if [ "$expected_mode" = "$got_mode" ]; then echo " PASS $label (mode=$got_mode)" PASS=$((PASS + 1)) @@ -194,8 +195,9 @@ for a in "$@"; do done exec /usr/bin/curl "${new_args[@]}" CURL_SHIM -# Now substitute FIXPORT with the actual port number -sed -i "s/FIXPORT/${FIX_PORT}/g" "$FIXTURE_DIR/bin/curl" +# Now substitute FIXPORT with the actual port number. Use perl rather than +# sed -i so the test runs on both GNU sed and BSD/macOS sed. +perl -0pi -e "s/FIXPORT/${FIX_PORT}/g" "$FIXTURE_DIR/bin/curl" chmod +x "$FIXTURE_DIR/bin/curl" # Helper: run the script with fixture environment @@ -210,6 +212,7 @@ run_review_check() { GITEA_HOST="fixture.local" \ REPO="molecule-ai/molecule-core" \ PR_NUMBER="999" \ + DEFAULT_BRANCH="main" \ TEAM="qa" \ TEAM_ID="20" \ REVIEW_CHECK_DEBUG="0" \ @@ -253,6 +256,14 @@ T4_RC=$(cat "$FIX_STATE_DIR/last_rc") assert_eq "T4 exit code 1 (no candidates)" "1" "$T4_RC" assert_contains "T4 awaiting non-author APPROVE" "awaiting non-author APPROVE" "$T4_OUT" +# T14 — non-default-base PR should not make the default branch red. +echo +echo "== T14 non-default base PR ==" +T14_OUT=$(run_review_check "T14_non_default_base") +T14_RC=$(cat "$FIX_STATE_DIR/last_rc") +assert_eq "T14 exit code 0 (non-default base no-op)" "0" "$T14_RC" +assert_contains "T14 not applicable notice" "gate not applicable" "$T14_OUT" + # T5 — only author reviews → exit 1 echo echo "== T5 only author reviews ==" @@ -296,10 +307,10 @@ echo "== T10 CURL_AUTH_FILE ==" # Verify the token-file logic directly: create a temp file with the # same mktemp pattern, write the header with printf, chmod 600, then assert. T10_TOKEN="secret-test-token-abc123" -T10_AUTHFILE=$(mktemp -p /tmp curl-auth.test.XXXXXX) +T10_AUTHFILE=$(mktemp "${TMPDIR:-/tmp}/curl-auth.test.XXXXXX") chmod 600 "$T10_AUTHFILE" printf 'header = "Authorization: token %s"\n' "$T10_TOKEN" > "$T10_AUTHFILE" -assert_file_mode "T10a mktemp -p /tmp mode 600 (CURL_AUTH_FILE pattern)" "$T10_AUTHFILE" "600" +assert_file_mode "T10a mktemp authfile mode 600 (CURL_AUTH_FILE pattern)" "$T10_AUTHFILE" "600" assert_file_contains "T10b printf header format (CURL_AUTH_FILE content)" "$T10_AUTHFILE" "Authorization: token secret-test-token-abc123" assert_file_contains "T10c 'header =' curl-config syntax" "$T10_AUTHFILE" 'header = "Authorization: token ' rm -f "$T10_AUTHFILE" diff --git a/.gitea/workflows/gate-check-v3.yml b/.gitea/workflows/gate-check-v3.yml index 71641320..b1175977 100644 --- a/.gitea/workflows/gate-check-v3.yml +++ b/.gitea/workflows/gate-check-v3.yml @@ -64,6 +64,7 @@ jobs: if: github.event_name == 'pull_request_target' || github.event.inputs.pr_number != '' env: GITEA_TOKEN: ${{ secrets.SOP_TIER_CHECK_TOKEN || secrets.GITHUB_TOKEN }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }} POST_COMMENT: ${{ github.event.inputs.post_comment || 'true' }} run: | @@ -78,6 +79,7 @@ jobs: if: github.event_name == 'schedule' env: GITEA_TOKEN: ${{ secrets.SOP_TIER_CHECK_TOKEN || secrets.GITHUB_TOKEN }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} REPO: ${{ github.repository }} run: | set -euo pipefail diff --git a/.gitea/workflows/qa-review.yml b/.gitea/workflows/qa-review.yml index 005b7474..c9360706 100644 --- a/.gitea/workflows/qa-review.yml +++ b/.gitea/workflows/qa-review.yml @@ -158,6 +158,7 @@ jobs: # pull_request_target → github.event.pull_request.number # issue_comment → github.event.issue.number PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} TEAM: qa TEAM_ID: '20' REVIEW_CHECK_DEBUG: '0' diff --git a/.gitea/workflows/security-review.yml b/.gitea/workflows/security-review.yml index 3b893cb0..6e5a1844 100644 --- a/.gitea/workflows/security-review.yml +++ b/.gitea/workflows/security-review.yml @@ -66,6 +66,7 @@ jobs: GITEA_HOST: git.moleculesai.app REPO: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} TEAM: security TEAM_ID: '21' REVIEW_CHECK_DEBUG: '0' diff --git a/tools/gate-check-v3/gate_check.py b/tools/gate-check-v3/gate_check.py index 5bff579a..963a8ab4 100644 --- a/tools/gate-check-v3/gate_check.py +++ b/tools/gate-check-v3/gate_check.py @@ -488,6 +488,21 @@ def run(repo: str, pr_number: int, post_comment: bool = False) -> dict: owner, name = repo.split("/", 1) pr = api_get(f"/repos/{owner}/{name}/pulls/{pr_number}") base_ref = pr.get("base", {}).get("ref", "main") + default_branch = os.environ.get("DEFAULT_BRANCH", "main") + if base_ref != default_branch: + result = { + "verdict": "CLEAR", + "repo": repo, + "pr": pr_number, + "skipped": True, + "reason": ( + f"PR targets {base_ref}, not protected default branch " + f"{default_branch}" + ), + "timestamp": datetime.now(timezone.utc).isoformat(), + } + print(json.dumps(result, indent=2)) + return result gates = [ signal_1_comment_scan(pr_number, repo), diff --git a/tools/gate-check-v3/test_gate_check.py b/tools/gate-check-v3/test_gate_check.py new file mode 100644 index 00000000..f27e2be8 --- /dev/null +++ b/tools/gate-check-v3/test_gate_check.py @@ -0,0 +1,34 @@ +import importlib.util +import pathlib + + +SCRIPT = pathlib.Path(__file__).with_name("gate_check.py") + + +def load_gate_check(): + spec = importlib.util.spec_from_file_location("gate_check", SCRIPT) + mod = importlib.util.module_from_spec(spec) + assert spec.loader is not None + spec.loader.exec_module(mod) + return mod + + +def test_run_skips_pr_not_targeting_default_branch(monkeypatch): + mod = load_gate_check() + + def fake_api_get(path): + assert path == "/repos/molecule-ai/molecule-core/pulls/843" + return { + "number": 843, + "base": {"ref": "staging"}, + "head": {"sha": "84b9ca3a129075b8d5159eda5e678f68be1af20f"}, + } + + monkeypatch.setenv("DEFAULT_BRANCH", "main") + monkeypatch.setattr(mod, "api_get", fake_api_get) + + result = mod.run("molecule-ai/molecule-core", 843, post_comment=False) + + assert result["verdict"] == "CLEAR" + assert result["skipped"] is True + assert "staging" in result["reason"] -- 2.45.2 From 5043532d30b272337c699ab5103432304a1ef0eb Mon Sep 17 00:00:00 2001 From: hongming-codex-laptop Date: Wed, 13 May 2026 14:10:28 -0700 Subject: [PATCH 2/2] fix(go): remove ineffectual pgplugin index increment --- workspace-server/internal/memory/pgplugin/store.go | 1 - 1 file changed, 1 deletion(-) diff --git a/workspace-server/internal/memory/pgplugin/store.go b/workspace-server/internal/memory/pgplugin/store.go index c00c0112..3bb6ad2a 100644 --- a/workspace-server/internal/memory/pgplugin/store.go +++ b/workspace-server/internal/memory/pgplugin/store.go @@ -80,7 +80,6 @@ func (s *Store) PatchNamespace(ctx context.Context, name string, body contract.N } parts = append(parts, fmt.Sprintf("metadata = $%d", idx)) args = append(args, metadata) - idx++ // advance so subsequent fields (if any) get correct positional index } query := fmt.Sprintf(` UPDATE memory_namespaces SET %s -- 2.45.2