Test PR not targeting main #22
@@ -154,6 +154,22 @@ jobs:
|
||||
blocking = [f for f in findings if f["severity"] in policy["block_on"] and f["confidence"] >= policy["min_confidence"]]
|
||||
blocked = len(blocking) > 0
|
||||
|
||||
# Один и тот же коммит может быть провёрен дважды (см. баг
|
||||
# Gitea с переиспользованием SHA между разными PR — два
|
||||
# параллельных прогона на идентичный коммит). Статус в
|
||||
# Gitea хранит только ПОСЛЕДНЮЮ запись по (sha, context),
|
||||
# так что более поздний, но менее строгий результат тихо
|
||||
# затирает более ранний блокирующий. Раз уже была
|
||||
# зафиксирована блокировка на этом коммите — не снимаем
|
||||
# её молча, только новым коммитом.
|
||||
prior_failed = False
|
||||
try:
|
||||
prior = gitea("GET", f"/repos/{REPO}/commits/{COMMIT_SHA}/statuses")
|
||||
prior_failed = any(s.get("context") == "security/scan" and s.get("status") == "failure" for s in prior)
|
||||
except Exception as e:
|
||||
print(f"не удалось прочитать прежние статусы, продолжаю без sticky-fail: {e}")
|
||||
sticky = prior_failed and not blocked
|
||||
|
||||
outdir = f"security-analysis/findings/pr-{PR_NUMBER or 'manual'}"
|
||||
os.makedirs(outdir, exist_ok=True)
|
||||
outpath = f"{outdir}/{int(time.time())}.json"
|
||||
@@ -177,19 +193,22 @@ jobs:
|
||||
for f in top:
|
||||
body += f"**{f['severity'].upper()}** `{f['file']}:{f['line_start']}` — {f['title']} ({f['source']})\n\n"
|
||||
body += f"Полный список: `{outpath}`\n\n"
|
||||
if sticky:
|
||||
body += "🔴 **Merge заблокирован** — этот же коммит уже был помечен как блокирующий в более раннем прогоне; новый прогон нашёл меньше, но старую блокировку это не снимает (нужен новый коммит).\n"
|
||||
else:
|
||||
body += "🔴 **Merge заблокирован** — есть находки выше порога `security-analysis/policy.yml`.\n" if blocked else "✅ Порог не превышен.\n"
|
||||
|
||||
gitea("POST", f"/repos/{REPO}/issues/{PR_NUMBER}/comments", {"body": body})
|
||||
|
||||
gitea("POST", f"/repos/{REPO}/statuses/{COMMIT_SHA}", {
|
||||
"state": "failure" if blocked else "success",
|
||||
"state": "failure" if (blocked or sticky) else "success",
|
||||
"context": "security/scan",
|
||||
"description": f"{len(findings)} findings, {len(blocking)} blocking",
|
||||
"description": (f"{len(findings)} findings, {len(blocking)} blocking" + (" (sticky: prior run flagged this commit)" if sticky else "")),
|
||||
"target_url": f"{SERVER}/{REPO}/src/branch/{HEAD_REF}/{outpath}",
|
||||
})
|
||||
|
||||
print(f"findings: {len(findings)}, blocking: {len(blocking)}")
|
||||
if blocked:
|
||||
print(f"findings: {len(findings)}, blocking: {len(blocking)}, sticky: {sticky}")
|
||||
if blocked or sticky:
|
||||
sys.exit(1)
|
||||
PYEOF
|
||||
|
||||
@@ -440,6 +459,20 @@ jobs:
|
||||
blocking = [f for f in findings if f["severity"] in policy["block_on"] and f["confidence"] >= policy["min_confidence"]]
|
||||
blocked = len(blocking) > 0
|
||||
|
||||
# См. аналогичный комментарий в шаге scan: LLM-ревьюер не
|
||||
# детерминирован, а один коммит может быть провёрен дважды
|
||||
# параллельно (баг Gitea с переиспользованием SHA между
|
||||
# PR). Если более ранний прогон на ЭТОМ ЖЕ коммите уже
|
||||
# нашёл блокирующую находку, более поздний "пустой" ответ
|
||||
# модели не должен тихо снимать блокировку.
|
||||
prior_failed = False
|
||||
try:
|
||||
prior = gitea("GET", f"/repos/{REPO}/commits/{COMMIT_SHA}/statuses")
|
||||
prior_failed = any(s.get("context") == "security/review" and s.get("status") == "failure" for s in prior)
|
||||
except Exception as e:
|
||||
print(f"не удалось прочитать прежние статусы, продолжаю без sticky-fail: {e}")
|
||||
sticky = prior_failed and not blocked
|
||||
|
||||
outdir = f"security-analysis/findings/pr-{PR_NUMBER or 'manual'}"
|
||||
outpath = f"{outdir}/{int(time.time())}-review.json"
|
||||
|
||||
@@ -467,19 +500,22 @@ jobs:
|
||||
if f.get("exploit_scenario"):
|
||||
body += f" сценарий: {f['exploit_scenario']}\n\n"
|
||||
body += f"Полный список: `{outpath}`\n\n"
|
||||
if sticky:
|
||||
body += "🔴 **Merge заблокирован** — этот же коммит уже был помечен как блокирующий в более раннем прогоне ревью; новый прогон ничего не нашёл, но старую блокировку это не снимает (нужен новый коммит).\n"
|
||||
else:
|
||||
body += "🔴 **Merge заблокирован** — есть находки выше порога `security-analysis/policy.yml`.\n" if blocked else "✅ Порог не превышен.\n"
|
||||
|
||||
gitea("POST", f"/repos/{REPO}/issues/{PR_NUMBER}/comments", {"body": body})
|
||||
|
||||
gitea("POST", f"/repos/{REPO}/statuses/{COMMIT_SHA}", {
|
||||
"state": "failure" if blocked else "success",
|
||||
"state": "failure" if (blocked or sticky) else "success",
|
||||
"context": "security/review",
|
||||
"description": f"{len(findings)} findings, {len(blocking)} blocking",
|
||||
"description": (f"{len(findings)} findings, {len(blocking)} blocking" + (" (sticky: prior run flagged this commit)" if sticky else "")),
|
||||
"target_url": f"{SERVER}/{REPO}",
|
||||
})
|
||||
|
||||
print(f"findings: {len(findings)}, blocking: {len(blocking)}")
|
||||
if blocked:
|
||||
print(f"findings: {len(findings)}, blocking: {len(blocking)}, sticky: {sticky}")
|
||||
if blocked or sticky:
|
||||
sys.exit(1)
|
||||
PYEOF2
|
||||
|
||||
|
||||
Reference in New Issue
Block a user