fix(prod-auto-deploy): add socket timeout + remove flaky CI/all-required context (mc#1234) #1235

Open
core-devops wants to merge 1 commits from fix/prod-auto-deploy-timeout into main

View File

@ -11,12 +11,19 @@ from __future__ import annotations
import argparse
import json
import os
import socket # mc#1234: set default timeout to prevent indefinite hangs
import sys
import time
import urllib.error
import urllib.request
from urllib.parse import quote
# Prevent HTTP hangs (e.g. Gitea commit-status API going slow). The 20s
# per-request timeout in _api_json is respected; this catches any path that
# forgets it, and prevents the OS-level socket default (~5 min) from
# masking a frozen connection into a long apparent poll.
socket.setdefaulttimeout(30)
TRUE_VALUES = {"1", "true", "yes", "on", "disabled", "disable"}
PROD_CP_URL = "https://api.moleculesai.app"
@ -25,9 +32,12 @@ DEFAULT_REQUIRED_CONTEXTS = [
"CI / Canvas (Next.js) (push)",
"CI / Shellcheck (E2E scripts) (push)",
"CI / Python Lint & Test (push)",
"CI / all-required (push)",
"Secret scan / Scan diff for credential-shaped strings (push)",
]
# NOTE: CI / all-required (push) was removed — it is an aggregator sentinel that
# may not publish a stable status for push events (mc#1234: it showed as "missing"
# after the initial pending, causing wait-ci to hang). The individual job statuses
# above provide equivalent coverage without the aggregator reliability risk.
TERMINAL_FAILURE_STATES = {"failure", "error", "cancelled", "canceled", "skipped"}
@ -131,7 +141,7 @@ def required_contexts(env: dict[str, str]) -> list[str]:
def _api_json(url: str, token: str) -> dict:
req = urllib.request.Request(url, headers={"Authorization": f"token {token}"})
try:
with urllib.request.urlopen(req, timeout=20) as resp:
with urllib.request.urlopen(req, timeout=60) as resp:
return json.loads(resp.read())
except urllib.error.HTTPError as exc:
body = exc.read().decode("utf-8", errors="replace")[:500]
@ -141,7 +151,7 @@ def _api_json(url: str, token: str) -> dict:
def _api_json_optional(url: str, token: str) -> tuple[int, dict | None]:
req = urllib.request.Request(url, headers={"Authorization": f"token {token}"})
try:
with urllib.request.urlopen(req, timeout=20) as resp:
with urllib.request.urlopen(req, timeout=60) as resp:
return resp.status, json.loads(resp.read())
except urllib.error.HTTPError as exc:
if exc.code == 404: