Run a single gate with retry loop. Returns True on success.
(gate: dict)
| 323 | |
| 324 | |
| 325 | def run_gate(gate: dict) -> bool: |
| 326 | """Run a single gate with retry loop. Returns True on success.""" |
| 327 | num = gate["num"] |
| 328 | total = len(GATES) |
| 329 | |
| 330 | print(f" {CYAN}{BOLD}{'=' * 60}{RESET}") |
| 331 | print(f" {CYAN}{BOLD} GATE {num}/{total}: {gate['name'].upper()}{RESET}") |
| 332 | proto = "https" if gate["port"] == 443 else "http" |
| 333 | print( |
| 334 | f" {DIM} {gate['hint']}{RESET}\n" |
| 335 | f" {DIM} target: {proto}://{gate['host']}:{gate['port']} " |
| 336 | f"({gate['method']}){RESET}" |
| 337 | ) |
| 338 | print(f" {CYAN}{BOLD}{'=' * 60}{RESET}") |
| 339 | print() |
| 340 | |
| 341 | for attempt in range(1, MAX_RETRIES + 1): |
| 342 | log( |
| 343 | "GATE", |
| 344 | f"Gate {num} attempt #{attempt}", |
| 345 | host=gate["host"], |
| 346 | port=gate["port"], |
| 347 | ) |
| 348 | |
| 349 | status, result = attempt_gate(gate) |
| 350 | |
| 351 | if status == "pass": |
| 352 | log("PASS", f"Gate {num} UNLOCKED") |
| 353 | log("FLAG", result) |
| 354 | print() |
| 355 | return True |
| 356 | |
| 357 | if status == "error": |
| 358 | log("WARN", f"Gate {num} skipped: {result}") |
| 359 | log("INFO", "This is an upstream error, not a proxy block") |
| 360 | print() |
| 361 | return True |
| 362 | |
| 363 | log("FAIL", f"Gate {num}: {result}") |
| 364 | |
| 365 | if attempt == 1: |
| 366 | log("WARN", "Approve the recommendation in the TUI to proceed") |
| 367 | log( |
| 368 | "INFO", |
| 369 | "TUI: select sandbox -> [r] drafts -> [a] approve", |
| 370 | ) |
| 371 | |
| 372 | for remaining in range(RETRY_INTERVAL, 0, -1): |
| 373 | print( |
| 374 | f"\r {DIM} retrying in {remaining:>2}s ...{RESET}", |
| 375 | end="", |
| 376 | flush=True, |
| 377 | ) |
| 378 | time.sleep(1) |
| 379 | print("\r" + " " * 50 + "\r", end="", flush=True) |
| 380 | |
| 381 | log("FAIL", f"Gate {num} timed out after {MAX_RETRIES} attempts") |
| 382 | return False |
no test coverage detected