Repository navigation
ci: shared tests and release on merge to stable, version from Cargo.toml - #110
Conversation
Branch renaming
Optimize memory usage
Dev -> Stable 4.2.0
ubuntu-latest is a label GitHub moves. The image changes under us and a green pipeline turns red on a morning nobody touched the code. Pinning to ubuntu-24.04 means the runner moves when we move it. dtolnay/rust-toolchain was called at @stable, a branch, not a release. It is pinned to a commit, dated in the trailing comment because that repo publishes no release tag for it. Version-tagged actions are untouched.
The lint job ran an unpinned `pipx install ruff`, which picked up 0.16.9 and failed on 8 pre-existing errors (import order, __slots__ sort, SIM102, SIM201). The Rust job tracked `stable`, whose clippy now denies for_kv_map in src/node/base.rs. Both blocked unrelated PRs such as #92. Pin ruff==0.16.9 in the workflow and dev group, pin Rust 1.97.1 with clippy and rustfmt in rust-toolchain.toml and rust-tests.yml, and fix the errors in source.
…ore/pin-actions-sha
Fork PRs get a read-only GITHUB_TOKEN, so the comment step failed the job after the benchmark itself passed.
windows-latest and macos-latest were still floating in the wheel matrix.
rust-tests.yml and python-tests.yml published to crates.io and PyPI on every push to stable, each with a long-lived token. Publishing moves to publish.yml, triggered only by v* tags. Its first job refuses tags outside vMAJOR.MINOR.PATCH or vMAJOR.MINOR.PATCH-rc.N and any tag that does not equal the Cargo.toml version. Both test workflows run before any wheel is built, every build must succeed before a registry sees the release, PyPI uses trusted publishing in the pypi environment, crates.io runs in the release environment, and the last job creates the GitHub Release with an SPDX JSON SBOM attached. actions-rs/toolchain is archived and is replaced by actions-rust-lang/setup-rust-toolchain reading rust-toolchain.toml. Every workflow declares least-privilege permissions, every action is pinned to a commit SHA, and CLA calls the shared reusable workflow.
ruff 0.16 formats Python blocks in Markdown, so ruff format --check failed on README.md and the lint job only ran ruff check. Formatting it lets lint run both checks.
pyproject.toml and Cargo.toml both declared 4.2.0, two sources that publish.yml could only compare against one of. maturin fills a dynamic [project] version from Cargo.toml, so Cargo.toml is now the single source for crates.io, PyPI, and the tag check. poetry.lock and .flake8 are left over from before the move to uv and ruff. Nothing reads them.
#139 replaces long-lived registry tokens with OIDC. crates.io supports trusted publishing: rust-lang/crates-io-auth-action exchanges the job's OIDC token for a short-lived publish token, so CARGO_REGISTRY_TOKEN no longer needs to exist as a secret.
rust-tests.yml, python-tests.yml, the CLA caller, and the release steps of publish.yml now use the org workflows in blacklanternsecurity/CLA at one pinned SHA instead of carrying copies. - python: python-tests.yml derives the matrix from requires-python, replacing the literal 3.9 to 3.14 list, runs ruff check and ruff format --check (format was never checked here), and builds the extension with maturin develop when maturin is the backend. - rust: rust-tests.yml with --all-features --locked on the rust-toolchain.toml channel. - publish: release-check.yml validates the tag against Cargo.toml (now the single version source). The wheel matrix and the crates.io and PyPI uploads stay here because they are radixtarget-specific and PyPI trusted publishing does not work in a reusable workflow. publish.yml creates the release with the SPDX SBOM and attaches the wheels. - archive/** is no longer excluded: archive tags are not created.
Picks up secret-env skipping absent secrets on fork PRs and rust-tests running setup-script before clippy. No caller input changes.
e532142 sits on feat/shared-workflows, which was squash-merged and can stop resolving once the branch is deleted. 40c6e18 is CLA main and a superset: it adds optional registry login for image SBOMs to publish.yml, with defaults that leave existing callers unchanged. Refs blacklanternsecurity/bbot-enterprise#139
Follows .github-config#17 through CLA#11: publish.yml runs on push to the trunk instead of a v* tag, publishes in the release environment a bbot-leads member approves, re-runs safely (PyPI skip-existing, crates.io only when the version is new), and leaves the tag and the GitHub release to the bls-release App at the end of the run. The pypi environment and the long-lived registry token are gone.
# Conflicts: # .github/workflows/benchmark.yml # .github/workflows/python-tests.yml # pyproject.toml # radixtarget/test/test_rust_radixtarget.py # uv.lock
- publish: build wheels through CLA's maturin-wheels, which installs every interpreter requires-python allows, so Windows and macOS ship per-version wheels again; publish crates.io through CLA's crates.yml after PyPI; pass no App credentials - python-tests, rust-tests, cla: CODECOV_TOKEN and the CLA App credentials by name instead of secrets: inherit; drop the stable push triggers that duplicated the publish calls - python-tests: keep reporting the required test (3.11) to (3.15) contexts from the real result until the ruleset moves - stable-guard: refuse a pull request into stable whose version or dependencies cannot release - benchmark: explicit permissions and a pinned runner - re-pin every CLA reference to CLA#11
# Conflicts: # .github/workflows/benchmark.yml # .github/workflows/python-tests.yml # .github/workflows/rust-tests.yml
4.3.0 is on PyPI and crates.io with no v4.3.0 tag, so release-check would refuse it as partly published.
RadixTarget Benchmark Results100000 networks per table, 100000 lookups, median of 5 runs (seed 1337).
Change is in time taken: negative is faster. |
…t releasing
publish.yml drops to permissions: {} and grants contents read per job.
check also gets actions and pull-requests read for CLA#11's provenance
check and environment guard.
dependabot-auto-merge.yml is removed. Once dev drops to zero approvals
it would merge Dependabot PRs on CI alone (pjhartlieb).
The README gains a Releasing section: the four release approvals per
run, and that PyPy and free-threaded interpreters get the sdist since
the shared wheel build covers default CPython only.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #110 +/- ##
===================================
Coverage 100% 100%
===================================
Files 3 3
Lines 604 605 +1
===================================
+ Hits 604 605 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
en0f
left a comment
There was a problem hiding this comment.
Approved, FYI:
.github/workflows/cla.yml: the CLA check will fail to start once this reaches stable.
The file’s top-level permissions are only pull-requests: write and statuses: write. When you list any permissions, everything you leave out is set to none, so contents becomes none.
At the pinned commit 07e14bc, the shared cla-reusable.yml job asks for contents: read.
A called workflow can’t ask for more than its caller gives it. GitHub rejects the run before it starts with “nested job ‘CLAAssistant’ is requesting ‘contents: read’, but is only allowed ‘contents: none’”. This happens on every pull_request_target and issue_comment event, so no PR gets a CLA status.
The PR checks don’t show this. pull_request_target runs the default branch’s workflow, and the “CLA Assistant” check on this PR came from the old cla.yml already on stable.
CLAAssistant isn’t a required check in the protecc ruleset, so merges won’t be blocked. The CLA gate would just stop running without any error on the PR.
Fix: add contents: read to the permissions in cla.yml.
en0f
left a comment
There was a problem hiding this comment.
Approved, see comment:
Still broke: head is still 3510c97,
.github/workflows/cla.yml: the CLA check won’t start once this reaches stable.
The caller grants only pull-requests: write and statuses: write, so contents falls to none.
At the pinned commit 07e14bc, the CLAAssistant job in cla-reusable.yml asks for contents: read. GitHub refuses to start the run, so no PR gets a CLA status.
The green “CLA Assistant” check on this PR comes from the old cla.yml on the default branch. That’s how pull_request_target works, so the PR checks can’t catch this.
The fix is to add contents: read to cla.yml.
It won’t block merges, because protecc only requires test (3.11) through test (3.15).
|
Inputs, secrets and permissions otherwise match v1.0.0. Please hold the merge until this repo's |
# Conflicts: # uv.lock
Move every CLA reusable workflow call to blacklanternsecurity/release-workflows at v1.0.0 and pass BLS_RELEASE_PRIVATE_KEY to the release-check and publish calls, which receive release-environment secrets only when mapped.
en0f
left a comment
There was a problem hiding this comment.
@pjhartlieb -
I found one blocker. It won’t stop this PR merging into dev, but it will make the first release fail when dev is promoted to stable.
Blocker: the first release from publish.yml will fail the provenance check.
Where it fails: release-check.yml at v1.0.0 runs provenance.py. That script walks the first-parent history of stable back to the last v* tag and requires every commit since then to belong to a PR merged into stable.
Why: The only v* tag reachable from stable is v3.0.0 (4.3.0 shipped without a tag). That leaves 34 first-parent commits to check, and I looked each one up with the GitHub API. 30 of them don’t pass:
5 direct pushes with no PR: the CLA commits cbd63aa, ff0ac17, e2787a1, ab32e6a and 0ecc48e.
25 merges of PRs whose base is master, not stable: #20–#27, #43–#51, #60, #62, #63 and #65–#69, all from before the branch rename. merged_into() checks the base name exactly.
What happens: The check job exits with “30 commit(s) since v3.0.0 bypassed review”. The tests, wheels, PyPI, crates.io and release jobs never run.
Fix: Before promoting, push a v4.3.0 tag on 3317d3e, the merge of #105 that shipped 4.3.0. The check would then start from there and only see #108 and #111 (both fine) plus the promotion merge. That also fills the tag gap the PR description mentions.
What changed
rust-tests.ymlandpython-tests.yml, which used to publish on everystablepush with long-lived tokens. Neither triggers onpush: stableany more, so they no longer duplicate the calls frompublish.yml.python-tests.ymlandrust-tests.ymlcall CLA's shared workflows. The Python matrix comes fromrequires-python.ruff format --checknow runs, and the extension is built withmaturin develop. Rust runs--all-features --lockedon therust-toolchain.tomlchannel.CODECOV_TOKENis passed by name. Until the default branch ruleset requirespython / passed, arequiredjob reportstest (3.11)to(3.15)from the real result.publish.ymlruns on a push tostable: CLA'srelease-check.yml, then rust and python tests, then CLA'smaturin-wheels.yml(every interpreterrequires-pythonallows, on Windows and macOS too), then PyPI with OIDC inrelease, then crates.io through CLA'scrates.ymlwith trusted publishing, then CLA'spublish.yml(tag and GitHub Release with SBOM and wheels, created last). No caller passes App credentials.stable-guard.yml:release readyon pull requests intostablerefuses a non-MAJOR.MINOR.PATCHversion and git or URL dependencies.cla.ymlpassesAPP_ID/APP_PRIVATE_KEYby name. No workflow usessecrets: inherit.benchmark.ymldeclarescontents: readandpull-requests: writeand pins its runner.Cargo.tomlis the single version source, now 4.3.1: 4.3.0 is on PyPI and crates.io with nov4.3.0tag.poetry.lockand.flake8removed. Merges currentdev(dependabot grouping, shared auto-merge).Before promoting to
stablereleaseenvironment with reviewers and astable-only deployment policy, holdingBLS_RELEASE_APP_IDandBLS_RELEASE_PRIVATE_KEY.publish.yml, environmentrelease. Then delete the PyPI and crates.io token secrets.protecc(11169658), and the matching .github-config#1/Prune / Defragment branches to save space #2 Terraform: requirepython / passed,rust / passedandrelease ready, then drop therequiredjob.Validation
Related issues
Supersedes #96, moved from a fork to an upstream branch.