e358b9b92f
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Waiting to run
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 8s
CI / Detect changes (pull_request) Successful in 16s
CI / Python Lint & Test (pull_request) Successful in 1m2s
E2E API Smoke Test / detect-changes (pull_request) Successful in 1m12s
E2E Chat / detect-changes (pull_request) Successful in 18s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (pull_request) Has been skipped
Harness Replays / detect-changes (pull_request) Successful in 20s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 20s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 22s
Lint curl status-code capture / Scan workflows for curl status-capture pollution (pull_request) Successful in 6s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 9s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 11s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (local) (pull_request) Successful in 1m50s
lint-continue-on-error-tracking / lint-continue-on-error-tracking (pull_request) Successful in 1m44s
lint-required-workflows-docker-host-pinned / Lint docker-host pin on docker-touching workflows (pull_request) Successful in 6s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 5s
Lint pre-flip continue-on-error / Verify continue-on-error flips have run-log proof (pull_request) Successful in 1m42s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m40s
lint-mask-pr-atomicity / lint-mask-pr-atomicity (pull_request) Successful in 2m2s
gate-check-v3 / gate-check (pull_request) Successful in 16s
qa-review / approved (pull_request) Successful in 12s
sop-checklist / review-refire (pull_request) Has been skipped
sop-checklist / na-declarations (pull_request) N/A: (none)
lint-required-context-exists-in-bp / lint-required-context-exists-in-bp (pull_request) Successful in 2m0s
security-review / approved (pull_request) Successful in 6s
sop-checklist / all-items-acked (pull_request) Successful in 5s
sop-tier-check / tier-check (pull_request) Successful in 6s
Ops Scripts Tests / Ops scripts (unittest) (pull_request) Successful in 1m21s
Lint workflow YAML (Gitea-1.22.6-hostile shapes) / Lint workflow YAML for Gitea-1.22.6-hostile shapes (pull_request) Successful in 1m31s
CI / Platform (Go) (pull_request) Successful in 4s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 3s
CI / Canvas (Next.js) (pull_request) Successful in 23s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 10s
E2E Chat / E2E Chat (pull_request) Successful in 12s
CI / all-required (pull_request) Successful in 7m47s
Harness Replays / Harness Replays (pull_request) Successful in 16s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 1m55s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 1m48s
audit-force-merge / audit (pull_request) Successful in 10s
194 lines
5.3 KiB
Python
194 lines
5.3 KiB
Python
"""Tests for `.gitea/scripts/detect-changes.py`."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
from pathlib import Path
|
|
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
SCRIPT = REPO_ROOT / ".gitea" / "scripts" / "detect-changes.py"
|
|
|
|
|
|
def load_module():
|
|
spec = importlib.util.spec_from_file_location("detect_changes", SCRIPT)
|
|
assert spec is not None
|
|
module = importlib.util.module_from_spec(spec)
|
|
assert spec.loader is not None
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def test_ci_profile_classifies_surfaces():
|
|
mod = load_module()
|
|
|
|
assert mod.classify("ci", ["workspace-server/internal/handlers/a2a_proxy.go"]) == {
|
|
"platform": True,
|
|
"canvas": False,
|
|
"python": False,
|
|
"scripts": False,
|
|
}
|
|
assert mod.classify("ci", ["canvas/src/app/page.tsx"]) == {
|
|
"platform": False,
|
|
"canvas": True,
|
|
"python": False,
|
|
"scripts": False,
|
|
}
|
|
assert mod.classify("ci", ["tests/e2e/test_model_slug.sh"]) == {
|
|
"platform": False,
|
|
"canvas": False,
|
|
"python": False,
|
|
"scripts": True,
|
|
}
|
|
assert mod.classify("ci", [".gitea/workflows/ci.yml", "README.md"]) == {
|
|
"platform": False,
|
|
"canvas": False,
|
|
"python": False,
|
|
"scripts": False,
|
|
}
|
|
|
|
|
|
def test_handlers_postgres_profile_is_narrower_than_workspace_server():
|
|
mod = load_module()
|
|
|
|
assert mod.classify("handlers-postgres", ["workspace-server/internal/handlers/a2a_proxy.go"]) == {
|
|
"handlers": True,
|
|
}
|
|
assert mod.classify("handlers-postgres", ["workspace-server/internal/provisioner/provisioner.go"]) == {
|
|
"handlers": False,
|
|
}
|
|
|
|
|
|
def test_e2e_api_profile_covers_api_inputs():
|
|
mod = load_module()
|
|
|
|
assert mod.classify("e2e-api", ["workspace-server/internal/handlers/workspace.go"]) == {
|
|
"api": True,
|
|
}
|
|
assert mod.classify("e2e-api", ["tests/e2e/test_api.sh"]) == {"api": True}
|
|
assert mod.classify("e2e-api", ["canvas/src/app/page.tsx"]) == {"api": False}
|
|
|
|
|
|
def test_fail_open_all_true_for_missing_base():
|
|
mod = load_module()
|
|
|
|
assert mod.all_true("ci") == {
|
|
"platform": True,
|
|
"canvas": True,
|
|
"python": True,
|
|
"scripts": True,
|
|
}
|
|
|
|
|
|
def test_fetch_base_prefers_advertised_base_ref(monkeypatch):
|
|
mod = load_module()
|
|
calls: list[list[str]] = []
|
|
exists_checks = 0
|
|
|
|
def fake_base_exists(base: str) -> bool:
|
|
nonlocal exists_checks
|
|
exists_checks += 1
|
|
return exists_checks >= 1
|
|
|
|
def fake_run_git(args: list[str], *, timeout: int = 30):
|
|
calls.append(args)
|
|
|
|
class Result:
|
|
returncode = 0
|
|
stdout = ""
|
|
stderr = ""
|
|
|
|
return Result()
|
|
|
|
monkeypatch.setattr(mod, "base_exists", fake_base_exists)
|
|
monkeypatch.setattr(mod, "run_git", fake_run_git)
|
|
|
|
mod.fetch_base("abc123", "main")
|
|
|
|
assert calls == [["fetch", "--depth=1", "origin", "main"]]
|
|
|
|
|
|
def test_fetch_base_falls_back_to_sha_when_ref_fetch_does_not_materialize(monkeypatch):
|
|
mod = load_module()
|
|
calls: list[list[str]] = []
|
|
|
|
monkeypatch.setattr(mod, "base_exists", lambda _base: False)
|
|
|
|
def fake_run_git(args: list[str], *, timeout: int = 30):
|
|
calls.append(args)
|
|
|
|
class Result:
|
|
returncode = 0
|
|
stdout = ""
|
|
stderr = ""
|
|
|
|
return Result()
|
|
|
|
monkeypatch.setattr(mod, "run_git", fake_run_git)
|
|
|
|
mod.fetch_base("abc123", "main")
|
|
|
|
assert calls == [
|
|
["fetch", "--depth=1", "origin", "main"],
|
|
["fetch", "--depth=1", "origin", "abc123"],
|
|
]
|
|
|
|
|
|
def test_changed_paths_uses_merge_base_for_pull_request(monkeypatch):
|
|
mod = load_module()
|
|
calls: list[list[str]] = []
|
|
|
|
def fake_run_git(args: list[str], *, timeout: int = 30):
|
|
calls.append(args)
|
|
|
|
class Result:
|
|
returncode = 0
|
|
stdout = "workspace/agent.py\n"
|
|
stderr = ""
|
|
|
|
if args[0] == "merge-base":
|
|
Result.stdout = "merge123\n"
|
|
return Result()
|
|
|
|
monkeypatch.setattr(mod, "run_git", fake_run_git)
|
|
|
|
assert mod.changed_paths("base123", use_merge_base=True) == ["workspace/agent.py"]
|
|
assert calls == [
|
|
["merge-base", "base123", "HEAD"],
|
|
["diff", "--name-only", "merge123", "HEAD"],
|
|
]
|
|
|
|
|
|
def test_detect_deepens_base_ref_when_pr_merge_base_missing(monkeypatch):
|
|
mod = load_module()
|
|
calls: list[tuple[str, str | None]] = []
|
|
merge_base_calls = 0
|
|
|
|
monkeypatch.setattr(mod, "base_exists", lambda _base: True)
|
|
|
|
def fake_merge_base(base: str):
|
|
nonlocal merge_base_calls
|
|
merge_base_calls += 1
|
|
if merge_base_calls == 1:
|
|
return None
|
|
return "merge123"
|
|
|
|
def fake_deepen_base_ref(base_ref: str):
|
|
calls.append(("deepen", base_ref))
|
|
|
|
def fake_changed_paths(base: str, *, use_merge_base: bool):
|
|
calls.append(("changed", str(use_merge_base)))
|
|
return [".gitea/workflows/ci.yml"]
|
|
|
|
monkeypatch.setattr(mod, "merge_base", fake_merge_base)
|
|
monkeypatch.setattr(mod, "deepen_base_ref", fake_deepen_base_ref)
|
|
monkeypatch.setattr(mod, "changed_paths", fake_changed_paths)
|
|
|
|
assert mod.detect("ci", "pull_request", "base123", "", "main") == {
|
|
"platform": False,
|
|
"canvas": False,
|
|
"python": False,
|
|
"scripts": False,
|
|
}
|
|
assert calls == [("deepen", "main"), ("changed", "True")]
|