Skip to content

ci: shared tests and tag-only publish, version from Cargo.toml - #96

Open
singlerider wants to merge 20 commits into
blacklanternsecurity:devfrom
singlerider:ci/publish-on-tag
Open

singlerider wants to merge 20 commits into
blacklanternsecurity:devfrom
singlerider:ci/publish-on-tag

Conversation

@singlerider

@singlerider singlerider commented Oct 3, 2026 •

Copy link
Copy Markdown

What changed

  • Publishing removed from rust-tests.yml and python-tests.yml. Both used to publish on every stable push with long-lived tokens.
  • python-tests.yml and rust-tests.yml call the shared workflows in blacklanternsecurity/CLA at one pinned SHA. The Python matrix comes from requires-python, replacing the literal 3.9 to 3.14 list. ruff format --check now runs (only ruff check did before), and the extension is built with maturin develop. Rust runs --all-features --locked on the rust-toolchain.toml channel. actions-rs/toolchain is gone.
  • publish.yml runs on v* tags only: shared release-check.yml validates the tag against Cargo.toml, then rust and python tests run, then the wheel matrix and sdist build, then crates.io and PyPI upload, then shared publish.yml creates the GitHub Release with the SPDX JSON SBOM and the wheels attached.
  • crates.io uses trusted publishing (rust-lang/crates-io-auth-action), so CARGO_REGISTRY_TOKEN is no longer stored. PyPI uses OIDC in the pypi environment.
  • Cargo.toml is the single version source. pyproject.toml declares dynamic = ["version"] and maturin fills it in.
  • Dead poetry.lock and .flake8 removed. README code blocks formatted so ruff format --check passes.
  • Every workflow has permissions:, every action is SHA-pinned, and the CLA caller uses the shared SHA. Builds on ci: pin the runner image and the branch-ref actions #92.

Required checks: python / passed, rust / passed.

Validation

$ cargo fmt --all -- --check && cargo clippy --all-targets --all-features --locked -- -D warnings && cargo test --all-features --locked
test result: ok. 72 passed; 0 failed; 2 ignored
test result: ok. 9 passed; 0 failed; 0 ignored
$ uv run ruff check -q && uv run ruff format --check -q
ruff check + format --check: clean (ruff 0.16.9)
$ uv run pytest -q
14 passed in 1.12s
$ uv run python -c "import importlib.metadata as m; print(m.version('radixtarget'))"
4.2.0
$ uvx --from actionlint-py actionlint
(no findings)

Admin steps

  • Register trusted publishers: PyPI (workflow publish.yml, environment pypi) and crates.io (workflow publish.yml, environment release). Then delete the PyPI and crates.io token secrets.

Related issues

  • Part of blacklanternsecurity/bbot-enterprise#139
  • Part of blacklanternsecurity/bbot-enterprise#140
  • Part of blacklanternsecurity/bbot-enterprise#149
  • Part of blacklanternsecurity/bbot-enterprise#155
  • Part of blacklanternsecurity/bbot-enterprise#156

TheTechromancer and others added 14 commits December 16, 2025 10:23
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 blacklanternsecurity#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.
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.
@codecov-commenter

codecov-commenter commented Oct 3, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100%. Comparing base (e26e924) to head (0ba31d0).

Additional details and impacted files
@@         Coverage Diff         @@
##            dev    #96   +/-   ##
===================================
  Coverage   100%   100%           
===================================
  Files         3      3           
  Lines       604    605    +1     
===================================
+ Hits        604    605    +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.
@singlerider singlerider changed the title ci: publish on version tags only ci: shared tests and tag-only publish, version from Cargo.toml Oct 3, 2026
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

@liquidsec liquidsec left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will mean anyone with write access can publish. This needs to be discussed.

@singlerider singlerider self-assigned this Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants