Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions ion/propose/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,21 @@ def run_propose(ctx, dry_run: bool = False) -> dict:
if c["kind"] not in ("policy_fix", "health_fix") or json.loads(latest["state"]).get("created_gen") == gen:
info["state"] = f"closed ({latest['status']})"
continue
if c["kind"] == "health_fix":
# A done health_fix means its PR was opened; while that PR still waits for a
# maintainer merge, the finding is being handled. Re-proposing it (seen live:
# P-0014/P-0015 duplicating P-0011/P-0012) is pure tracker noise.
st = json.loads(latest["state"])
pr_n = st.get("pr_number")
if pr_n:
try:
pr = ctx.gh.rest("GET", f"/repos/{cfg.org}/{c['subject']['repo']}/pulls/{int(pr_n)}")
except Exception: # noqa: BLE001 (an unreadable PR never suppresses a finding)
pr = {}
if pr.get("state") == "open" and not pr.get("merged"):
info["state"] = f"suppressed (PR #{int(pr_n)} open)"
res["suppressed"].append(key)
continue
if c["persist"] and not scoring.ready(streak, cfg):
info["state"] = f"waiting ({streak}/{cfg['thresholds']['persist_runs']} runs)"
continue
Expand Down
21 changes: 21 additions & 0 deletions tests/test_propose.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,27 @@ def test_hysteresis_in_engine_then_issue_created(ctx):
assert not ctx.gh.writes_to("POST", "/comments") # never any comment


def test_done_health_fix_with_open_pr_is_not_reproposed(ctx):
analysed(ctx); run_propose(ctx)
run_collect(ctx); run_analyze(ctx); run_propose(ctx)
rows = ctx.db.q("select * from proposals where kind='health_fix'")
assert rows, "the fixture world should produce a health_fix proposal"
p = proposals.view(rows[0])
repo = p["subject"]["repo"]
# the executor finished and its PR is still open, waiting for a maintainer merge
proposals.set_status(ctx.db, p["id"], "done")
ctx.db.set_state(p["id"], pr_number=41)
run_collect(ctx); run_analyze(ctx)
r = run_propose(ctx)
assert len(ctx.db.q("select 1 from proposals where kind='health_fix'")) == len(rows)
assert any("open" in str(c.get("state")) for c in r["candidates"]
if c["key"] == p["key"]), r["candidates"]
# once that PR is no longer open, a later generation may propose again
ctx.gh.merged.add((repo, 41))
run_collect(ctx); run_analyze(ctx); run_propose(ctx)
assert len(ctx.db.q("select 1 from proposals where kind='health_fix'")) > len(rows)


def test_dry_run_writes_nothing(ctx):
analysed(ctx)
before = len(ctx.gh.writes)
Expand Down
Loading