Repository navigation
Conversation
Add Linux packaged-crate qualification for both backends, strict rustdoc, isolated install and external-consumer smoke checks, and publish dry-run. Retain SHA-specific archive and command evidence even when qualification fails. Amp-Thread-ID: https://ampcode.com/threads/T-01a11df5-5390-73cf-a980-c28826029bd9 Co-authored-by: Raul Cardenas Montoya <montoyaraul34@gmail.com>
The packaged release gate found a redundant explicit intra-doc target. Keep the same destination without suppressing the rustdoc warning. Amp-Thread-ID: https://ampcode.com/threads/T-01a11df5-5390-73cf-a980-c28826029bd9 Co-authored-by: Raul Cardenas Montoya <montoyaraul34@gmail.com>
🤖 CodeAnt AI — Review Status
|
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
|
Warning Review limit reachedEnable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. Next included review available in 19 minutes. View limit detailsLimit details: You’ve used all 5 included reviews currently available. Your 7 included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (4)
Comment |
There was a problem hiding this comment.
This PR adds comprehensive Cargo archive release qualification to CI. The implementation is solid with proper error handling, timeout management, and evidence retention. The new packaged release job correctly qualifies the exact PR head SHA, runs extensive tests on extracted archives in both modes, and validates the publish path. Documentation is thorough and the doc link fix is appropriate. No blocking issues identified.
You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.
There was a problem hiding this comment.
Gates Failed
New code is healthy
(1 new file with code health below 10.00)
Enforce critical code health rules
(1 file with Bumpy Road Ahead)
Enforce advisory code health rules
(1 file with Complex Method, Large Method, Excess Number of Function Arguments)
Our agent can fix these. Install it.
Gates Passed
3 Quality Gates Passed
Reason for failure
| New code is healthy | Violations | Code Health Impact | |
|---|---|---|---|
| qualify-package.py | 4 rules | 8.48 | Suppress |
| Enforce critical code health rules | Violations | Code Health Impact | |
|---|---|---|---|
| qualify-package.py | 1 critical rule | 8.48 | Suppress |
| Enforce advisory code health rules | Violations | Code Health Impact | |
|---|---|---|---|
| qualify-package.py | 3 advisory rules | 8.48 | Suppress |
Quality Gate Profile: Pay Down Tech Debt
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.
| def smoke(binary, mode, version, work, evidence, env): | ||
| help_text = run(f"{mode}-help", [binary, "--help"], work, evidence, env, timeout=10) | ||
| if "--config" not in help_text or "--version" not in help_text: | ||
| raise RuntimeError("installed CLI is missing expected options") | ||
| actual_version = run(f"{mode}-version", [binary, "--version"], work, evidence, env, timeout=10) | ||
| if actual_version.strip() != f"brainstem-daemon {version}": | ||
| raise RuntimeError("installed version does not match the package") | ||
|
|
||
| # Allocate distinct ports; no external publisher is needed for simulation. | ||
| ports = set() | ||
| while len(ports) < 3: | ||
| ports.add(free_port()) | ||
| sub_port, pub_port, control_port = sorted(ports) | ||
| config_text = f'''lif_count = 4 | ||
| izh_count = 0 | ||
| channels = 4 | ||
| tick_rate_hz = 100 | ||
| log_level = "info" | ||
| spine_sub_port = {sub_port} | ||
| spine_pub_port = {pub_port} | ||
| control_bind = "127.0.0.1:{control_port}" | ||
| model_path = "missing-checkpoint.json" | ||
| ''' | ||
| simulation = work / f"{mode}-simulation.toml" | ||
| simulation.write_text('runtime_mode = "simulation"\n' + config_text) | ||
| shutil.copy2(simulation, evidence / simulation.name) | ||
| # Observe readiness, not merely survival after an arbitrary sleep. Exercise | ||
| # both Unix shutdown signals with bounded startup and teardown. | ||
| for stop_signal in (signal.SIGINT, signal.SIGTERM): | ||
| label = f"{mode}-simulation-{stop_signal.name}" | ||
| with (evidence / f"{label}.log").open("w") as log: | ||
| process = subprocess.Popen( | ||
| [binary, "--config", simulation], cwd=work, env=env, | ||
| stdout=log, stderr=subprocess.STDOUT, | ||
| ) | ||
| try: | ||
| deadline = time.monotonic() + 10 | ||
| while True: | ||
| if process.poll() is not None: | ||
| raise RuntimeError(f"{label}: exited before readiness ({process.returncode})") | ||
| try: | ||
| with urllib.request.urlopen( | ||
| f"http://127.0.0.1:{control_port}/readyz", timeout=0.5, | ||
| ) as response: | ||
| if response.status == 200 and response.read() == b"ready\n": | ||
| break | ||
| except (urllib.error.URLError, TimeoutError): | ||
| pass | ||
| if time.monotonic() >= deadline: | ||
| raise RuntimeError(f"{label}: never became ready") | ||
| time.sleep(0.05) | ||
| process.send_signal(stop_signal) | ||
| if process.wait(timeout=10) != 0: | ||
| raise RuntimeError(f"{label}: did not shut down successfully") | ||
| finally: | ||
| if process.poll() is None: | ||
| process.kill() | ||
| process.wait() | ||
| log.write(f"\nQUALIFIED: /readyz=200; {stop_signal.name}; graceful exit=0\n") | ||
| print(f"[{label}] /readyz=200; graceful exit=0", flush=True) | ||
|
|
||
| # Live is the default. Both missing and corrupt checkpoints must fail before | ||
| # runtime startup; a successful exit or a hang must not pass this check. | ||
| for invalid in ("missing", "corrupt"): | ||
| checkpoint = work / "missing-checkpoint.json" | ||
| if invalid == "corrupt": | ||
| checkpoint.write_text("not a checkpoint") | ||
| live = work / f"{mode}-live-{invalid}.toml" | ||
| live.write_text(config_text) | ||
| shutil.copy2(live, evidence / live.name) | ||
| text = run( | ||
| f"{mode}-live-{invalid}", [binary, "--config", live], work, | ||
| evidence, env, expected=1, timeout=10, | ||
| ) | ||
| if "invalid or missing Spikenaut checkpoint" not in text: | ||
| raise RuntimeError("live rejection did not report checkpoint failure") | ||
| checkpoint.unlink() |
There was a problem hiding this comment.
❌ New issue: Complex Method
smoke has a cyclomatic complexity of 23, threshold = 9
| def qualify(evidence): | ||
| repo = Path(__file__).resolve().parents[2] | ||
| env = os.environ.copy() | ||
| # Do not inherit target/Rust flags that could mask a packaged build failure. | ||
| for key in ("CARGO_TARGET_DIR", "RUSTFLAGS", "CARGO_ENCODED_RUSTFLAGS", | ||
| "RUSTDOCFLAGS", "CARGO_ENCODED_RUSTDOCFLAGS", "RUST_LOG"): | ||
| env.pop(key, None) | ||
| env.update(CC="gcc", CXX="g++", CARGO_TERM_COLOR="never") | ||
| cargo = ["cargo", "+1.98.1"] | ||
| sha = run("git-sha", ["git", "rev-parse", "HEAD"], repo, evidence, env).strip() | ||
| dirty = run("git-status", ["git", "status", "--porcelain", "--untracked-files=no"], repo, evidence, env) | ||
| if dirty.strip(): | ||
| raise RuntimeError("qualification requires a clean committed checkout") | ||
| run("rustc", ["rustc", "+1.98.1", "--version", "--verbose"], repo, evidence, env) | ||
| run("cargo", cargo + ["--version"], repo, evidence, env) | ||
| manifest = tomllib.loads((repo / "Cargo.toml").read_text()) | ||
| package_name = f"{manifest['package']['name']}-{manifest['package']['version']}" | ||
| identity = {"sha": sha, "package": package_name, "status": "running"} | ||
| (evidence / "identity.json").write_text(json.dumps(identity, indent=2) + "\n") | ||
|
|
||
| with tempfile.TemporaryDirectory(prefix="brainstem-package-") as temporary: | ||
| work = Path(temporary) | ||
| env["CARGO_TARGET_DIR"] = str(work / "target") | ||
| contents = run("package-list", cargo + ["package", "--locked", "--list"], repo, evidence, env) | ||
| tracked = run("git-sources", ["git", "ls-files", "src", "tests"], repo, evidence, env) | ||
| required = set(tracked.splitlines()) | { | ||
| "Cargo.toml", "Cargo.toml.orig", "Cargo.lock", "README.md", | ||
| "LICENSE-MIT", "LICENSE-APACHE-2.0", "rust-toolchain.toml", ".cargo_vcs_info.json", | ||
| } | ||
| listed = set(contents.splitlines()) | ||
| missing = required - listed | ||
| if missing: | ||
| raise RuntimeError(f"package is missing required files: {sorted(missing)}") | ||
| if any(path.startswith((".github/", ".devin/", "docs/", "target/")) for path in listed): | ||
| raise RuntimeError("package includes repository-only or generated files") | ||
| run("package", cargo + ["package", "--locked"], repo, evidence, env) | ||
| archive = work / "target" / "package" / f"{package_name}.crate" | ||
| shutil.copy2(archive, evidence / archive.name) | ||
| identity["archive_sha256"] = hashlib.sha256(archive.read_bytes()).hexdigest() | ||
| extracted = work / "extracted" | ||
| extracted.mkdir() | ||
| with tarfile.open(archive) as tar: | ||
| tar.extractall(extracted, filter="data") | ||
| package = extracted / package_name | ||
| vcs = json.loads((package / ".cargo_vcs_info.json").read_text()) | ||
| if vcs["git"]["sha1"] != sha or vcs["git"].get("dirty", False): | ||
| raise RuntimeError("archive VCS identity does not match the clean candidate SHA") | ||
| if not all((package / path).is_file() for path in required): | ||
| raise RuntimeError("extracted archive is missing required files") | ||
| (evidence / "identity.json").write_text(json.dumps(identity, indent=2) + "\n") | ||
|
|
||
| for mode, features in (("stub", []), ("corpus-ipc", ["--features", "corpus-ipc"])): | ||
| # Never reuse checkout artifacts, or artifacts from the other backend. | ||
| env["CARGO_TARGET_DIR"] = str(work / f"target-{mode}") | ||
| for command in ("build", "test"): | ||
| run(f"{mode}-{command}", cargo + [command, "--locked"] + features, package, evidence, env) | ||
| docs_env = dict(env, RUSTDOCFLAGS="-D warnings") | ||
| run(f"{mode}-rustdoc", cargo + ["doc", "--locked", "--no-deps"] + features, package, evidence, docs_env) | ||
| root = work / f"install-{mode}" | ||
| run( | ||
| f"{mode}-install", cargo + ["install", "--locked", "--path", str(package), "--root", str(root)] + features, | ||
| work, evidence, env, | ||
| ) | ||
| smoke(root / "bin" / "brainstem-daemon", mode, manifest["package"]["version"], work, evidence, env) | ||
| consumer = work / f"consumer-{mode}" | ||
| (consumer / "src").mkdir(parents=True) | ||
| (consumer / "Cargo.toml").write_text(f'''[package] | ||
| name = "package-consumer" | ||
| version = "0.0.0" | ||
| edition = "2024" | ||
|
|
||
| [dependencies] | ||
| brainstem-daemon = {{ path = {json.dumps(str(package))}, features = {json.dumps(features[1:] if features else [])} }} | ||
| ''') | ||
| (consumer / "src" / "main.rs").write_text('''use brainstem_daemon::{BrainstemDaemon, DaemonConfig, RuntimeMode}; | ||
|
|
||
| fn main() -> Result<(), Box<dyn std::error::Error>> { | ||
| let path = std::env::args().nth(1).expect("config argument"); | ||
| let mut config = DaemonConfig::load(std::path::Path::new(&path))?; | ||
| assert_eq!(config.runtime_mode, RuntimeMode::Simulation); | ||
| let daemon = BrainstemDaemon::try_new(config.clone())?; | ||
| assert!(daemon.restore_network().is_ok()); | ||
| config.runtime_mode = RuntimeMode::Live; | ||
| assert!(BrainstemDaemon::try_new(config)?.restore_network().is_err()); | ||
| println!("external consumer: simulation restore OK; missing live checkpoint rejected"); | ||
| Ok(()) | ||
| } | ||
| ''') | ||
| shutil.copytree(consumer, evidence / f"consumer-{mode}") | ||
| run(f"{mode}-consumer-lock", cargo + ["generate-lockfile"], consumer, evidence, env) | ||
| shutil.copy2(consumer / "Cargo.lock", evidence / f"consumer-{mode}" / "Cargo.lock") | ||
| run( | ||
| f"{mode}-consumer", cargo + ["run", "--locked", "--", str(work / f"{mode}-simulation.toml")], | ||
| consumer, evidence, env, | ||
| ) | ||
|
|
||
| # Use the clean source checkout for Cargo's publish path, which itself | ||
| # packages and verifies it. Nothing is uploaded; no bypass flags are used. | ||
| env["CARGO_TARGET_DIR"] = str(work / "publish-target") | ||
| run("publish-dry-run", cargo + ["publish", "--dry-run", "--locked"], repo, evidence, env) | ||
| identity["status"] = "passed" | ||
| (evidence / "identity.json").write_text(json.dumps(identity, indent=2) + "\n") | ||
| print(f"PASS: packaged release qualification for {sha}", flush=True) |
There was a problem hiding this comment.
❌ New issue: Complex Method
qualify has a cyclomatic complexity of 17, threshold = 9
| def qualify(evidence): | ||
| repo = Path(__file__).resolve().parents[2] | ||
| env = os.environ.copy() | ||
| # Do not inherit target/Rust flags that could mask a packaged build failure. | ||
| for key in ("CARGO_TARGET_DIR", "RUSTFLAGS", "CARGO_ENCODED_RUSTFLAGS", | ||
| "RUSTDOCFLAGS", "CARGO_ENCODED_RUSTDOCFLAGS", "RUST_LOG"): | ||
| env.pop(key, None) | ||
| env.update(CC="gcc", CXX="g++", CARGO_TERM_COLOR="never") | ||
| cargo = ["cargo", "+1.98.1"] | ||
| sha = run("git-sha", ["git", "rev-parse", "HEAD"], repo, evidence, env).strip() | ||
| dirty = run("git-status", ["git", "status", "--porcelain", "--untracked-files=no"], repo, evidence, env) | ||
| if dirty.strip(): | ||
| raise RuntimeError("qualification requires a clean committed checkout") | ||
| run("rustc", ["rustc", "+1.98.1", "--version", "--verbose"], repo, evidence, env) | ||
| run("cargo", cargo + ["--version"], repo, evidence, env) | ||
| manifest = tomllib.loads((repo / "Cargo.toml").read_text()) | ||
| package_name = f"{manifest['package']['name']}-{manifest['package']['version']}" | ||
| identity = {"sha": sha, "package": package_name, "status": "running"} | ||
| (evidence / "identity.json").write_text(json.dumps(identity, indent=2) + "\n") | ||
|
|
||
| with tempfile.TemporaryDirectory(prefix="brainstem-package-") as temporary: | ||
| work = Path(temporary) | ||
| env["CARGO_TARGET_DIR"] = str(work / "target") | ||
| contents = run("package-list", cargo + ["package", "--locked", "--list"], repo, evidence, env) | ||
| tracked = run("git-sources", ["git", "ls-files", "src", "tests"], repo, evidence, env) | ||
| required = set(tracked.splitlines()) | { | ||
| "Cargo.toml", "Cargo.toml.orig", "Cargo.lock", "README.md", | ||
| "LICENSE-MIT", "LICENSE-APACHE-2.0", "rust-toolchain.toml", ".cargo_vcs_info.json", | ||
| } | ||
| listed = set(contents.splitlines()) | ||
| missing = required - listed | ||
| if missing: | ||
| raise RuntimeError(f"package is missing required files: {sorted(missing)}") | ||
| if any(path.startswith((".github/", ".devin/", "docs/", "target/")) for path in listed): | ||
| raise RuntimeError("package includes repository-only or generated files") | ||
| run("package", cargo + ["package", "--locked"], repo, evidence, env) | ||
| archive = work / "target" / "package" / f"{package_name}.crate" | ||
| shutil.copy2(archive, evidence / archive.name) | ||
| identity["archive_sha256"] = hashlib.sha256(archive.read_bytes()).hexdigest() | ||
| extracted = work / "extracted" | ||
| extracted.mkdir() | ||
| with tarfile.open(archive) as tar: | ||
| tar.extractall(extracted, filter="data") | ||
| package = extracted / package_name | ||
| vcs = json.loads((package / ".cargo_vcs_info.json").read_text()) | ||
| if vcs["git"]["sha1"] != sha or vcs["git"].get("dirty", False): | ||
| raise RuntimeError("archive VCS identity does not match the clean candidate SHA") | ||
| if not all((package / path).is_file() for path in required): | ||
| raise RuntimeError("extracted archive is missing required files") | ||
| (evidence / "identity.json").write_text(json.dumps(identity, indent=2) + "\n") | ||
|
|
||
| for mode, features in (("stub", []), ("corpus-ipc", ["--features", "corpus-ipc"])): | ||
| # Never reuse checkout artifacts, or artifacts from the other backend. | ||
| env["CARGO_TARGET_DIR"] = str(work / f"target-{mode}") | ||
| for command in ("build", "test"): | ||
| run(f"{mode}-{command}", cargo + [command, "--locked"] + features, package, evidence, env) | ||
| docs_env = dict(env, RUSTDOCFLAGS="-D warnings") | ||
| run(f"{mode}-rustdoc", cargo + ["doc", "--locked", "--no-deps"] + features, package, evidence, docs_env) | ||
| root = work / f"install-{mode}" | ||
| run( | ||
| f"{mode}-install", cargo + ["install", "--locked", "--path", str(package), "--root", str(root)] + features, | ||
| work, evidence, env, | ||
| ) | ||
| smoke(root / "bin" / "brainstem-daemon", mode, manifest["package"]["version"], work, evidence, env) | ||
| consumer = work / f"consumer-{mode}" | ||
| (consumer / "src").mkdir(parents=True) | ||
| (consumer / "Cargo.toml").write_text(f'''[package] | ||
| name = "package-consumer" | ||
| version = "0.0.0" | ||
| edition = "2024" | ||
|
|
||
| [dependencies] | ||
| brainstem-daemon = {{ path = {json.dumps(str(package))}, features = {json.dumps(features[1:] if features else [])} }} | ||
| ''') | ||
| (consumer / "src" / "main.rs").write_text('''use brainstem_daemon::{BrainstemDaemon, DaemonConfig, RuntimeMode}; | ||
|
|
||
| fn main() -> Result<(), Box<dyn std::error::Error>> { | ||
| let path = std::env::args().nth(1).expect("config argument"); | ||
| let mut config = DaemonConfig::load(std::path::Path::new(&path))?; | ||
| assert_eq!(config.runtime_mode, RuntimeMode::Simulation); | ||
| let daemon = BrainstemDaemon::try_new(config.clone())?; | ||
| assert!(daemon.restore_network().is_ok()); | ||
| config.runtime_mode = RuntimeMode::Live; | ||
| assert!(BrainstemDaemon::try_new(config)?.restore_network().is_err()); | ||
| println!("external consumer: simulation restore OK; missing live checkpoint rejected"); | ||
| Ok(()) | ||
| } | ||
| ''') | ||
| shutil.copytree(consumer, evidence / f"consumer-{mode}") | ||
| run(f"{mode}-consumer-lock", cargo + ["generate-lockfile"], consumer, evidence, env) | ||
| shutil.copy2(consumer / "Cargo.lock", evidence / f"consumer-{mode}" / "Cargo.lock") | ||
| run( | ||
| f"{mode}-consumer", cargo + ["run", "--locked", "--", str(work / f"{mode}-simulation.toml")], | ||
| consumer, evidence, env, | ||
| ) | ||
|
|
||
| # Use the clean source checkout for Cargo's publish path, which itself | ||
| # packages and verifies it. Nothing is uploaded; no bypass flags are used. | ||
| env["CARGO_TARGET_DIR"] = str(work / "publish-target") | ||
| run("publish-dry-run", cargo + ["publish", "--dry-run", "--locked"], repo, evidence, env) | ||
| identity["status"] = "passed" | ||
| (evidence / "identity.json").write_text(json.dumps(identity, indent=2) + "\n") | ||
| print(f"PASS: packaged release qualification for {sha}", flush=True) |
There was a problem hiding this comment.
❌ New issue: Large Method
qualify has 94 lines, threshold = 70
| def smoke(binary, mode, version, work, evidence, env): | ||
| help_text = run(f"{mode}-help", [binary, "--help"], work, evidence, env, timeout=10) | ||
| if "--config" not in help_text or "--version" not in help_text: | ||
| raise RuntimeError("installed CLI is missing expected options") | ||
| actual_version = run(f"{mode}-version", [binary, "--version"], work, evidence, env, timeout=10) | ||
| if actual_version.strip() != f"brainstem-daemon {version}": | ||
| raise RuntimeError("installed version does not match the package") | ||
|
|
||
| # Allocate distinct ports; no external publisher is needed for simulation. | ||
| ports = set() | ||
| while len(ports) < 3: | ||
| ports.add(free_port()) | ||
| sub_port, pub_port, control_port = sorted(ports) | ||
| config_text = f'''lif_count = 4 | ||
| izh_count = 0 | ||
| channels = 4 | ||
| tick_rate_hz = 100 | ||
| log_level = "info" | ||
| spine_sub_port = {sub_port} | ||
| spine_pub_port = {pub_port} | ||
| control_bind = "127.0.0.1:{control_port}" | ||
| model_path = "missing-checkpoint.json" | ||
| ''' | ||
| simulation = work / f"{mode}-simulation.toml" | ||
| simulation.write_text('runtime_mode = "simulation"\n' + config_text) | ||
| shutil.copy2(simulation, evidence / simulation.name) | ||
| # Observe readiness, not merely survival after an arbitrary sleep. Exercise | ||
| # both Unix shutdown signals with bounded startup and teardown. | ||
| for stop_signal in (signal.SIGINT, signal.SIGTERM): | ||
| label = f"{mode}-simulation-{stop_signal.name}" | ||
| with (evidence / f"{label}.log").open("w") as log: | ||
| process = subprocess.Popen( | ||
| [binary, "--config", simulation], cwd=work, env=env, | ||
| stdout=log, stderr=subprocess.STDOUT, | ||
| ) | ||
| try: | ||
| deadline = time.monotonic() + 10 | ||
| while True: | ||
| if process.poll() is not None: | ||
| raise RuntimeError(f"{label}: exited before readiness ({process.returncode})") | ||
| try: | ||
| with urllib.request.urlopen( | ||
| f"http://127.0.0.1:{control_port}/readyz", timeout=0.5, | ||
| ) as response: | ||
| if response.status == 200 and response.read() == b"ready\n": | ||
| break | ||
| except (urllib.error.URLError, TimeoutError): | ||
| pass | ||
| if time.monotonic() >= deadline: | ||
| raise RuntimeError(f"{label}: never became ready") | ||
| time.sleep(0.05) | ||
| process.send_signal(stop_signal) | ||
| if process.wait(timeout=10) != 0: | ||
| raise RuntimeError(f"{label}: did not shut down successfully") | ||
| finally: | ||
| if process.poll() is None: | ||
| process.kill() | ||
| process.wait() | ||
| log.write(f"\nQUALIFIED: /readyz=200; {stop_signal.name}; graceful exit=0\n") | ||
| print(f"[{label}] /readyz=200; graceful exit=0", flush=True) | ||
|
|
||
| # Live is the default. Both missing and corrupt checkpoints must fail before | ||
| # runtime startup; a successful exit or a hang must not pass this check. | ||
| for invalid in ("missing", "corrupt"): | ||
| checkpoint = work / "missing-checkpoint.json" | ||
| if invalid == "corrupt": | ||
| checkpoint.write_text("not a checkpoint") | ||
| live = work / f"{mode}-live-{invalid}.toml" | ||
| live.write_text(config_text) | ||
| shutil.copy2(live, evidence / live.name) | ||
| text = run( | ||
| f"{mode}-live-{invalid}", [binary, "--config", live], work, | ||
| evidence, env, expected=1, timeout=10, | ||
| ) | ||
| if "invalid or missing Spikenaut checkpoint" not in text: | ||
| raise RuntimeError("live rejection did not report checkpoint failure") | ||
| checkpoint.unlink() |
There was a problem hiding this comment.
❌ New issue: Large Method
smoke has 70 lines, threshold = 70
| def smoke(binary, mode, version, work, evidence, env): | ||
| help_text = run(f"{mode}-help", [binary, "--help"], work, evidence, env, timeout=10) | ||
| if "--config" not in help_text or "--version" not in help_text: | ||
| raise RuntimeError("installed CLI is missing expected options") | ||
| actual_version = run(f"{mode}-version", [binary, "--version"], work, evidence, env, timeout=10) | ||
| if actual_version.strip() != f"brainstem-daemon {version}": | ||
| raise RuntimeError("installed version does not match the package") | ||
|
|
||
| # Allocate distinct ports; no external publisher is needed for simulation. | ||
| ports = set() | ||
| while len(ports) < 3: | ||
| ports.add(free_port()) | ||
| sub_port, pub_port, control_port = sorted(ports) | ||
| config_text = f'''lif_count = 4 | ||
| izh_count = 0 | ||
| channels = 4 | ||
| tick_rate_hz = 100 | ||
| log_level = "info" | ||
| spine_sub_port = {sub_port} | ||
| spine_pub_port = {pub_port} | ||
| control_bind = "127.0.0.1:{control_port}" | ||
| model_path = "missing-checkpoint.json" | ||
| ''' | ||
| simulation = work / f"{mode}-simulation.toml" | ||
| simulation.write_text('runtime_mode = "simulation"\n' + config_text) | ||
| shutil.copy2(simulation, evidence / simulation.name) | ||
| # Observe readiness, not merely survival after an arbitrary sleep. Exercise | ||
| # both Unix shutdown signals with bounded startup and teardown. | ||
| for stop_signal in (signal.SIGINT, signal.SIGTERM): | ||
| label = f"{mode}-simulation-{stop_signal.name}" | ||
| with (evidence / f"{label}.log").open("w") as log: | ||
| process = subprocess.Popen( | ||
| [binary, "--config", simulation], cwd=work, env=env, | ||
| stdout=log, stderr=subprocess.STDOUT, | ||
| ) | ||
| try: | ||
| deadline = time.monotonic() + 10 | ||
| while True: | ||
| if process.poll() is not None: | ||
| raise RuntimeError(f"{label}: exited before readiness ({process.returncode})") | ||
| try: | ||
| with urllib.request.urlopen( | ||
| f"http://127.0.0.1:{control_port}/readyz", timeout=0.5, | ||
| ) as response: | ||
| if response.status == 200 and response.read() == b"ready\n": | ||
| break | ||
| except (urllib.error.URLError, TimeoutError): | ||
| pass | ||
| if time.monotonic() >= deadline: | ||
| raise RuntimeError(f"{label}: never became ready") | ||
| time.sleep(0.05) | ||
| process.send_signal(stop_signal) | ||
| if process.wait(timeout=10) != 0: | ||
| raise RuntimeError(f"{label}: did not shut down successfully") | ||
| finally: | ||
| if process.poll() is None: | ||
| process.kill() | ||
| process.wait() | ||
| log.write(f"\nQUALIFIED: /readyz=200; {stop_signal.name}; graceful exit=0\n") | ||
| print(f"[{label}] /readyz=200; graceful exit=0", flush=True) | ||
|
|
||
| # Live is the default. Both missing and corrupt checkpoints must fail before | ||
| # runtime startup; a successful exit or a hang must not pass this check. | ||
| for invalid in ("missing", "corrupt"): | ||
| checkpoint = work / "missing-checkpoint.json" | ||
| if invalid == "corrupt": | ||
| checkpoint.write_text("not a checkpoint") | ||
| live = work / f"{mode}-live-{invalid}.toml" | ||
| live.write_text(config_text) | ||
| shutil.copy2(live, evidence / live.name) | ||
| text = run( | ||
| f"{mode}-live-{invalid}", [binary, "--config", live], work, | ||
| evidence, env, expected=1, timeout=10, | ||
| ) | ||
| if "invalid or missing Spikenaut checkpoint" not in text: | ||
| raise RuntimeError("live rejection did not report checkpoint failure") | ||
| checkpoint.unlink() |
There was a problem hiding this comment.
❌ New issue: Bumpy Road Ahead
smoke has 2 blocks with nested conditional logic. Any nesting of 2 or deeper is considered. Threshold is 2 blocks per function
| def run(label, args, cwd, evidence, env, expected=0, timeout=1800): | ||
| log = evidence / f"{label}.log" | ||
| record = {"label": label, "command": list(map(str, args)), "cwd": str(cwd), | ||
| "expected_exit": expected, "timeout_seconds": timeout, | ||
| "rustdocflags": env.get("RUSTDOCFLAGS", "")} | ||
| with (evidence / "commands.jsonl").open("a") as commands: | ||
| commands.write(json.dumps(record) + "\n") | ||
| print(f"[{label}] cwd={cwd} $ {shlex.join(map(str, args))}", flush=True) | ||
| with log.open("w") as output: | ||
| result = subprocess.run( | ||
| args, cwd=cwd, env=env, stdout=output, stderr=subprocess.STDOUT, | ||
| timeout=timeout, check=False, | ||
| ) | ||
| text = log.read_text() | ||
| with (evidence / "commands.jsonl").open("a") as commands: | ||
| commands.write(json.dumps({"label": label, "exit": result.returncode}) + "\n") | ||
| print(text[-4000:], flush=True) | ||
| print(f"[{label}] exit={result.returncode}", flush=True) | ||
| if result.returncode != expected: | ||
| raise RuntimeError(f"{label}: expected exit {expected}, got {result.returncode}") | ||
| return text |
There was a problem hiding this comment.
❌ New issue: Excess Number of Function Arguments
run has 7 arguments, max arguments = 4
| def smoke(binary, mode, version, work, evidence, env): | ||
| help_text = run(f"{mode}-help", [binary, "--help"], work, evidence, env, timeout=10) | ||
| if "--config" not in help_text or "--version" not in help_text: | ||
| raise RuntimeError("installed CLI is missing expected options") | ||
| actual_version = run(f"{mode}-version", [binary, "--version"], work, evidence, env, timeout=10) | ||
| if actual_version.strip() != f"brainstem-daemon {version}": | ||
| raise RuntimeError("installed version does not match the package") | ||
|
|
||
| # Allocate distinct ports; no external publisher is needed for simulation. | ||
| ports = set() | ||
| while len(ports) < 3: | ||
| ports.add(free_port()) | ||
| sub_port, pub_port, control_port = sorted(ports) | ||
| config_text = f'''lif_count = 4 | ||
| izh_count = 0 | ||
| channels = 4 | ||
| tick_rate_hz = 100 | ||
| log_level = "info" | ||
| spine_sub_port = {sub_port} | ||
| spine_pub_port = {pub_port} | ||
| control_bind = "127.0.0.1:{control_port}" | ||
| model_path = "missing-checkpoint.json" | ||
| ''' | ||
| simulation = work / f"{mode}-simulation.toml" | ||
| simulation.write_text('runtime_mode = "simulation"\n' + config_text) | ||
| shutil.copy2(simulation, evidence / simulation.name) | ||
| # Observe readiness, not merely survival after an arbitrary sleep. Exercise | ||
| # both Unix shutdown signals with bounded startup and teardown. | ||
| for stop_signal in (signal.SIGINT, signal.SIGTERM): | ||
| label = f"{mode}-simulation-{stop_signal.name}" | ||
| with (evidence / f"{label}.log").open("w") as log: | ||
| process = subprocess.Popen( | ||
| [binary, "--config", simulation], cwd=work, env=env, | ||
| stdout=log, stderr=subprocess.STDOUT, | ||
| ) | ||
| try: | ||
| deadline = time.monotonic() + 10 | ||
| while True: | ||
| if process.poll() is not None: | ||
| raise RuntimeError(f"{label}: exited before readiness ({process.returncode})") | ||
| try: | ||
| with urllib.request.urlopen( | ||
| f"http://127.0.0.1:{control_port}/readyz", timeout=0.5, | ||
| ) as response: | ||
| if response.status == 200 and response.read() == b"ready\n": | ||
| break | ||
| except (urllib.error.URLError, TimeoutError): | ||
| pass | ||
| if time.monotonic() >= deadline: | ||
| raise RuntimeError(f"{label}: never became ready") | ||
| time.sleep(0.05) | ||
| process.send_signal(stop_signal) | ||
| if process.wait(timeout=10) != 0: | ||
| raise RuntimeError(f"{label}: did not shut down successfully") | ||
| finally: | ||
| if process.poll() is None: | ||
| process.kill() | ||
| process.wait() | ||
| log.write(f"\nQUALIFIED: /readyz=200; {stop_signal.name}; graceful exit=0\n") | ||
| print(f"[{label}] /readyz=200; graceful exit=0", flush=True) | ||
|
|
||
| # Live is the default. Both missing and corrupt checkpoints must fail before | ||
| # runtime startup; a successful exit or a hang must not pass this check. | ||
| for invalid in ("missing", "corrupt"): | ||
| checkpoint = work / "missing-checkpoint.json" | ||
| if invalid == "corrupt": | ||
| checkpoint.write_text("not a checkpoint") | ||
| live = work / f"{mode}-live-{invalid}.toml" | ||
| live.write_text(config_text) | ||
| shutil.copy2(live, evidence / live.name) | ||
| text = run( | ||
| f"{mode}-live-{invalid}", [binary, "--config", live], work, | ||
| evidence, env, expected=1, timeout=10, | ||
| ) | ||
| if "invalid or missing Spikenaut checkpoint" not in text: | ||
| raise RuntimeError("live rejection did not report checkpoint failure") | ||
| checkpoint.unlink() |
There was a problem hiding this comment.
❌ New issue: Excess Number of Function Arguments
smoke has 6 arguments, max arguments = 4
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| BestPractice | 1 medium |
| ErrorProne | 1 high |
| CodeStyle | 1 minor |
| Complexity | 4 medium |
🟢 Metrics 34 complexity · 0 duplication
Metric Results Complexity 34 Duplication 0
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
|
|
Overall Grade |
Security Reliability Complexity Hygiene |
Code Review Summary
| Analyzer | Status | Updated (UTC) | Details |
|---|---|---|---|
| Rust | Oct 9, 2026 12:17a.m. | Review ↗ | |
| Secrets | Oct 9, 2026 12:17a.m. | Review ↗ |
Important
AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.
CodeAnt Nitpicks1 code suggestion1.
|
CodeAnt PR Risk: Low Risk
Assessed commit: |
There was a problem hiding this comment.
2 issues found across 4 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/workflows/ci.yml">
<violation number="1" location=".github/workflows/ci.yml:156">
P3: `if-no-files-found: error` makes this always() retention step fail as a second error whenever an earlier step (checkout, apt-get, toolchain install) fails before target/package-evidence/ is created. The job already reports the original failure, so this only adds misleading noise to the run summary. Use `warn` so the retention step under `if: always()` can never fail the run by itself.</violation>
</file>
<file name=".github/scripts/qualify-package.py">
<violation number="1" location=".github/scripts/qualify-package.py:45">
P3: `free_port` returns an ephemeral port by binding and immediately closing the socket, but `smoke` only binds those ports later, inside a freshly spawned daemon process (and in `corpus-ipc` mode after ZMQ context/socket setup). Between the close and the daemon's bind, any other local process can claim the port, which makes this release gate flaky: the daemon fails to bind (or the readiness probe hits a different service) and the whole qualification run fails spuriously. Pass `0` would be the robust alternative if the daemon could report its assigned ports; with this design, lease each port by double-checking it is still free right before spawning, or retry the whole smoke run with a fresh port set on bind failure.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
| with: | ||
| name: package-qualification-${{ github.event.pull_request.head.sha || github.sha }} | ||
| path: target/package-evidence/ | ||
| if-no-files-found: error |
There was a problem hiding this comment.
P3: if-no-files-found: error makes this always() retention step fail as a second error whenever an earlier step (checkout, apt-get, toolchain install) fails before target/package-evidence/ is created. The job already reports the original failure, so this only adds misleading noise to the run summary. Use warn so the retention step under if: always() can never fail the run by itself.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At .github/workflows/ci.yml, line 156:
<comment>`if-no-files-found: error` makes this always() retention step fail as a second error whenever an earlier step (checkout, apt-get, toolchain install) fails before target/package-evidence/ is created. The job already reports the original failure, so this only adds misleading noise to the run summary. Use `warn` so the retention step under `if: always()` can never fail the run by itself.</comment>
<file context>
@@ -122,3 +122,36 @@ jobs:
+ with:
+ name: package-qualification-${{ github.event.pull_request.head.sha || github.sha }}
+ path: target/package-evidence/
+ if-no-files-found: error
+ retention-days: 90
</file context>
| if-no-files-found: error | |
| if-no-files-found: warn |
| return text | ||
|
|
||
|
|
||
| def free_port(): |
There was a problem hiding this comment.
P3: free_port returns an ephemeral port by binding and immediately closing the socket, but smoke only binds those ports later, inside a freshly spawned daemon process (and in corpus-ipc mode after ZMQ context/socket setup). Between the close and the daemon's bind, any other local process can claim the port, which makes this release gate flaky: the daemon fails to bind (or the readiness probe hits a different service) and the whole qualification run fails spuriously. Pass 0 would be the robust alternative if the daemon could report its assigned ports; with this design, lease each port by double-checking it is still free right before spawning, or retry the whole smoke run with a fresh port set on bind failure.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At .github/scripts/qualify-package.py, line 45:
<comment>`free_port` returns an ephemeral port by binding and immediately closing the socket, but `smoke` only binds those ports later, inside a freshly spawned daemon process (and in `corpus-ipc` mode after ZMQ context/socket setup). Between the close and the daemon's bind, any other local process can claim the port, which makes this release gate flaky: the daemon fails to bind (or the readiness probe hits a different service) and the whole qualification run fails spuriously. Pass `0` would be the robust alternative if the daemon could report its assigned ports; with this design, lease each port by double-checking it is still free right before spawning, or retry the whole smoke run with a fresh port set on bind failure.</comment>
<file context>
@@ -0,0 +1,247 @@
+ return text
+
+
+def free_port():
+ with socket.socket() as sock:
+ sock.bind(("127.0.0.1", 0))
</file context>
User description
Closes #69
Summary
.crateoutside the checkout, and build/test default andcorpus-ipcmodes independently.cargo +1.98.1 publish --dry-run --lockedwithout bypass flags. No actual crates.io upload is performed.Acceptance evidence
Local qualification passed on candidate 198e195, using Rust/Cargo 1.98.1 on Linux:
cargo +1.98.1 package --locked --list: 40 files; required manifests/lockfile, licenses, README, toolchain, sources and test fixtures present.cargo +1.98.1 package --locked: package verification passed; embedded Git SHA matches the clean candidate checkout.corpus-ipcbuild/tests: 173 unit tests and 9 integration tests passed, 0 failed, 1 intentionally ignored signal test.RUSTDOCFLAGS="-D warnings" cargo +1.98.1 doc --locked --no-deps, separately default and--features corpus-ipc.--help,--version=brainstem-daemon 0.3.0, simulation/readyz= 200, SIGINT and SIGTERM graceful exit = 0. Missing/corrupt live checkpoints each exit 1 with checkpoint-specific errors.cargo +1.98.1 publish --dry-run --locked: exit 0,warning: aborting upload due to dry run.cargo fmt --check, locked build/test and strict all-target Clippy, default and all-features; all passed. Workflowactionlintand Python syntax checks passed.Retained local archive SHA-256:
4a20191be0f6620f743f4e24b3b1fe15c420d4c012b049927d7725284d267eea.The PR CI run will independently retain its evidence under
package-qualification-198e195b33aff2042069240372c471df308bb2b4. See the run's downloadable artifact andidentity.json; onlystatus: passedmeans qualification completed. Preserve that artifact in the release record before its 90-day expiry, and rerun qualification for any changed candidate SHA. Local results do not assert that pending hosted CI checks are green.Scope and delivery
Part of 02 — v0.3.0 release qualification. All #69 acceptance checks have passed locally; hosted CI confirmation follows this PR. This does not qualify other release gates, publish a crate, merge this PR, or create/update any Linear issue.
Summary by cubic
Adds a Linux release-qualification CI job that tests the actual Cargo
packagearchive built from the PR head SHA instead of the checkout or a synthetic merge commit.The job verifies required archive contents, extracts and builds/tests the
.cratein both default andcorpus-ipcmodes, runs warning-denying rustdoc, installs release binaries into isolated roots with CLI and signal smoke tests, runs external library consumers, and performscargo publish --dry-run --locked(no upload). Evidence is retained as a SHA-specific artifact for 90 days, includingidentity.jsonwith the SHA, archive checksum, and qualification status. Local docs document reproduction.Also fixes a redundant intra-doc link that the strict rustdoc gate flagged; no runtime behavior changes.
Written for commit 198e195. Summary will update on new commits.
CodeAnt-AI Description
Verify Cargo release archives and fresh installs in CI
What Changed
corpus-ipcfeatures.Impact
✅ Catch missing release files before publication✅ Catch broken fresh installs before release✅ Keep SHA-specific evidence for failed release checks💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.