Conversation
The five substantive `run:` blocks in .github/workflows/ci.yml (staging gawk for the sandbox, installing actionlint, reporting sccache statistics, discarding the instrumented build trees, and installing Kani) become Python scripts under scripts/ci, written to docs/scripting-standards.md: each is a Cyclopts application reading its parameters from INPUT_* and ambient GitHub Actions environment variables, running external programs through cuprum's allowlisted catalogue rather than a shell, and using pathlib for the filesystem. The workflow invokes each as `uv run --script scripts/ci/<name>.py`, so every pin sits beside its step as an `env:` entry the contract tests can read, and ci.yml drops from 400 lines to 329. Setup uv moves ahead of the first script in build-test and is added to kani-smoke. The actionlint installer no longer runs the upstream downloader script behind a curl override: the checksum-verified archive is the whole artefact, so the single `actionlint` member is extracted directly. Both installers refuse links and directories in archives and accept only https:// and file:// URLs. scripts/ci/ci_support.py holds the shared catalogue, runner, GITHUB_PATH publication, and verified download and extraction. scripts/tests/test_ci_* cover every script's happy path and failure modes with pytest and cmd-mox shims for sudo, sccache, df, and cargo, and serve release fixtures over file:// so the real download, verification, and extraction path runs without a network. `make test-ci-scripts` runs them; CI runs it before Format. The scripts pin cyclopts and cuprum in their PEP 723 blocks at the Makefile's CYCLOPTS_VERSION and CUPRUM_VERSION, held equal by a test, and ty checks them alongside the other Python sources. The workflow contracts for the retired inline blocks now assert the script invocation and the pins each step passes; the behaviours they spelled out line by line live in the script tests. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Reviewer's GuideThe PR moves substantive inline CI shell into five tested, environment-driven Cyclopts scripts using cuprum for allowlisted process execution and pathlib for filesystem work. The workflow now delegates to one-line Sequence diagram for verified CI archive installationsequenceDiagram
participant CI as GitHub Actions
participant Script as install_actionlint.py or install_kani.py
participant Release as Release archive
participant Support as ci_support.py
participant Disk as Versioned install directory
participant Tool as actionlint or cargo kani
CI->>Script: Run via uv run --script with INPUT_* pins
Script->>Disk: Check cached executable or bundle
alt payload missing
Script->>Support: download(url, destination)
Support->>Release: Fetch HTTPS or file URL
Release-->>Support: Archive bytes
Script->>Support: verify_sha256(archive, pin)
Script->>Support: extract_members(archive, destination, members)
Support-->>Disk: Write regular executable files
Script->>Tool: Run setup when verifier bundle requires it
end
Script-->>CI: Installed or restored pinned tool
Sequence diagram for CI report and cleanup scriptssequenceDiagram
participant CI as GitHub Actions
participant Report as report_sccache_stats.py
participant Cache as sccache
participant Summary as GITHUB_STEP_SUMMARY
participant Cleanup as discard_instrumented_tree.py
participant Disk as Target filesystem
CI->>Report: Run statistics step
Report->>Cache: show_stats(--show-stats)
Report->>Cache: show_stats(--stats-format=json)
Report->>Summary: Write text summary and report files
CI->>Cleanup: Run cleanup step
Cleanup->>Disk: show_disk_usage()
Cleanup->>Disk: discard(target_dir, subtrees)
Cleanup->>Disk: show_disk_usage()
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
cuprum 0.1.0 on PyPI predates the `RunOutputOptions` runtime the scripting standards describe; 0.2.0 is close but unreleased. The scripts and the Makefile's CI_SCRIPT_DEPS now pin `cuprum @ git+https://github.com/ leynos/cuprum@<CUPRUM_REF>`, held equal by the metadata test, and the shared runner passes `output=RunOutputOptions(capture=True, echo=...)`. Bump CUPRUM_REF to the release pin once 0.2.0 ships. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueComment |
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ci-windows.yml, netsukefile-test.yml, and coverage-main.yml carried the same inline sccache report block as ci.yml; each now runs scripts/ci/report_sccache_stats.py, and coverage-main.yml runs scripts/ci/discard_instrumented_tree.py for its instrumented tree as well. The lanes that lacked uv gain a cache-less Setup uv step after their credential export. The sccache contract now requires the script on every compiling lane; the release smoke job, which only prints the JSON form and has no uv, is the one recorded exception. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
Gates Failed
Enforce advisory code health rules
(3 files with Complex Method, Excess Number of Function Arguments, Large Method)
Our agent can fix these. Install it.
Gates Passed
5 Quality Gates Passed
Reason for failure
| Enforce advisory code health rules | Violations | Code Health Impact | |
|---|---|---|---|
| install_kani.py | 2 advisory rules | 9.28 | Suppress |
| ci_support.py | 2 advisory rules | 9.39 | Suppress |
| install_actionlint.py | 1 advisory rule | 9.69 | 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.
Summary
This branch moves every substantive inline shell block in
.github/workflows/ci.ymlinto Python scripts underscripts/ci, written to the repository's scripting standards. Each script is a Cyclopts application that reads its parameters fromINPUT_*and ambient GitHub Actions environment variables, runs external programs through cuprum's allowlisted catalogue rather than a shell, and usespathlibfor the filesystem. The workflow invokes each one asuv run --script scripts/ci/<name>.py, so a step body is one line and every pin it needs is anenv:entry beside it, where the workflow contract tests read it. The workflow drops from 400 lines, its file limit, to 329.The five converted steps in
ci.ymlare the gawk staging for the test sandbox, the actionlint installer, the sccache statistics report, the instrumented-tree discard, and the Kani installer. The remainingrun:lines are singlemaketargets or version prints. The actionlint installer no longer runs the upstream downloader behind acurloverride: the checksum-verified archive is the whole artefact, so the singleactionlintmember is extracted directly, and both installers refuse links and directories in archives and accept onlyhttps://andfile://URLs.Every script has behavioural tests with pytest and cmd-mox, which shim
sudo,sccache,df, andcargoat the process boundary, and release fixtures are served overfile://so the real download, verification, and extraction path runs without a network.make test-ci-scriptsruns the suite; CI runs it beforemake check-fmt.No roadmap task or issue is attached, and no execplan exists for this change.
Review walkthrough
GITHUB_PATHpublication, and the verified download and extraction that both installers use.Setup uvahead of the first script; see the actionlint step and the Kani step for theenv:pin pattern.kani-smokegains its ownSetup uv.test-ci-scripts; the version pins feed the test and typecheck gates, andtypecheck-pythonnow resolvesscripts/ci. pyproject.toml exempts the Cyclopts entry points from the argument-count ceilings, since one keyword parameter per input is the contract.test_ci_<name>.pyper script, plus test_ci_scripts_metadata.py, which holds each PEP 723 block to the Makefile pins and the env-first Cyclopts shape.Validation
make test-ci-scripts: 54 passedmake test-workflow-contracts: 364 passedmake lint-python,make typecheck-python: passPATH="$HOME/go/bin:$PATH" make github-actions-lint: pass (yamllint and actionlint)make check-fmt,make markdownlint,make nixie: passuv run --script:discard_instrumented_tree.pyagainst a scratch target directory;install_actionlint.pyagainst the real v1.7.12 release with the pinned SHA-256 (cold install, then warm reuse reportingrestored from the cache volume)No Rust sources changed, so the Clippy, Whitaker, and
cargo testgates were not run. The scripts have not yet run on a GitHub runner; the first CI run of this PR is the proof forstage_test_shell.py(needssudo apt-get) andinstall_kani.py.Notes
leynos/cuprum@a2134c7a(the Makefile'sCUPRUM_REF) rather than the PyPI 0.1.0 release, because the scripts use theRunOutputOptionsruntime that 0.2.0 will ship. BumpCUPRUM_REFto the release pin once it is published. That revision has noCatalogue.from_programseither, so the scripts build aProgramCataloguefromProjectSettings;docs/scripting-standards.mdstill shows the older sketch and needs a separate correction.ci-windows.yml,netsukefile-test.yml, andcoverage-main.ymlnow runsreport_sccache_stats.pytoo, andcoverage-main.ymlusesdiscard_instrumented_tree.py; lanes without uv gained a cache-lessSetup uvstep. The sccache contract requires the script on every compiling lane exceptrelease.yml's Windows smoke job, which only prints the JSON form and is recorded as the one exception.References
Summary by Sourcery
Replace substantive inline CI shell with tested, secure Python helper scripts and update workflows, contracts, tooling, and documentation to use them.
New Features:
Bug Fixes:
Enhancements:
Build:
CI:
Documentation:
Tests: