Skip to content

Release 0.3.0: hermetic rules on all six platforms, uv_audit_test, and a six-platform CI matrix - #1

Merged
amsokol merged 9 commits into
mainfrom
windows-hermetic-0.3.0
Oct 9, 2026
Merged

amsokol merged 9 commits into
mainfrom
windows-hermetic-0.3.0

Conversation

@amsokol

@amsokol amsokol commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Release 0.3.0: every public rule works without host tools on linux, darwin, and windows (amd64 and arm64), and CI checks this on all six platforms.

Changes

Dependency updates (every release is at least 2 days old; each sha256 is from the upstream checksum file and checked against the download):

  • protoc-gen-protovalidate-buffa v0.10.2 (catalog and pin).
  • ruff 0.16.10, rules_go 0.64.1.
  • uv 0.12.23, fetched directly from its GitHub release like ruff.
  • markdown: aspect_rules_js 3.5.1, rules_nodejs 6.7.6, Node 24.21.0, pnpm 12.10.1. Node and pnpm checksums are pinned here because those versions are newer than the rules' catalogs.

No host bash or Python on Windows:

  • bazel_utils_core downloads busybox-w32 (amd64, arm64).
  • Test and run rules return a .bat launcher that runs the wrapper with busybox sh. buf_module and buf_generate run their scripts with busybox instead of run_shell. Wrappers are ash-compatible.
  • Prebuilt binaries get a .exe output on Windows. buf_plugin keeps the wrapped binary's extension.
  • protoc-gen-buffa, protoc-gen-buffa-packaging, and protoc-gen-connect-rust have no aarch64 Windows build upstream, so windows-arm64 uses the x64 build under emulation.
  • protoc.plugin zips are extracted at build time with bsdtar from tar.bzl. Bazel 9.2's own zip reader crashes on protobuf-go's zip comment.
  • Bazel's Windows test env has no %LocalAppData% or %USERPROFILE%, so the Go wrappers point them at the test tmpdir.
  • markdownlint_test needs build:windows --enable_runfiles, because rules_js's js_binary needs a runfiles tree.
  • Wrappers find the workspace through the runfiles manifest: on Windows the runfiles tree holds copies, not links to the checkout.
  • aspect_rules_py is dropped: 1.12.1 failed on Windows hosts ("Unsupported platform windows") and broke analysis of the whole build.

Breaking: pip_audit_test is replaced by uv_audit_test, which runs uv audit --frozen with the pinned uv. flags are now uv audit flags, and the binary override attr is uv. The python module no longer ships pip-audit, its lock, or a Python toolchain. uv audit is a uv preview feature; the wrapper opts in with --preview-features audit-command.

Fixed:

  • protoc-gen-grpc-gateway v2.31.0 windows-arm64 pinned protoc-gen-openapiv2's sha256. Bazel's repository cache is keyed by sha256, so Windows arm64 builds could silently get the openapiv2 binary. The new catalog_test fails when one sha256 is pinned for two URLs or a version is missing one of the six platforms.
  • golangci_test and govulncheck_test run in the go.mod directory, so a go.mod below the repo root works. The README documents that layout, but it failed with "directory prefix … does not contain main module".

Tests and CI:

  • tests/ has a fixture for every public rule, including buf_generate with all nine prebuilt plugins.
  • CI is one matrix: ubuntu-24.04, ubuntu-24.04-arm, macos-15-intel, macos-15, windows-2025, windows-11-arm. It runs on pull requests, v* tags, and manual dispatch.
  • Each job builds and tests //... and runs the three format targets, which must leave the checkout unchanged.
  • Windows jobs set a missing --shell_executable, so any use of a host bash fails.

Repo: Cursor rules are removed. CLAUDE.md holds the maintainer notes: the 2-day quarantine, pin locations, Windows and ash rules, testing, and versioning.

Test plan

  • CI green on all six platforms: build, 14 tests, and three format targets with no changes.
  • golangci-lint, buf lint, uv audit, and catalog_test fail when an error is added on purpose.
  • Every wrapper runs under busybox ash locally, both with manifest-only runfiles and with a copied runfiles tree.

🤖 Generated with Claude Code

amsokol and others added 9 commits October 8, 2026 22:32
…toolchain.

protoc-gen-protovalidate-buffa v0.10.2 joins the catalog and becomes the
pin; ruff goes to 0.16.10; uv is pinned to 0.12.23 in this module instead
of aspect_rules_py's 0.11.6; rules_go goes to 0.64.1. The markdown module
moves to aspect_rules_js 3.5.1, rules_nodejs 6.7.6, Node 24.21.0, and
pnpm 12.10.1. Node and pnpm are newer than the rules' catalogs, so their
checksums are pinned here from nodejs.org SHASUMS256.txt and npm.

Every release is at least two days old. Each sha256 comes from the
upstream checksum file and was checked against the downloaded asset. The
README plugin tables now list every catalog version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Aleksandr Sokolovskii <amsokol@gmail.com>
… with uv_audit_test, and test each public rule in CI.

Windows no longer needs a host bash or Python. bazel_utils_core downloads
busybox-w32: test and run rules return a .bat launcher that runs their
wrapper with busybox sh, and buf_module/buf_generate run their scripts with
it. Wrappers are ash-compatible. Prebuilt binaries get a .exe output on
Windows, buf_plugin keeps the wrapped binary's extension, and
protoc-gen-buffa, protoc-gen-buffa-packaging, and protoc-gen-connect-rust
use their x64 build on windows-arm64. protoc.plugin zips are extracted at
build time with the hermetic bsdtar from tar.bzl instead of host Python;
Bazel 9.2's zip reader still crashes on protobuf-go's zip comment.

Breaking: pip_audit_test is replaced by uv_audit_test, which runs
`uv audit --frozen` with the pinned uv. The python module drops pip-audit,
its lock, and the Python toolchain.

golangci_test and govulncheck_test now run in the go.mod directory, so a
go.mod below the repo root works.

tests/ has a fixture for every public rule, including buf_generate with all
nine prebuilt plugins, and CI runs build, test, and the format targets on
linux, darwin, and windows for amd64 and arm64 for pull requests and v*
tags. Cursor rules are removed; CLAUDE.md holds the maintainer notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Aleksandr Sokolovskii <amsokol@gmail.com>
Every language module and the aggregator move to 0.3.0 in lockstep. It is
a minor release because pip_audit_test was removed in favor of
uv_audit_test. README examples pin the v0.3.0 tag, and the CHANGELOG
compare links now start from v0.2.14.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Aleksandr Sokolovskii <amsokol@gmail.com>
macOS 15's BSD sha256sum cannot read a checklist from stdin, so both macOS jobs failed while installing Bazelisk. The step now computes the hash with shasum (or sha256sum) and compares it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Aleksandr Sokolovskii <amsokol@gmail.com>
…logs, and fix the Windows CI checksum step.

The windows-arm64 entry of protoc-gen-grpc-gateway v2.31.0 pinned
protoc-gen-openapiv2's sha256. Bazel's repository cache is keyed by
sha256, so when openapiv2 was fetched first, Windows arm64 builds silently
got the openapiv2 binary under the grpc-gateway name. The entry now pins
3ce0de4e…, from the release's checksums.txt and the downloaded asset; a
scan of every catalog found no other hash shared by two URLs.

catalog_test fails when a sha256 names more than one URL or a version lacks
one of the six platforms. plugin_url moves to defs.bzl so the test and the
download build the same URL.

In CI, Git Bash's shasum prefixed the hash with a backslash for a Windows
path, so the bazelisk check failed on both Windows jobs; it now hashes
stdin. The Rust plugins in the smoke template use strategy: all, so each
writes one root mod.rs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Aleksandr Sokolovskii <amsokol@gmail.com>
aspect_rules_py 1.12.1 registers a host repository that fails with
"Unsupported platform windows", and its Python toolchains made analysis of
the whole build fail on both Windows CI jobs. bazel_utils_python only used
it to download uv, so uv 0.12.23 now comes from its GitHub release through
http_archive and native_binary, like ruff, with the same sha256s from the
release's sha256.sum. uv_audit_test defaults to //:uv.

CLAUDE.md now says to fetch a needed binary directly instead of through
another rule set's module extension.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Aleksandr Sokolovskii <amsokol@gmail.com>
Bazel's Windows test env has no %LocalAppData% or %USERPROFILE%, so Go and
golangci-lint could not find a build cache. The Go wrappers now point both
at the test tmpdir when they are missing.

rules_js's js_binary finds node only through a runfiles tree, which Windows
does not build by default, so markdownlint looked for node.exe under the
workspace. .bazelrc enables runfiles on Windows, and README and CLAUDE.md
say markdownlint_test needs it there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Aleksandr Sokolovskii <amsokol@gmail.com>
… run in the checkout.

With --enable_runfiles, Windows fills the runfiles tree with copies, so the
MODULE.bazel marker resolved inside .runfiles and the wrappers fell back to
the execroot. buildifier then walked Bazel's temp files and markdownlint
linted the Go SDK under bazel-out. _rf_source reads the marker's manifest
entry, which points into the checkout, and falls back to the tree.

Checked with bash and busybox ash on a copied runfiles tree, and the full
build, test, and format flow on linux-amd64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Aleksandr Sokolovskii <amsokol@gmail.com>
The release is tagged on 2026-10-09 (UTC), so the CHANGELOG heading uses that date.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Aleksandr Sokolovskii <amsokol@gmail.com>
@amsokol
amsokol merged commit e1dbef0 into main Oct 9, 2026
6 checks passed
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.

1 participant