style: repo-wide lint pass — make the lint gate green again

Push builds have been RED on the lint step since ~build 209 from accumulated
formatting drift. This is the mechanical cleanup: ruff format + ruff --fix
(UP038 isinstance unions, SIM105 contextlib.suppress, UP031 f-strings, SIM115
tempfile context manager), shfmt -i 2 -ci, nixpkgs-fmt/statix/deadnix (merged
attrsets, dropped unused lib args), yamllint, and shell quoting fixes in
tests/lasuite-docs/setup_custom_tests.sh. No behaviour changes intended;
lint: PASS, unit tests: 138 passed.
This commit is contained in:
2026-06-09 21:56:15 +00:00
parent e76d4005ab
commit 9a7772563a
115 changed files with 952 additions and 660 deletions

View File

@ -29,9 +29,9 @@ def test_quick_form():
def test_non_trigger_forms_rejected():
for body in (
"!testmexyz", # the Adversary's classic negative
"!testmexyz", # the Adversary's classic negative
"!testme xyz",
"!testme--quick", # no space → not the quick form
"!testme--quick", # no space → not the quick form
"!testme --quick", # double space → not an exact match (conservative)
"please !testme",
"testme",
@ -43,10 +43,11 @@ def test_non_trigger_forms_rejected():
# --- Phase 3 U3: YunoHost-style PR comment builders (R2) -----------------------------------------
def test_start_comment_is_yunohost_shaped():
b = bridge.start_comment_body("uptime-kuma", "dfed87a39f8a", "https://drone.x/cc-ci/42")
assert bridge.COMMENT_MARKER in b # re-!testme updates the same comment
assert "🌻" in b and "" in b # marker + in-progress
assert bridge.COMMENT_MARKER in b # re-!testme updates the same comment
assert "🌻" in b and "" in b # marker + in-progress
assert "uptime-kuma" in b and "dfed87a3" in b
assert "https://drone.x/cc-ci/42" in b
@ -54,30 +55,38 @@ def test_start_comment_is_yunohost_shaped():
def test_result_comment_image_forward_when_card_available(monkeypatch):
monkeypatch.setattr(bridge, "artifact_available", lambda url: True)
monkeypatch.setattr(bridge, "DASH_URL", "https://ci.example")
b = bridge.result_comment_body("uptime-kuma", "dfed87a39f8a", "42", "https://drone.x/cc-ci/42", "success")
b = bridge.result_comment_body(
"uptime-kuma", "dfed87a39f8a", "42", "https://drone.x/cc-ci/42", "success"
)
assert bridge.COMMENT_MARKER in b
assert "" in b and "passed" in b
# the card + badge are embedded as linked images at the stable /runs/<num>/ URLs
assert "![cc-ci result card](https://ci.example/runs/42/summary.png)" in b
assert "https://ci.example/runs/42/badge.svg" in b
assert "(https://drone.x/cc-ci/42)" in b # links to the run
assert "(https://drone.x/cc-ci/42)" in b # links to the run
def test_result_comment_text_fallback_when_card_missing(monkeypatch):
# Render failed / not served → MUST degrade to text, never a broken image (R7).
monkeypatch.setattr(bridge, "artifact_available", lambda url: False)
b = bridge.result_comment_body("hedgedoc", "abc1234def", "9", "https://drone.x/cc-ci/9", "failure")
assert "summary.png" not in b # no image embed
assert "![" not in b # no markdown image at all
b = bridge.result_comment_body(
"hedgedoc", "abc1234def", "9", "https://drone.x/cc-ci/9", "failure"
)
assert "summary.png" not in b # no image embed
assert "![" not in b # no markdown image at all
assert "" in b and "failure" in b
assert "https://drone.x/cc-ci/9" in b
def test_find_existing_comment_matches_marker(monkeypatch):
monkeypatch.setattr(bridge, "list_comments", lambda fn, n: [
{"id": 1, "body": "just a normal comment"},
{"id": 2, "body": bridge.COMMENT_MARKER + "\n🌻 old run"},
])
monkeypatch.setattr(
bridge,
"list_comments",
lambda fn, n: [
{"id": 1, "body": "just a normal comment"},
{"id": 2, "body": bridge.COMMENT_MARKER + "\n🌻 old run"},
],
)
assert bridge.find_existing_comment("org/repo", 5) == 2

View File

@ -48,7 +48,9 @@ def test_is_enrolled_reads_flag(tmp_path, monkeypatch):
def test_registry_roundtrip(tmp_path, monkeypatch):
monkeypatch.setenv("CCCI_WARM_ROOT", str(tmp_path))
assert canonical.read_registry("custom-html") is None
rec = canonical.write_registry("custom-html", version="1.10.0+x", commit="abc123", status="idle")
rec = canonical.write_registry(
"custom-html", version="1.10.0+x", commit="abc123", status="idle"
)
assert rec["domain"] == "warm-custom-html.ci.commoninternet.net"
assert rec["version"] == "1.10.0+x" and rec["commit"] == "abc123" and rec["status"] == "idle"
back = canonical.read_registry("custom-html")
@ -66,9 +68,11 @@ def test_enrolled_recipes_scans_meta(tmp_path, monkeypatch):
fake_harness = tmp_path / "runner" / "harness"
fake_harness.mkdir(parents=True)
monkeypatch.setattr(canonical, "__file__", str(fake_harness / "canonical.py"))
for name, body in (("aaa", "WARM_CANONICAL = True\n"),
("bbb", "DEPS=['x']\n"),
("ccc", "WARM_CANONICAL = True\n")):
for name, body in (
("aaa", "WARM_CANONICAL = True\n"),
("bbb", "DEPS=['x']\n"),
("ccc", "WARM_CANONICAL = True\n"),
):
d = tmp_path / "tests" / name
d.mkdir(parents=True)
(d / "recipe_meta.py").write_text(body)
@ -85,12 +89,13 @@ def test_prune_stale_drops_deenrolled_only(tmp_path, monkeypatch):
# enrolled canonical (keep), de-enrolled canonical (prune), reconciler dir (keep), alerts (keep)
for name in ("keepme", "gone"):
(tmp_path / name).mkdir()
(tmp_path / name / "canonical.json").write_text('{"recipe":"%s"}' % name)
(tmp_path / "keycloak").mkdir(); (tmp_path / "keycloak" / "last_good").write_text("v1") # reconciler
(tmp_path / name / "canonical.json").write_text(f'{{"recipe":"{name}"}}')
(tmp_path / "keycloak").mkdir()
(tmp_path / "keycloak" / "last_good").write_text("v1") # reconciler
(tmp_path / "alerts").mkdir()
pruned = canonical.prune_stale()
assert pruned == ["gone"]
assert not (tmp_path / "gone").exists()
assert (tmp_path / "keepme").exists()
assert (tmp_path / "keycloak").exists() # no canonical.json → not a canonical → kept
assert (tmp_path / "keycloak").exists() # no canonical.json → not a canonical → kept
assert (tmp_path / "alerts").exists()

View File

@ -12,9 +12,8 @@ import os
import sys
import tempfile
_tok = tempfile.NamedTemporaryFile("w", delete=False, suffix=".tok")
_tok.write("test-token")
_tok.close()
with tempfile.NamedTemporaryFile("w", delete=False, suffix=".tok") as _tok:
_tok.write("test-token")
os.environ["DRONE_TOKEN_FILE"] = _tok.name
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "dashboard"))
@ -23,10 +22,17 @@ import dashboard # noqa: E402
def _row(**kw):
base = {
"recipe": "custom-html", "status": "success", "number": 4, "ref": "db9a9502",
"version": "db9a95024e9d", "level": 4, "level_cap_reason": "",
"has_screenshot": True, "flags": {"clean_teardown": True, "no_secret_leak": True},
"finished": 0, "url": "https://drone.x/cc-ci/4",
"recipe": "custom-html",
"status": "success",
"number": 4,
"ref": "db9a9502",
"version": "db9a95024e9d",
"level": 4,
"level_cap_reason": "",
"has_screenshot": True,
"flags": {"clean_teardown": True, "no_secret_leak": True},
"finished": 0,
"url": "https://drone.x/cc-ci/4",
}
base.update(kw)
return base
@ -43,24 +49,33 @@ def test_level_color_ramp_and_fallback():
def test_overview_grid_mirrors_results():
out = dashboard.render_overview([_row()])
assert "custom-html" in out
assert "level 4" in out # the corner level pill
assert dashboard.level_color(4) in out # coloured by level
assert "db9a95024e9d" in out # version from results.json
assert "/runs/4/screenshot.png" in out # thumbnail
assert "/runs/4/summary.png" in out # links to full card
assert "/recipe/custom-html" in out # history link
assert "level 4" in out # the corner level pill
assert dashboard.level_color(4) in out # coloured by level
assert "db9a95024e9d" in out # version from results.json
assert "/runs/4/screenshot.png" in out # thumbnail
assert "/runs/4/summary.png" in out # links to full card
assert "/recipe/custom-html" in out # history link
assert "✔ teardown" in out and "✔ no-leak" in out
def test_overview_never_greener_than_data():
# A failed run at level 0 must show level 0 + the failure pill — never a green/high level.
out = dashboard.render_overview([_row(status="failure", level=0, has_screenshot=False,
flags={}, level_cap_reason="L1 install FAILED")])
out = dashboard.render_overview(
[
_row(
status="failure",
level=0,
has_screenshot=False,
flags={},
level_cap_reason="L1 install FAILED",
)
]
)
assert "level 0" in out
assert dashboard.level_color(0) in out # red
assert dashboard.level_color(0) in out # red
assert dashboard._COLORS["failure"] in out
assert "level 4" not in out and "level 5" not in out and "level 6" not in out
assert "no screenshot" in out # placeholder, no broken image
assert "no screenshot" in out # placeholder, no broken image
def test_level_pill_unknown_when_no_results():
@ -74,7 +89,7 @@ def test_history_table_lists_runs():
assert "#4" in out and "#3" in out
assert "L4" in out and "L2" in out
assert "← all recipes" in out
assert "/runs/4/summary.png" in out # per-run card link
assert "/runs/4/summary.png" in out # per-run card link
def test_history_empty():
@ -83,12 +98,24 @@ def test_history_empty():
def test_build_row_projects_results(monkeypatch):
monkeypatch.setattr(dashboard, "_results_for", lambda n: {
"version": "1.2.3", "level": 2, "level_cap_reason": "cap",
"screenshot": "screenshot.png", "flags": {"clean_teardown": True},
})
b = {"number": 7, "status": "success", "event": "custom",
"params": {"RECIPE": "n8n", "REF": "abcdef1234567890"}, "finished": 10}
monkeypatch.setattr(
dashboard,
"_results_for",
lambda n: {
"version": "1.2.3",
"level": 2,
"level_cap_reason": "cap",
"screenshot": "screenshot.png",
"flags": {"clean_teardown": True},
},
)
b = {
"number": 7,
"status": "success",
"event": "custom",
"params": {"RECIPE": "n8n", "REF": "abcdef1234567890"},
"finished": 10,
}
r = dashboard._build_row(b)
assert r["recipe"] == "n8n" and r["number"] == 7
assert r["level"] == 2 and r["version"] == "1.2.3"
@ -99,11 +126,16 @@ def test_build_row_projects_results(monkeypatch):
def test_build_row_degrades_without_results(monkeypatch):
# No results.json (e.g. an old run): grid still renders from Drone fields, level absent.
monkeypatch.setattr(dashboard, "_results_for", lambda n: {})
b = {"number": 9, "status": "running", "event": "custom",
"params": {"RECIPE": "ghost", "REF": "deadbeefcafe1234567890"}, "finished": 0}
b = {
"number": 9,
"status": "running",
"event": "custom",
"params": {"RECIPE": "ghost", "REF": "deadbeefcafe1234567890"},
"finished": 0,
}
r = dashboard._build_row(b)
assert r["level"] is None and r["has_screenshot"] is False
assert r["version"] == "deadbeefcafe" # ref[:12] fallback
assert r["version"] == "deadbeefcafe" # ref[:12] fallback
# render must not crash or claim a level
assert "level —" in dashboard.render_overview([r])
@ -111,7 +143,7 @@ def test_build_row_degrades_without_results(monkeypatch):
def test_level_badge_shows_level_coloured(monkeypatch):
svg = dashboard.render_level_badge("custom-html", 4)
assert "custom-html" in svg and "level 4" in svg
assert dashboard.level_color(4) in svg # coloured by level
assert dashboard.level_color(4) in svg # coloured by level
assert svg.startswith("<svg") and "image" not in svg # plain SVG
# A higher displayed level than earned would be inflation — badge shows exactly the given level.
assert "level 5" not in svg and "level 6" not in svg
@ -133,8 +165,8 @@ def test_results_for_traversal_guarded():
dashboard.CCCI_RUNS_DIR = d
try:
assert dashboard._results_for("5") == {"level": 3}
assert dashboard._results_for("../../etc") == {} # traversal rejected
assert dashboard._results_for("nonexist") == {} # missing → {}
assert dashboard._results_for("../../etc") == {} # traversal rejected
assert dashboard._results_for("nonexist") == {} # missing → {}
assert dashboard._results_for("") == {}
finally:
dashboard.CCCI_RUNS_DIR = orig

View File

@ -10,7 +10,6 @@ from __future__ import annotations
import os
import sys
import tempfile
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "runner"))
from harness import deps # noqa: E402
@ -30,9 +29,7 @@ def test_declared_deps_reads_DEPS_list(tmp_path, monkeypatch):
# Build a fake repo layout under tmp_path
recipe_dir = tmp_path / "tests" / fake_recipe
recipe_dir.mkdir(parents=True)
(recipe_dir / "recipe_meta.py").write_text(
'HEALTH_PATH = "/"\nDEPS = ["keycloak", "redis"]\n'
)
(recipe_dir / "recipe_meta.py").write_text('HEALTH_PATH = "/"\nDEPS = ["keycloak", "redis"]\n')
# Patch the deps module's idea of "where the repo is" by monkey-patching __file__ for the
# function indirectly: declared_deps uses `os.path.dirname(__file__), "..", "..", "tests"` —
# which resolves to the real repo's `tests/`. So instead, override that with a symlink/dir

View File

@ -20,9 +20,9 @@ import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "runner"))
import run_recipe_ci # noqa: E402
# ---- 1. the pure gate predicate ----
def test_sso_dep_unverified_true_when_declared_notready_and_skipped():
"""declares DEPS + deps not ready + ≥1 requires_deps test skipped → run must FAIL (F2-11)."""
assert run_recipe_ci.sso_dep_unverified(["keycloak"], deps_ready=False, requires_deps_skipped=1)
@ -31,7 +31,9 @@ def test_sso_dep_unverified_true_when_declared_notready_and_skipped():
def test_sso_dep_unverified_false_when_deps_ready():
"""deps ready (setup_custom_tests succeeded) → SSO tests actually ran → not a failure."""
assert not run_recipe_ci.sso_dep_unverified(["keycloak"], deps_ready=True, requires_deps_skipped=0)
assert not run_recipe_ci.sso_dep_unverified(
["keycloak"], deps_ready=True, requires_deps_skipped=0
)
def test_sso_dep_unverified_false_when_no_deps_declared():
@ -43,11 +45,14 @@ def test_sso_dep_unverified_false_when_no_deps_declared():
def test_sso_dep_unverified_false_when_nothing_skipped():
"""Deps declared + not ready but ZERO requires_deps tests skipped → don't false-fail
(the recipe has no SSO-marked tests to have been masked)."""
assert not run_recipe_ci.sso_dep_unverified(["keycloak"], deps_ready=False, requires_deps_skipped=0)
assert not run_recipe_ci.sso_dep_unverified(
["keycloak"], deps_ready=False, requires_deps_skipped=0
)
# ---- 2. conftest skip + record behavior ----
def _load_conftest():
"""Load tests/conftest.py under a private module name (avoid clashing with pytest's own
loaded `conftest`), so we can call pytest_collection_modifyitems directly with fakes."""
@ -95,7 +100,9 @@ def test_conftest_appends_across_invocations(tmp_path, monkeypatch):
monkeypatch.setenv("CCCI_DEPS_SKIP_REPORT", str(report))
conftest.pytest_collection_modifyitems(None, [_FakeItem(["requires_deps"])])
conftest.pytest_collection_modifyitems(None, [_FakeItem(["requires_deps"]), _FakeItem(["requires_deps"])])
conftest.pytest_collection_modifyitems(
None, [_FakeItem(["requires_deps"]), _FakeItem(["requires_deps"])]
)
total = sum(int(x) for x in report.read_text().split())
assert total == 3

View File

@ -32,7 +32,9 @@ def _fake_clock(monkeypatch):
_DRIVE_META = {
"READY_PROBE": lambda d: [{"host": f"collabora-{d}", "path": "/hosting/discovery", "ok": (200,)}]
"READY_PROBE": lambda d: [
{"host": f"collabora-{d}", "path": "/hosting/discovery", "ok": (200,)}
]
}
@ -73,4 +75,6 @@ def test_wait_healthy_raises_when_converged_but_never_serves(monkeypatch):
monkeypatch.setattr(lc, "services_converged", lambda domain: True)
monkeypatch.setattr(lc, "http_get", lambda *a, **k: 502)
with pytest.raises(TimeoutError):
lc.wait_healthy("x.ci.commoninternet.net", ok_codes=(200,), deploy_timeout=60, http_timeout=60)
lc.wait_healthy(
"x.ci.commoninternet.net", ok_codes=(200,), deploy_timeout=60, http_timeout=60
)

View File

@ -126,9 +126,7 @@ def test_http_get_transport_failure_returns_status_zero():
def test_http_get_sends_headers(server):
status, body = harness_http.http_get(
f"{server}/echo-headers", headers={"X-Auth": "token-123"}
)
status, body = harness_http.http_get(f"{server}/echo-headers", headers={"X-Auth": "token-123"})
assert status == 200
assert body["X-Auth"] == "token-123"

View File

@ -275,7 +275,9 @@ def test_build_results_threads_expected_na(tmp_path):
assert data["level_cap_rung"] == "backup_restore"
assert data["rungs"]["functional"] == "pass"
assert data["skips"]["intentional"]["backup_restore"] == "stateless static file server"
assert data["skips"]["unintentional"] == [] # backup_restore declared; functional passed → clean
assert (
data["skips"]["unintentional"] == []
) # backup_restore declared; functional passed → clean
def test_write_results_roundtrip(tmp_path):