feat(build): native add-on publish/sign/verify pipeline + forgejo lane (#3425) #3475

Merged
mfreeman451 merged 2 commits from feat/native-addon-publish-pipeline into staging 2026-05-31 21:51:10 +00:00
Owner

What

The native add-on publish / sign / verify pipeline + forgejo lane (build-signing §2.1/2.3/2.4). Faithfully mirrors the proven WASM-plugin rails, adding the per-arch dimension WASM has no analogue for, and wiring in the per-arch artifact signer from #3474.

Components

  • build/native_addons/publish_addon.sh + per-bundle _push sh_binary targets (defs.bzl, aggregated by all_push_targets): push the OCI artifact = bundle zip + bundle-level ed25519 upload-signature (reuses upload_signature_tool) + each per-arch tarball + its agent-release ed25519 signature (addon_artifact_signature_tool). oras stamps each layer's title so (os, arch) is recoverable downstream.
  • scripts/push_all_native_addons.sh — runs every _push target (≈ push_all_wasm_plugins.sh).
  • scripts/sign-native-addon-publish.sh — cosign-signs each pushed artifact by digest (OCI 1.1 referrer + legacy detached signature, identical mechanics to the WASM signer so the verify-then-mirror importer accepts it).
  • scripts/verify-native-addon-publish.sh — verify-before-release: artifactType, the bundle + upload-signature layers + the ed25519 upload-signature, the Cosign signature, and every per-arch tarball against its agent-release signature.
  • scripts/generate-native-addon-import-index.shserviceradar-native-addon-index.json with a per-arch artifacts[] (os/arch + bare-binary sha256 + tarball sha256 + OCI tarball/​signature layer digests) for the §4 importer.
  • .forgejo/workflows/native-addons.ymlworkflow_dispatch lane mirroring wasm-plugins.yml: OpenBao cosign env + the agent-release key (derives the public key for verify) → push → sign → verify → index → upload release asset.

Verification

  • Local (clean): buildifier, bash -n on all scripts, YAML parse; bazel query //build/native_addons:all loads and the three _push targets resolve; the import-index per-arch jq join produces correct {os,arch,sha256,tarball_sha256,tarball_digest,signature_digest} against assembler fixtures + a synthetic OCI manifest.
  • The per-arch signer this drives is unit-tested and was exercised on a real tarball (#3474).

Not validated locally (CI-only)

  • Registry push + Cosign signing run in the forgejo lane: Harbor robot creds and the release/upload ed25519 keys are CI secrets, and cosign-release is reached via the in-cluster OpenBao k8s auth.
  • A live OpenBao validation from this host was blocked by the sandbox (port-forwarding openbao-system to reach the production signing key is beyond the granted scope) — sensible guardrail. Happy to run it if you enable that access (or run the port-forward yourself), but the lane mirrors the in-production WASM signing path that already works.
  • Bundle builds need the linux CI runner (Go cross-compile won't run on a darwin host).

Next

The §4 control-plane importer (Elixir): verify-then-mirror the per-arch artifacts to object storage and record object_key / sha256 / signature on the AddonPackage so the agent's pushed-artifact fetch resolves.

🤖 Generated with Claude Code

## What The native add-on **publish / sign / verify pipeline + forgejo lane** (build-signing §2.1/2.3/2.4). Faithfully mirrors the proven WASM-plugin rails, adding the per-arch dimension WASM has no analogue for, and wiring in the per-arch artifact signer from #3474. ## Components - **`build/native_addons/publish_addon.sh`** + per-bundle **`_push`** `sh_binary` targets (`defs.bzl`, aggregated by `all_push_targets`): push the OCI artifact = bundle zip + bundle-level ed25519 **upload-signature** (reuses `upload_signature_tool`) + **each per-arch tarball + its agent-release ed25519 signature** (`addon_artifact_signature_tool`). `oras` stamps each layer's title so `(os, arch)` is recoverable downstream. - **`scripts/push_all_native_addons.sh`** — runs every `_push` target (≈ `push_all_wasm_plugins.sh`). - **`scripts/sign-native-addon-publish.sh`** — cosign-signs each pushed artifact by digest (OCI 1.1 referrer **+** legacy detached signature, identical mechanics to the WASM signer so the verify-then-mirror importer accepts it). - **`scripts/verify-native-addon-publish.sh`** — verify-before-release: artifactType, the bundle + upload-signature layers + the ed25519 upload-signature, the Cosign signature, **and every per-arch tarball against its agent-release signature**. - **`scripts/generate-native-addon-import-index.sh`** — `serviceradar-native-addon-index.json` with a per-arch `artifacts[]` (`os`/`arch` + bare-binary `sha256` + tarball `sha256` + OCI tarball/​signature layer digests) for the §4 importer. - **`.forgejo/workflows/native-addons.yml`** — `workflow_dispatch` lane mirroring `wasm-plugins.yml`: OpenBao cosign env + the agent-release key (derives the public key for verify) → push → sign → verify → index → upload release asset. ## Verification - **Local (clean):** `buildifier`, `bash -n` on all scripts, YAML parse; `bazel query //build/native_addons:all` loads and the three `_push` targets resolve; the import-index **per-arch jq join** produces correct `{os,arch,sha256,tarball_sha256,tarball_digest,signature_digest}` against assembler fixtures + a synthetic OCI manifest. - The per-arch signer this drives is unit-tested and was exercised on a real tarball (#3474). ## Not validated locally (CI-only) - **Registry push + Cosign signing** run in the forgejo lane: Harbor robot creds and the release/upload ed25519 keys are CI secrets, and `cosign-release` is reached via the in-cluster OpenBao k8s auth. - A live OpenBao validation from this host was **blocked by the sandbox** (port-forwarding `openbao-system` to reach the production signing key is beyond the granted scope) — sensible guardrail. Happy to run it if you enable that access (or run the port-forward yourself), but the lane mirrors the in-production WASM signing path that already works. - Bundle builds need the linux CI runner (Go cross-compile won't run on a darwin host). ## Next The §4 control-plane importer (Elixir): verify-then-mirror the per-arch artifacts to object storage and record `object_key` / `sha256` / `signature` on the `AddonPackage` so the agent's pushed-artifact fetch resolves. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(build): native add-on publish/sign/verify pipeline + forgejo lane (#3425)
Some checks failed
lint / lint (push) Successful in 1m11s
Secret Scan / gitleaks (pull_request) Successful in 57s
lint / lint (pull_request) Successful in 1m53s
Golang Tests / test-go (push) Failing after 2m44s
CI / build (pull_request) Failing after 4m20s
d34b6c5db2
build-signing §2.1/2.3/2.4 + the publish lane. Mirrors the proven WASM-plugin
rails for native add-ons, adding the per-arch dimension WASM lacks.

- build/native_addons/publish_addon.sh + per-bundle `_push` sh_binary targets
  (defs.bzl): push the OCI artifact = bundle zip + bundle-level ed25519
  upload-signature (reused upload_signature_tool) + each per-arch tarball + its
  agent-release ed25519 signature (addon_artifact_signature_tool). oras stamps each
  layer's title so the os/arch is recoverable. all_push_targets aggregates them.
- scripts/push_all_native_addons.sh: runs every _push target.
- scripts/sign-native-addon-publish.sh: cosign-signs each pushed artifact
  (OCI 1.1 referrer + legacy detached signature) by digest — same mechanics as
  the wasm signer so the verify-then-mirror importer accepts it.
- scripts/verify-native-addon-publish.sh: verify-before-release — artifactType,
  bundle + upload-signature layers + the ed25519 upload-signature, the Cosign
  signature, AND every per-arch tarball against its agent-release signature.
- scripts/generate-native-addon-import-index.sh: serviceradar-native-addon-index.json
  with a per-arch artifacts[] (os/arch + bare-binary sha256 + tarball sha256, OCI
  layer digest, and signature layer digest) for the importer.
- .forgejo/workflows/native-addons.yml: workflow_dispatch lane mirroring
  wasm-plugins.yml — OpenBao cosign env + the agent-release key (derives the public
  key for verify), push -> sign -> verify -> index -> upload release asset.

Validated locally: buildifier + shell `bash -n` + YAML parse clean; bazel package
loads and the three `_push` targets resolve; the import-index per-arch jq join
produces correct {os,arch,sha256,tarball_sha256,tarball_digest,signature_digest}
against assembler fixtures. The per-arch signer it drives is unit-tested + was
exercised on a real tarball (#3474). The registry push + cosign signing run in the
forgejo lane (Harbor robot creds + the release/upload keys are CI secrets; OpenBao
cosign-release is reached via the in-cluster k8s auth). Production signing is
CI-only — local registry push and the openbao-system port-forward are not available
from this host.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(build): drop the WASM-style bundle upload-signature; live-validated the pipeline (#3425)
Some checks failed
lint / lint (push) Successful in 1m19s
Secret Scan / gitleaks (pull_request) Successful in 1m8s
lint / lint (pull_request) Successful in 2m25s
Golang Tests / test-go (push) Successful in 2m58s
CI / build (pull_request) Failing after 5m16s
7b61ba9c68
Live-validating the publish pipeline against the real registry + OpenBao surfaced
two bugs and one design mismatch:

1. publish_addon.sh reused the wasm upload_signature_tool for a bundle-level
   ed25519 "upload-signature", but that tool is wasm-specific — it requires a
   plugin.yaml + a single wasm module, which native bundles don't have (addon.yaml
   + per-arch binaries). It failed with "plugin.yaml entry is missing".
   -> Dropped the bundle-level upload-signature entirely. The OCI bundle's
   integrity/provenance is covered by the Cosign signature over the artifact, and
   each per-arch tarball already carries the agent-release ed25519 signature the
   agent verifies. Removed it from publish_addon.sh, the _push targets (defs.bzl),
   verify-native-addon-publish.sh, generate-native-addon-import-index.sh, and the
   forgejo lane (no PLUGIN_UPLOAD_SIGNING needed).
2. oras push rejects absolute file paths, and the verify/index steps recover
   (os, arch) from each layer's org.opencontainers.image.title (which oras sets to
   the path as given). -> publish_addon.sh now stages every layer in one dir and
   pushes by basename, so paths are relative and titles are clean file names.

Live-validated end to end (assembler bundle -> real registry + OpenBao,
throwaway artifact keys, prod cosign-release, --tlog-upload=false, test repo):
- publish_addon.sh pushed the OCI artifact (bundle + per-arch tarball/sig layers,
  clean basename titles, correct media types);
- cosign sign --key hashivault://cosign-release then cosign verify --key
  docs/cosign.pub = Verified OK (and cosign-release's public key == docs/cosign.pub);
- each per-arch tarball signature fetched from the registry verified against the
  agent-release public key.

shell `bash -n`, buildifier, YAML parse, and `bazel query` (3 _push targets) clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Owner

Live-validated against the real registry + OpenBao 🔬

Ran the pipeline end to end on the demo cluster (assembler-built bundle, throwaway artifact keys, prod cosign-release via OpenBao, --tlog-upload=false, a throwaway serviceradar/native-addon-livetest repo). This surfaced + fixed two bugs and one design mismatch (see the latest commit):

  1. Bundle upload-signature dropped. publish_addon.sh reused the wasm upload_signature_tool, but it's wasm-specific (needs plugin.yaml + a single wasm module) — failed with plugin.yaml entry is missing. Native bundles don't fit that shape, and the bundle is already covered by the Cosign signature while each per-arch tarball carries the agent-release ed25519 sig the agent verifies. Removed it everywhere (publish/_push/verify/index/lane).
  2. oras absolute-path rejection. oras push rejects absolute paths, and layer titles (which carry os/arch) must be clean basenames — now stages all layers in one dir and pushes by basename.

Verified end to end:

  • publish_addon.sh → OCI artifact pushed (bundle + per-arch tarball/sig layers, clean basename titles, correct media types).
  • cosign public-key --key hashivault://cosign-release == committed docs/cosign.pub.
  • cosign sign --key hashivault://cosign-releasecosign verify --key docs/cosign.pub = Verified OK.
  • Each per-arch tarball signature fetched from the registry verified against the agent-release public key.

⚠️ Cleanup needed: the throwaway test repo serviceradar/native-addon-livetest is still in Harbor — the serviceradar-ci robot is push-only (403 on delete), so it needs a project-admin to remove. Nothing was written to the public Rekor log (--tlog-upload=false).

## Live-validated against the real registry + OpenBao 🔬 Ran the pipeline end to end on the `demo` cluster (assembler-built bundle, throwaway artifact keys, **prod `cosign-release` via OpenBao**, `--tlog-upload=false`, a throwaway `serviceradar/native-addon-livetest` repo). This surfaced + fixed two bugs and one design mismatch (see the latest commit): 1. **Bundle upload-signature dropped.** `publish_addon.sh` reused the wasm `upload_signature_tool`, but it's wasm-specific (needs `plugin.yaml` + a single wasm module) — failed with `plugin.yaml entry is missing`. Native bundles don't fit that shape, and the bundle is already covered by the Cosign signature while each per-arch tarball carries the agent-release ed25519 sig the agent verifies. Removed it everywhere (publish/_push/verify/index/lane). 2. **oras absolute-path rejection.** `oras push` rejects absolute paths, and layer titles (which carry os/arch) must be clean basenames — now stages all layers in one dir and pushes by basename. **Verified end to end:** - `publish_addon.sh` → OCI artifact pushed (bundle + per-arch tarball/sig layers, clean basename titles, correct media types). - `cosign public-key --key hashivault://cosign-release` == committed `docs/cosign.pub`. - `cosign sign --key hashivault://cosign-release` → `cosign verify --key docs/cosign.pub` = **Verified OK**. - Each per-arch tarball signature **fetched from the registry** verified against the agent-release public key. ⚠️ **Cleanup needed:** the throwaway test repo **`serviceradar/native-addon-livetest`** is still in Harbor — the `serviceradar-ci` robot is push-only (403 on delete), so it needs a project-admin to remove. Nothing was written to the public Rekor log (`--tlog-upload=false`).
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
carverauto/serviceradar!3475
No description provided.