ci2: fix worker F821 NameError, mark harness2 sha1 non-security, rename E741 var

- worker._tenant_dirs: playwright refresh log used undefined 'task';
  use the method argument project_id (ruff F821, real bug: NameError
  aborted tenant seeding when a playwright script was refreshed).
  Regression: cloud/tests/test_worker_playwright_seed_f821.py (2 tests;
  pre-fix run reproduces NameError at worker.py:2780).
- harness2.assign_ids: hashlib.sha1(..., usedforsecurity=False) -- the
  digest is only a deterministic shuffle seed, not a security use;
  digest value unchanged, bandit B324 no longer fires (High 5 -> 4).
- harness2.select_final: rename ambiguous loop var 'l' to 'lab'
  (ruff E741, behaviour-invariant).
- Deliberately NOT changed: host.py shell=True x4 (see PR body -- all
  four are intentional shell commands, changing semantics is unsafe),
  remaining ruff 109 / mypy 24, workflow thresholds (75% coverage
  gate unchanged; no gate was relaxed or removed).
This commit is contained in:
host committed 2026-11-03 02:48:54 +00:00
1 parent c127beaa98
commit 7ba5bfaf81
3 files changed
+94 -3

No files matched your search

+6 -2
View File
@@ -1209,7 +1209,10 @@ def _anon_id(index: int) -> str:
def assign_ids(labels: Sequence[str], *, task_id: str, k: int, mode: str) -> dict[str, str]: def assign_ids(labels: Sequence[str], *, task_id: str, k: int, mode: str) -> dict[str, str]:
"""匿名 id -> 真实 label:按排序后定种子洗牌,同输入永远同结果。""" """匿名 id -> 真实 label:按排序后定种子洗牌,同输入永远同结果。"""
seed = int(hashlib.sha1(f"{task_id}|{k}|{mode}".encode()).hexdigest()[:12], 16) # 仅确定性洗牌种子,非安全用途(不防碰撞、不做完整性校验):
# usedforsecurity=False 后 bandit B324 不再误报,且摘要值不变。
seed = int(hashlib.sha1(f"{task_id}|{k}|{mode}".encode(),
usedforsecurity=False).hexdigest()[:12], 16)
ordered = sorted(labels) ordered = sorted(labels)
random.Random(seed).shuffle(ordered) random.Random(seed).shuffle(ordered)
return {_anon_id(i): lbl for i, lbl in enumerate(ordered)} return {_anon_id(i): lbl for i, lbl in enumerate(ordered)}
@@ -1284,7 +1287,8 @@ def select_final(
except Exception as exc: except Exception as exc:
# 回落:已交付的终版里排第一的那个;连这个都没有才算选失败。 # 回落:已交付的终版里排第一的那个;连这个都没有才算选失败。
sel.chosen_label = sorted(pool)[0] sel.chosen_label = sorted(pool)[0]
sel.chosen_id = next(a for a, l in sel.id_map.items() if l == sel.chosen_label) sel.chosen_id = next(a for a, lab in sel.id_map.items()
if lab == sel.chosen_label)
sel.fallback = True sel.fallback = True
sel.error = str(exc)[:400] sel.error = str(exc)[:400]
sel.ok = True sel.ok = True
@@ -0,0 +1,83 @@
"""Regression for ruff F821 in Worker._tenant_dirs (worker.py:2780).
The playwright seeding branch logged
``task.get("project_id")`` even though ``_tenant_dirs`` only receives
``project_id`` -- there is no ``task`` variable in scope. The branch is
only reached when playwright seeding is on AND the seeder reports a
refreshed script, so ordinary seeding tests (flag off, or no refresh)
never hit it: at runtime the log call raised NameError and aborted
tenant seeding for an existing project whose playwright scripts had
just been refreshed.
No Docker, no network: _tenant_dirs runs against temp dirs and the
playwright seeder is patched to report a refresh, so the test proves
only that the log branch uses the method argument, not that real
scripts are copied.
"""
import os
import sys
import tempfile
import unittest
from pathlib import Path
from unittest import mock
try:
from cloud.server import init_db
from cloud.worker import Worker
except ImportError:
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
from cloud.server import init_db
from cloud.worker import Worker
class WorkerPlaywrightSeedF821TestCase(unittest.TestCase):
def setUp(self):
self.tmp = tempfile.TemporaryDirectory()
self.db_path = os.path.join(self.tmp.name, "control.db")
init_db(self.db_path)
self.template_home = os.path.join(self.tmp.name, "tpl-home")
os.makedirs(self.template_home)
open(os.path.join(self.template_home, "config.toml"),
"w").write('[model_provider.xcmapi]\n'
'base_url="https://xcmapi.org/v1"\n')
self.template_repo = os.path.join(self.tmp.name, "tpl-repo")
os.makedirs(os.path.join(self.template_repo, ".git"))
open(os.path.join(self.template_repo, "sample.py"),
"w").write("def add(a, b):\n return a + b\n")
def tearDown(self):
self.tmp.cleanup()
def _worker(self):
return Worker(
self.db_path, "/fake/host.py",
env={"XCM_API_KEY": "test-placeholder"},
tenants_root=os.path.join(self.tmp.name, "tenants"),
tenant_template_home=self.template_home,
tenant_template_repo=self.template_repo,
tenant_isolation=True,
playwright_mcp=True)
def test_refreshed_script_logs_project_id_without_name_error(self):
# Pre-fix this raised NameError: name 'task' is not defined.
worker = self._worker()
with mock.patch("cloud.worker._ensure_playwright_mcp",
return_value={"script_refreshed":
["playwright_mcp.py"]}):
with self.assertLogs(worker.logger, level="INFO") as logs:
dirs = worker._tenant_dirs("projA")
self.assertIn("codex_home", dirs)
self.assertTrue(any("projA" in line and "playwright_mcp.py" in line
for line in logs.output))
def test_no_refresh_still_seeds(self):
worker = self._worker()
with mock.patch("cloud.worker._ensure_playwright_mcp",
return_value={"script_refreshed": []}):
dirs = worker._tenant_dirs("projA")
self.assertIn("codex_home", dirs)
if __name__ == "__main__":
unittest.main()
+5 -1
View File
@@ -2776,9 +2776,13 @@ class Worker:
"/var/lib/codex-app-server/codex-home/" "/var/lib/codex-app-server/codex-home/"
"playwright_mcp.py"]) "playwright_mcp.py"])
if _seeded.get("script_refreshed"): if _seeded.get("script_refreshed"):
# _tenant_dirs 只收 project_id 参数,作用域里没有 task:
# 此前写 task.get("project_id") 在脚本刷新时抛 NameError,
# 中断整个租户播种(ruff F821,回归见
# test_worker_playwright_seed_f821)。
self.logger.info( self.logger.info(
"playwright MCP scripts refreshed for project %s: %s", "playwright MCP scripts refreshed for project %s: %s",
task.get("project_id"), project_id,
",".join(_seeded["script_refreshed"])) ",".join(_seeded["script_refreshed"]))
if _seeded.get("script_skipped_modified"): if _seeded.get("script_skipped_modified"):
self.logger.warning( self.logger.warning(