79 lines
4.6 KiB
Python
79 lines
4.6 KiB
Python
"""Run issuer source checks with no host network, HOME, or credentials."""
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import time
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("mode", choices=["focused", "full", "build", "consumer-build", "integration"])
|
|
parser.add_argument("--attempt", type=int, default=1)
|
|
parser.add_argument("--source", type=Path, default=Path("/tmp/custodian-keycape-current-client-r1/source"))
|
|
parser.add_argument("--cache-from", type=Path)
|
|
args = parser.parse_args()
|
|
source = args.source.resolve()
|
|
assert source.is_relative_to("/tmp") and (source / "src/go.mod").is_file()
|
|
workspace = source.parent
|
|
(workspace / "home").mkdir(exist_ok=True)
|
|
toolchain = Path("/home/worsch/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.26.7.linux-amd64")
|
|
argv = ["bwrap", "--unshare-net", "--unshare-pid", "--die-with-parent", "--new-session"]
|
|
for name in ["/usr", "/lib", "/lib64"]:
|
|
argv += ["--ro-bind", name, name]
|
|
argv += ["--symlink", "usr/bin", "/bin", "--proc", "/proc", "--dev", "/dev", "--tmpfs", "/tmp",
|
|
"--bind", str(workspace), "/work", "--ro-bind", "/home/worsch/go/pkg/mod", "/modules",
|
|
"--ro-bind", str(toolchain), "/toolchain", "--chdir", "/work/consumer" if args.mode == "consumer-build" else "/work/" + source.name + "/src", "--clearenv"]
|
|
if args.mode == "integration":
|
|
argv += ["--ro-bind", str(HERE / 'current_session_owner.py'), "/fixture-owner.py",
|
|
"--ro-bind", "/home/worsch/ops-warden/.venv/lib/python3.12/site-packages", "/python-site"]
|
|
if args.cache_from:
|
|
cache = args.cache_from.resolve()
|
|
assert cache.is_relative_to('/tmp') and cache.is_dir()
|
|
argv += ['--bind', str(cache), '/work/gocache']
|
|
for key, value in {"PATH": "/toolchain/bin:/usr/bin:/bin", "HOME": "/work/home", "GOTOOLCHAIN": "local",
|
|
"GOPROXY": "off", "GOSUMDB": "off", "GOMODCACHE": "/modules", "GOCACHE": "/work/gocache",
|
|
"GOMAXPROCS": "4", "CGO_ENABLED": "1"}.items():
|
|
argv += ["--setenv", key, value]
|
|
if args.mode == "integration":
|
|
for key,value in {'PYTHONPATH':'/work/warden-source/src:/python-site', 'PYTHONDONTWRITEBYTECODE':'1',
|
|
'KEYCAPE_FIXTURE_BINARY':'/work/keycape-candidate','KEYCAPE_PUBLIC_CONSUMER':'/work/tokenstatus-consumer',
|
|
'KEYCAPE_OWNER_FIXTURE':'/fixture-owner.py','KEYCAPE_OWNER_REPORT':'/work/owner-boundary-result.json'}.items():
|
|
argv += ['--setenv',key,value]
|
|
command = ['go','test','-p','4','-race','-json','-count=1','-tags','current_owner_fixture','-run','^TestOnlineActualOwnerBoundaryAcrossProcesses$','./internal/authclient']
|
|
elif args.mode == "build":
|
|
command = ["go", "build", "-o", "/work/keycape-candidate", "./cmd/keycape"]
|
|
elif args.mode == "consumer-build":
|
|
command = ['go','build','-o','/work/tokenstatus-consumer','.']
|
|
else:
|
|
command = ["go", "test", "-p", "4", "-race", "-json", "-count=1"]
|
|
command += ["-run", "^TestOnline", "./internal/authclient"] if args.mode == "focused" else ["./..."]
|
|
argv += ["--", *command]
|
|
prefix = HERE / f"{args.mode}-attempt{args.attempt}"
|
|
assert not prefix.with_suffix(".json").exists()
|
|
start = time.monotonic()
|
|
source_inventory = {str(p.relative_to(source)): "sha256:" + hashlib.sha256(p.read_bytes()).hexdigest()
|
|
for p in (source / 'src').rglob('*') if p.is_file()}
|
|
with prefix.with_suffix(".jsonl").open("xb") as output:
|
|
result = subprocess.run(argv, stdout=output, stderr=subprocess.STDOUT, timeout=900)
|
|
counts = {"pass": 0, "fail": 0, "skip": 0}
|
|
failures, skips = [], []
|
|
for line in prefix.with_suffix(".jsonl").read_text().splitlines():
|
|
try:
|
|
event = json.loads(line)
|
|
except ValueError:
|
|
continue
|
|
if event.get("Test") and event.get("Action") in counts:
|
|
action = event["Action"]
|
|
counts[action] += 1
|
|
if action == "fail": failures.append(event["Package"] + ":" + event["Test"])
|
|
if action == "skip": skips.append(event["Package"] + ":" + event["Test"])
|
|
receipt = {"returncode": result.returncode, "seconds": round(time.monotonic() - start, 2), "argv": argv,
|
|
"source_sha256_at_start": source_inventory,
|
|
"counts_including_subtests": counts, "failures": failures, "skips": skips,
|
|
"source": str(source), "native_acceptance": False, "credentials_accessed": False,
|
|
"network": "private empty namespace; fixture loopback only", "home": "new empty sandbox HOME"}
|
|
prefix.with_suffix(".json").write_text(json.dumps(receipt, indent=2) + "\n")
|
|
print(json.dumps({k: receipt[k] for k in ["returncode", "seconds", "counts_including_subtests", "failures", "skips"]}))
|
|
raise SystemExit(result.returncode)
|