fix(release): replace goreleaser pro-only prebuilt builder with OSS-compatible shape#258
Merged
Conversation
The v0.2.0 release pipeline failed with:
yaml: unmarshal errors:
line 63: field prebuilt not found in type config.Build
Root cause: .goreleaser.yaml used `builder: prebuilt` to consume OCB's
per-platform output, but `prebuilt` is a GoReleaser Pro-only feature.
The OSS goreleaser-action installed by the workflow cannot parse it.
Fix: drop goreleaser entirely. The `package` job (renamed from
`goreleaser`) now builds + tar.gz-archives + sha256-checksums the OCB
binaries with inline shell, generates per-archive CycloneDX SBOMs via
syft directly, and creates the GitHub Release via `gh release create
--generate-notes`. Same determinism contract (SOURCE_DATE_EPOCH from
tag commit + numeric-owner + --sort=name + gzip -n + tag-pinned
TRACECORE_VERSION). Same dist/ artifact shape, so downstream sbom /
sign / provenance / attest / ko-publish jobs are unchanged aside from
the `needs:` job-name rename.
The SBOM (anchore/syft) / cosign-keyless / SLSA v1.0 / GitHub
attest-build-provenance chain is preserved end-to-end.
v0.2.0 git tag remains on origin as a "failed release" marker
(deletion blocked by branch-protection). Operator cuts v0.2.1
post-merge to land the first installable release.
Signed-off-by: Tri Lam <tri@maydow.com>
Per fresh-context review of #258: HIGH — tar shape regression vs goreleaser default. Previous shape `tar -C dist/stage -cf - tracecore_${ver}_${os}_${arch}` wrapped contents in a versioned subdir. goreleaser v2's wrap_in_directory defaults to false; deleted .goreleaser.yaml never set it, so the prior path emitted ./tracecore at root. `curl … | tar xz && ./tracecore` operator muscle memory now restored: tar from inside the staging dir with `.` so contents land at archive root. MEDIUM — gh release create is not idempotent. On any retry of the workflow against a tag whose release already exists (transient gh API hiccup, SLSA-reusable failure followed by manual rerun-all-jobs), the previous shape exits non-zero and blocks the downstream chain. goreleaser had `mode: append` semantics. Now: gh release view as a guard, gh release upload --clobber for assets — matches the sign job's bundle-upload pattern. LOW deltas declined: SOURCE_DATE_EPOCH already wired via Makefile mod_timestamp; SLSA reusable v2.1.0→v2.2.0 bump is separate PR; defense-in-depth nullglob count guard not load-bearing (upload-artifact if-no-files-found:error catches it upstream). Signed-off-by: Tri Lam <tri@maydow.com>
This was referenced Jun 1, 2026
trilamsr
added a commit
that referenced
this pull request
Jun 1, 2026
…259) (#263) ## Summary Three concern-isolated doc-rot reconciles, one commit per issue: - **#256** — `components/receivers/pyspy/README.md` + `RUNBOOK.md` reframe the stale 2026-05-22 "Scheduled for deletion at v0.3.0" banner to "deferred to v0.4.0+ per [#222](#222)" with the OTel-Profiles-→-Beta + parca-agent-OTLP-export re-evaluation triggers named verbatim. - **#257** — `docs/rfcs/0013-distro-first-pivot.md` adds deferral banners at §4 Migration timeline (v0.3.0 row) and §Migration/rollout v0.3.0 sequencing; annotates the §7 Deletion list rows + PR-M sequencing entry with explicit `(deferred to v0.4.0+ per #222)` markers. Historical sequencing preserved verbatim (option 1 from the issue). - **#259** — `docs/reproducibility.md` + `docs/notes/reproducibility.md` reconciled against post-PR-#258 inline-shell `package` job: drop all `.goreleaser.yaml` / `.goreleaser.yml` / `goreleaser.yml` signer-workflow references; reframe build narrative around `SOURCE_DATE_EPOCH` + `tar --mtime` + `--sort=name` + `gzip -n` deterministic-byte controls; update download patterns + verification commands to operate on tar.gz archives; add an explicit `sha256sum -c checksums.txt` step so the operator integrity chain (sha256sum → checksums.txt → cosign bundle) is named in the walkthrough. Cosign bundle naming unchanged. ## Root causes - **#256**: banner predates the PR-M deferral memo in #222; PR #254 reconciled `docs/migration/v0.2-to-v0.3.md` but explicitly left the receiver READMEs out of scope. - **#257**: PR #254's References section flagged the RFC body with a "supersede with #222" note but the body itself was untouched. - **#259**: PR #258 (goreleaser → inline shell) deletes `.goreleaser.yaml`; the reproducibility docs additionally referenced a never-existed `.github/workflows/goreleaser.yml` signer-workflow path (the file has always been `release.yml`), so the docs were doubly-broken pre-#258 and singly-broken post-#258. ## Sequencing note PR #258 is the source of truth for the post-pivot inline-shell `package` job referenced by the #259 reconcile. #258 is currently open + green; if #258 merges first, the doc paths are immediately accurate. If this PR merges first, the docs describe the target state and converge once #258 lands. Either order works. ## Test plan - [x] `bash scripts/doc-check.sh` — clean (500 markdown links resolve, 47 non-.md intra-repo links resolve, banned-phrase lint clean, all required sections present, 10 fenced bash/sh blocks in `docs/reproducibility.md` shell-syntax-clean). - [x] `make check` — clean (gofumpt, tidy-check, golangci-lint 0 issues, go vet, go mod verify). - [x] Manual cross-link spot check: confirmed the new `#222` issue links + `docs/migration/v0.2-to-v0.3.md` cross-references resolve; confirmed RFC `(deferred to v0.4.0+ per #222)` markers attached at every flagged line (matrix row, deletion-list rows, §Migration/rollout sequencing entry); confirmed reproducibility docs no longer mention `goreleaser` anywhere via `grep -i goreleaser`. - [x] Verified no in-flight conflicts with PR #254 (already-merged migration-guide reconcile) or PR #258 (still-open inline-shell pivot — touches `.github/workflows/release.yml` + deletes `.goreleaser.yaml`, no overlap with this PR's files). ## Out of scope / follow-ups No new doc-rot noticed beyond the three issues addressed here. ```release-notes docs: reconcile three stale references post-v0.2.0: pyspy README + RUNBOOK + RFC-0013 §Migration now correctly reflect that PR-M (parca-agent recipe + pyspy delete) is deferred to v0.4.0+ pending OTel Profiles → Beta + parca-agent OTLP export (#222); reproducibility docs (docs/reproducibility.md + docs/notes/reproducibility.md) updated for the post-#258 inline-shell `package` job — operator-facing integrity chain (sha256sum → checksums.txt → cosign bundle → SLSA attestation) preserved end-to-end. ``` Closes #256. Closes #257. Closes #259. --------- Signed-off-by: Tri Lam <tri@maydow.com> Co-authored-by: Tri Lam <tri@maydow.com>
3 tasks
trilamsr
added a commit
that referenced
this pull request
Jun 1, 2026
## Summary Codify the release gates per tier (patch / minor / RC / GA) into a single operator-readable doc. Each tier names what must be done BEFORE the release-prep PR opens. - Universal gates: `make check` / `make test` / chart-appversion lockstep / adversarial review / no-AI-footer audit - Patch + minor: doc-check + validator-recipe + migration-guide row + bench gate - RC: ≥12 NORTHSTAR patterns, schema v1.0 RC, soft-locked attrs, deprecation policy, support matrix, compat CI, SLO declared, threat model, ref architectures, production-preset Helm, upgrade guide, SDKs - GA: third-party audit, real-operator integration, externally-verified reproducibility, attrs hard-locked, SLOs binding, launch artifacts Tag-cut steps map to the inline-shell release pipeline shipped via #258 (no goreleaser). Branch-protection caveats note the tag-deletion block. ## Test plan - [x] `bash scripts/doc-check.sh` clean - [x] `make check` clean - [ ] CI gates (verify-test, verify-lint, validator-recipe, build, install-bench) ```release-notes docs(release): RELEASE-CHECKLIST.md formalizes patch / minor / RC / GA release gates ``` Signed-off-by: Tri Lam <tri@maydow.com> Co-authored-by: Tri Lam <tri@maydow.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The
v0.2.0release pipeline failed at theRun goreleaserstep with:Root cause:
.goreleaser.yamlusedbuilder: prebuiltto consume OCB's per-platform output, butprebuiltis a GoReleaser Pro-only feature ("This feature is exclusively available with GoReleaser Pro"). The OSSgoreleaser-actioninstalled by the workflow (distribution: goreleaser,version: ~> v2→ v2.16) cannot parse the field, so the YAML unmarshal fails before any build runs. RFC-0013 PR-A2 assumed OSS support; it does not have it.Chosen fix (Approach C — drop goreleaser entirely):
.goreleaser.yaml.goreleaserjob topackageand inline the build → archive → checksum logic in shell.make buildper-arch (linux/{amd64,arm64}) writes./_build/tracecore; we stage it alongsideLICENSE+README.md, tar with--sort=name --owner=0 --group=0 --numeric-owner --mtime=@$SOURCE_DATE_EPOCH | gzip -n, then append asha256sumline todist/checksums.txt.syft <archive> -o cyclonedx-json=<archive>.sbom.cdx.jsondirectly (same engine the goreleasersboms:stanza shelled out to).gh release create "$TAG" --title "$TAG" --generate-notes [--prerelease] dist/*.tar.gz dist/*.sbom.cdx.json dist/checksums.txt.Tradeoffs:
--generate-notesgives a flat commit list — good enough for routine releases, and operators can hand-edit viagh release edit "$TAG" --notes-file …for marquee releases.mod_timestamp: "{{ .CommitTimestamp }}"templating, but the same SOURCE_DATE_EPOCH is now passed totar --mtimedirectly so byte-reproducibility against the tag commit is preserved.~> v2floating-version risk, no Pro-vs-OSS field-compatibility footgun.The downstream
sbom,sign,provenance,attest, andko-publishjobs are unchanged aside from theneeds:job-name rename (goreleaser→package) and the matchingneeds.<job>.outputs.{tag,hashes}references. SBOM / cosign-keyless / SLSA v1.0 /attest-build-provenancechain is preserved end-to-end.Considered and rejected:
archives.files): still requires goreleaser to know about each binary's existence; withoutprebuilt, there's no OSS-compatible way to tell goreleaser "package this file as an archive without compiling anything".make build): fragile, ugly, leaves a fakemain.goin the tree just to satisfy goreleaser's default builder.Test plan
Ran locally:
actionlint .github/workflows/release.yml— clean.make check— green (gofumpt,tidy-check,golangci-lint,go vet,go mod verify).goreleaser/needs.goreleaserreferences — only intentional historical comments remain.Will be exercised on the
v0.2.1tag push after merge:packagejob builds linux/{amd64,arm64} OCB binaries, archives + checksums, creates the GitHub Release with--generate-notes.sbom(source-tree CycloneDX) uploads to the release.sign(cosign-keyless) signs + verifies tar.gz + checksums.txt; uploads bundles.provenance(SLSA v1.0 reusable workflow) attaches provenance to the release withupload-tag-name: $TAG.attest(GitHubactions/attest-build-provenance) attests each tar.gz.ko-publishbuilds + pushesghcr.io/tracecoreai/tracecore:0.2.1+:latest, cosign-signs by digest, attests image.Reproducible-archive sanity (post-merge, on the runner): two consecutive
make build+tarinvocations against the sameSOURCE_DATE_EPOCHshould produce byte-identical.tar.gzfiles (operator can spot-check viasha256sumin the workflow logs).Followups
v0.2.1after this merges. That is the first installable release. Suggested:git tag -s v0.2.1 -m 'v0.2.1: first installable release (goreleaser-pro fix)' git push origin v0.2.1v0.2.0tag handling: deletion is blocked by branch-protection rules, so the tag stays on origin as a "failed release" marker. No GitHub Release object was ever created against it, sogh release view v0.2.0will continue to 404 — operators landing on the tag should be steered tov0.2.1. (Alternative: a maintainer with admin override can deletev0.2.0if the marker is undesirable; not blocking.)v0.2.0tag points at commit0025969which still carries the old.goreleaser.yaml. The fix only takes effect for tags pushed after this PR merges tomain.docs/notes/reproducibility.mdanddocs/reproducibility.mdreference.github/workflows/goreleaser.yml(a path that has never existed in this repo — workflow isrelease.yml) and describe goreleaser as the build engine. Out of scope here; tracked separately.Reviewer A+ deltas applied (commit 47e4f32)
Per fresh-context review:
tar -C dist/stage -cf - "tracecore_${ver}_linux_${arch}"wrapped contents in a versioned subdir. goreleaser v2'swrap_in_directorydefaults to false, and the deleted.goreleaser.yamlnever set it, so the prior release shape emitted./tracecoreat archive root. Now: tar from inside the staging dir with.so contents land at archive root. Preservescurl … | tar xz && ./tracecoreoperator muscle memory.gh release createmade idempotent. On workflow retries (transient gh API failure, SLSA-reusable manual rerun-all-jobs), the previous shape exited non-zero. Now:gh release viewas guard +gh release upload --clobberfor assets, mirroring thesignjob's bundle pattern.mod_timestamp; SLSA reusable v2.1→v2.2 bump deferred to separate PR; defense-in-depth nullglob count guard not load-bearing (upload-artifactif-no-files-found: errorcatches upstream).