BCR: automate publishing SafeDI to the Bazel Central Registry#287
BCR: automate publishing SafeDI to the Bazel Central Registry#287
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2812886239
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| with: | ||
| tag_name: ${{ github.event.release.tag_name || inputs.tag_name }} | ||
| registry_fork: dfed/bazel-central-registry | ||
| attest: true |
There was a problem hiding this comment.
Disable attestations for this release pipeline
Set attest to false here unless the release job is migrated to bazel-contrib’s release_ruleset workflow. This repository’s release is produced by .github/workflows/publish.yml (custom gh release create flow), and publish-to-bcr documents that source archive attestations from other release flows are rejected by BCR; keeping attest: true will cause the generated BCR submission to fail validation instead of publishing successfully.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Agreed — fixed in f0739aa. Our release workflow is the custom .github/workflows/publish.yml, not bazel-contrib/.github's release_ruleset.yaml, so there are no upstream source-artifact attestations for publish-to-bcr to chain. Set attest: false and dropped the id-token: write / attestations: write permissions that only existed for that path. If we ever migrate the release job, flipping back to true is a one-line change.
Addresses codex P1 on PR #287. The publish-to-bcr reusable workflow only produces meaningful attestations when the release itself is produced by bazel-contrib/.github's `release_ruleset.yaml`, because it reads source-artifact attestations from the release to chain them onto the generated BCR entry. SafeDI's release is produced by our custom `.github/workflows/publish.yml` — there are no upstream attestations to extend, so `attest: true` would either fail to find them or produce meaningless ones. Drop the `id-token: write` / `attestations: write` permissions that only existed for the attestation path. If we ever migrate the release job to `release_ruleset.yaml` (tracked as a separate concern), flip this back to `true`.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f0739aa75c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| { | ||
| "integrity": "", | ||
| "strip_prefix": "{REPO}-{VERSION}", | ||
| "url": "https://github.com/{OWNER}/{REPO}/archive/refs/tags/{TAG}.tar.gz" |
There was a problem hiding this comment.
Switch source template to a stable release asset URL
BCR presubmit treats GitHub archive/... URLs as unstable and fails validation for them, so publishing with this template will produce PRs that block unless a maintainer manually adds @bazel-io skip_check unstable_url each time. Since this workflow is meant to automate BCR submissions on every release, using archive/refs/tags/{TAG}.tar.gz here effectively breaks the automation path; use a stable /releases/download/... source archive URL instead.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 1302650 — .bcr/source.template.json now points at releases/download/{TAG}/{REPO}-{VERSION}.tar.gz, and .github/workflows/publish.yml produces that tarball via git archive --prefix=SafeDI-<version>/ and uploads it as a release asset alongside the existing SafeDITool binaries. Verified locally that the tarball layout matches the strip_prefix in the template.
Addresses codex P1 on PR #287. BCR presubmit flags GitHub's auto- generated `archive/refs/tags/{TAG}.tar.gz` URLs as unstable — the archive contents are considered subject to change (GitHub's tarball format has been tweaked historically), so submissions using them fail validation unless a maintainer adds `@bazel-io skip_check unstable_url` to the BCR PR. For a fully-automated BCR pipeline that defeats the point. Switch to uploading a reproducible source tarball as a release asset. `git archive --prefix=SafeDI-<version>/` from the just- created tag produces the same bytes on every invocation, and the release-asset URL `releases/download/<tag>/SafeDI-<version>.tar.gz` is stable by BCR's definition. Update `.bcr/source.template.json` to reference that URL instead. The `strip_prefix` (`{REPO}-{VERSION}`) already matches `--prefix=SafeDI-<version>/` in the `git archive` call.
|
@codex review |
|
Codex Review: Didn't find any major issues. Can't wait for the next one! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## claude/bazel-example-project-d6f783 #287 +/- ##
=====================================================================
Coverage 100.00% 100.00%
=====================================================================
Files 41 41
Lines 7043 7043
=====================================================================
Hits 7043 7043 🚀 New features to boost your workflow:
|
7547902 to
5136cd9
Compare
Ties SafeDI's release flow into the Bazel Central Registry via
bazel-contrib/publish-to-bcr. Every GitHub release (including
betas) now files a PR to BCR adding a new version entry.
## What's in it
### `.bcr/` — Publish-to-BCR templates
- `metadata.template.json` — module-level metadata (homepage,
maintainer, repository). Copied to `modules/safedi/metadata.json` on
first submission, updated per-version thereafter.
- `source.template.json` — points at GitHub's auto-generated source
tarball (`archive/refs/tags/{TAG}.tar.gz`) with `strip_prefix =
"{REPO}-{VERSION}"`. No need to upload a separate source artifact —
GitHub's tag tarball is reproducible and suffices.
- `presubmit.yml` — BCR validation config. Two stages:
- `verify_safedi_build` — builds the four SafeDI targets against
the archive (`@safedi//Sources/SafeDI`, `//SafeDICore`,
`//SafeDIMacros`, `//SafeDITool`).
- `bcr_test_module` — points at `Examples/ExampleBazelIntegration`
for a downstream smoke test. BCR `cd`s into the example's own
MODULE.bazel workspace, resolves SafeDI via the registry (not the
local_path_override that only applies when the example is root),
and builds the two `swift_library` targets. Catches regressions
in the consumer path that our own build can't.
- `config.yml` — intentionally empty (all config lives in the other
three files).
### `.github/workflows/publish-to-bcr.yml`
- Triggers on `release.published` — every GitHub release fires the
workflow, beta or stable. A `workflow_dispatch` escape hatch lets
us replay a publish after fixing a template bug without cutting a
new release.
- Delegates to `bazel-contrib/publish-to-bcr/.github/workflows/publish.yaml@v1.2.0`
(the canonical reusable workflow).
- `registry_fork: dfed/bazel-central-registry` — push branches there
before filing the PR upstream.
- Authed via the `BCR_PUBLISH_PAT` secret (classic PAT; fine-grained
PATs can't open PRs against public repos per GitHub's roadmap).
### Version stamping
`Scripts/update-version.sh` now also stamps `MODULE.bazel`'s top-level
`module(version = "…")` — scoped to the `module(…)` block so
`bazel_dep(…, version = "X")` lines elsewhere in the file stay put.
`.github/workflows/publish.yml`'s commit step adds `MODULE.bazel` to
`git add`, and the `Show changes` step prints its diff alongside
Package.swift / Plugins/Shared.swift.
`.github/workflows/ci.yml`'s `update-version-check` job gains a
fourth verification: `awk '/^module\(/,/^\)/' MODULE.bazel | grep -q
'version = "99.99.99-test"'`. Same awk range idiom we use in the
sed — scopes the match so a future `bazel_dep` version can't
false-positive.
## Release flow end-to-end
1. Operator runs the existing `Publish` workflow with a version.
2. `build-*` jobs produce the SafeDITool binaries; `assemble-and-
publish` bundles them into an artifact bundle, computes its
checksum, stamps Package.swift + Plugins/Shared.swift +
MODULE.bazel via `update-version.sh`, commits + tags + creates
the GitHub release.
3. GitHub fires `release.published`; `publish-to-bcr.yml` runs; the
reusable workflow clones the tagged source archive, reads
`.bcr/`, generates the BCR entry, pushes to
`dfed/bazel-central-registry`, and opens a PR against
`bazelbuild/bazel-central-registry`.
4. BCR maintainers + presubmit validate the entry; once merged,
downstream consumers can `bazel_dep(name = "safedi",
version = "X")`.
## Not in it (future)
- README / Manual section pointing Bazel users at the BCR module
(blocked on BCR accepting the first submission).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses codex P1 on PR #287. The publish-to-bcr reusable workflow only produces meaningful attestations when the release itself is produced by bazel-contrib/.github's `release_ruleset.yaml`, because it reads source-artifact attestations from the release to chain them onto the generated BCR entry. SafeDI's release is produced by our custom `.github/workflows/publish.yml` — there are no upstream attestations to extend, so `attest: true` would either fail to find them or produce meaningless ones. Drop the `id-token: write` / `attestations: write` permissions that only existed for the attestation path. If we ever migrate the release job to `release_ruleset.yaml` (tracked as a separate concern), flip this back to `true`.
Addresses codex P1 on PR #287. BCR presubmit flags GitHub's auto- generated `archive/refs/tags/{TAG}.tar.gz` URLs as unstable — the archive contents are considered subject to change (GitHub's tarball format has been tweaked historically), so submissions using them fail validation unless a maintainer adds `@bazel-io skip_check unstable_url` to the BCR PR. For a fully-automated BCR pipeline that defeats the point. Switch to uploading a reproducible source tarball as a release asset. `git archive --prefix=SafeDI-<version>/` from the just- created tag produces the same bytes on every invocation, and the release-asset URL `releases/download/<tag>/SafeDI-<version>.tar.gz` is stable by BCR's definition. Update `.bcr/source.template.json` to reference that URL instead. The `strip_prefix` (`{REPO}-{VERSION}`) already matches `--prefix=SafeDI-<version>/` in the `git archive` call.
1302650 to
394ea86
Compare
Summary
Ties SafeDI's release flow into the Bazel Central Registry via
bazel-contrib/publish-to-bcr. Every GitHub release (beta or stable) now files a PR to BCR adding a new version entry.What's in it
.bcr/templatesmetadata.template.json— module metadata (homepage, maintainer, repo).source.template.json— points at a release-asset source tarball (releases/download/{TAG}/{REPO}-{VERSION}.tar.gz). BCR flags GitHub's auto-generatedarchive/...URLs as unstable, so we upload a reproducible tarball ourselves.presubmit.yml— two validation stages:verify_safedi_build— builds the four SafeDI targets (@safedi//Sources/{SafeDI,SafeDICore,SafeDIMacros,SafeDITool}).bcr_test_module— points BCR atExamples/ExampleBazelIntegrationfor a downstream smoke test. The example'slocal_path_overrideis ignored when not root, so BCR resolvessafedifrom the registry and proves the consumer path works.config.yml— intentionally empty..github/workflows/publish-to-bcr.ymlrelease.published(every release, including betas) plus aworkflow_dispatchretry hatch.bazel-contrib/publish-to-bcr/.github/workflows/publish.yaml@v1.2.0.registry_fork: dfed/bazel-central-registry, auth viaBCR_PUBLISH_PATclassic PAT.attest: falsebecause our release is produced by the custompublish.yml, not bazel-contrib'srelease_ruleset— there are no upstream source-artifact attestations to chain.Source tarball + version stamping
.github/workflows/publish.yml— producesSafeDI-<version>.tar.gzviagit archive --prefix=SafeDI-<version>/from the just-created tag and uploads it as a release asset. Stable URL for BCR'sreleases/download/...reference.Scripts/update-version.sh— now also stampsMODULE.bazel's top-levelmodule(version = "…"). Scoped to themodule(…)block via sed's address-range sobazel_depversion lines elsewhere stay put..github/workflows/publish.yml— addsMODULE.bazelto the commit step and shows its diff..github/workflows/ci.yml—update-version-checkjob verifies the stamping end-to-end via the matching awk-range idiom.Release flow end-to-end
Publishworkflow with a version.assemble-and-publishbundles + checksums + stampsPackage.swift/Plugins/Shared.swift/MODULE.bazel+ commits + tags + creates the GitHub release with the source tarball + tool binaries attached.release.publishedevent firespublish-to-bcr.yml→ reusable workflow reads.bcr/, generates the entry, pushes todfed/bazel-central-registry, opens a PR upstream.bazel_dep(name = "safedi", version = "X").Not in it (blocked on first BCR merge)
bazel_dep(name = "safedi", ...)" is premature until the BCR entry actually exists. Add in a follow-up PR once the first submission lands.Test plan
./Scripts/update-version.sh 99.99.99-test abc123…stamps all three files correctly, verified locally.update-version-checkCI step catches theMODULE.bazelstamp viaawk '/^module\(/,/^\)/' ... | grep -q ....git archive --prefix=SafeDI-test/ -o /tmp/test.tar.gz HEADproduces the right layout (verified locally).🤖 Generated with Claude Code