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:
1 parent
c127beaa98
commit
7ba5bfaf81
3 files changed
+94
-3
No files matched your search
+6
-2
@@ -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]:
|
||||
"""匿名 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)
|
||||
random.Random(seed).shuffle(ordered)
|
||||
return {_anon_id(i): lbl for i, lbl in enumerate(ordered)}
|
||||
@@ -1284,7 +1287,8 @@ def select_final(
|
||||
except Exception as exc:
|
||||
# 回落:已交付的终版里排第一的那个;连这个都没有才算选失败。
|
||||
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.error = str(exc)[:400]
|
||||
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
@@ -2776,9 +2776,13 @@ class Worker:
|
||||
"/var/lib/codex-app-server/codex-home/"
|
||||
"playwright_mcp.py"])
|
||||
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(
|
||||
"playwright MCP scripts refreshed for project %s: %s",
|
||||
task.get("project_id"),
|
||||
project_id,
|
||||
",".join(_seeded["script_refreshed"]))
|
||||
if _seeded.get("script_skipped_modified"):
|
||||
self.logger.warning(
|
||||
|
||||
Reference in new issue
Block a user