Skip to content

build: harden release provenance and package metadata - #1

Merged
Vonng merged 1 commit into
masterfrom
build/harden-release-pipeline
Aug 3, 2026
Merged

build: harden release provenance and package metadata#1
Vonng merged 1 commit into
masterfrom
build/harden-release-pipeline

Conversation

@Vonng

@Vonng Vonng commented Aug 3, 2026

Copy link
Copy Markdown
Member

Pre-release hardening ahead of the 0804 authoritative release. No change to how packages are built or where they install; the packaging itself is left intact.

Provenance

Every mcli published so far is stamped +dirty / vcs.modified=true. GoReleaser writes into dist/ before building, dist/ was not ignored, so the Go toolchain saw an untracked path and marked every release binary as built from a modified tree — breaking the link between a published artifact and its tag.

  • Ignore dist/.
  • Add buildscripts/verify-build-provenance.sh, run from both the release and test workflows, asserting all six binaries carry vcs.revision == HEAD and vcs.modified=false.
  • Assert a clean checkout before building a release.
  • Drop the root .goreleaser.yml. Nothing referenced it, and it had diverged into a config that would publish a non-draft release in replace mode and push pgsty/mc:latest if goreleaser were ever run without --config.
  • Replace go mod tidy in the release hooks with go mod verify, and gate tidiness on PRs instead, so a release build can no longer rewrite go.mod.
  • find_binary must resolve exactly one binary per architecture instead of silently taking the first match.

Package metadata

  • SPDX identifier AGPL-3.0-or-later (was AGPLv3), Section: utils (was empty), and a description that describes the client rather than the object store.
  • /usr/local/bin/mcli is unchanged: minio/pkger hardcodes that destination, so this matches every official MinIO package.

Verification

test-release.yml could not pass on ubuntu-latest. Debian's rpm2cpio exits non-zero even when it writes a correct payload, so the payload comparison tripped set -o pipefail:

PIPESTATUS = 1 0 0   (rpm2cpio, cpio, sha256sum)

RHEL-family rpm2cpio returns 0, which is why it went unnoticed. This workflow last ran on 2026-03-12 against the pre-nFPM version; the current form has never executed. Replaced with rpm -K plus FILEDIGESTS.

  • RPM metadata expectations are now sourced from sign-release-rpms.sh, so nfpm.yml and the signing script cannot drift apart and strand a release part-way through signing.
  • Dockerfile.goreleaser is built and smoke-tested in CI. docker-release.yml is dispatch-only, so the image was otherwise never built until a real publish.
  • Architecture fields and apk metadata are asserted.

CI

  • Every action pinned to a commit SHA; dependabot added to keep them current.
  • permissions: contents: read on go.yml and vulncheck.yml.
  • Removed issues.yaml, which fed miniohq's project board using a secret this fork does not have; repointed the issue template away from MinIO's Slack.

Local rehearsal

Full pipeline run in an isolated clone: goreleaser check → 6 binaries → provenance verified → 6 packages → all RPM/DEB/APK assertions → container build and run. The 93-line validation step was extracted verbatim from this YAML and executed on a Debian/Ubuntu toolchain (exit 0). Upgrade paths 0801 → 0804 and 0803 → 0804 verified for rpm, deb and apk.

CI is the remaining proof layer — in particular the pinned action SHAs and the rpm2cpio fix, both of which can only be confirmed on a real runner.

🤖 Generated with Claude Code

Every mcli published so far is stamped as built from a dirty tree, and
several guards around the release were either unreachable or untested.

Provenance:

- Ignore dist/. GoReleaser writes there before building, so the Go
  toolchain saw an untracked path and marked every release binary
  +dirty / vcs.modified=true, breaking the link between an artifact and
  its tag.
- Add buildscripts/verify-build-provenance.sh and run it from both the
  release and test workflows, so a stray untracked file fails the build
  rather than silently degrading provenance.
- Assert a clean checkout before building a release.
- Drop the root .goreleaser.yml. Nothing referenced it, and it had
  diverged into a config that would publish a non-draft release in
  replace mode and push pgsty/mc:latest if goreleaser were ever invoked
  without --config.
- Replace `go mod tidy` in the release hooks with `go mod verify` so a
  release build can no longer rewrite go.mod, and gate tidiness on PRs.
- Require find_binary to resolve exactly one binary per architecture
  instead of silently taking the first match.

Package metadata:

- Use the SPDX identifier AGPL-3.0-or-later, set Section: utils, and
  describe the client rather than the object store.
- Keep /usr/local/bin/mcli. minio/pkger hardcodes that destination, so
  this matches every official MinIO package.

Verification:

- test-release.yml could not pass on ubuntu-latest: Debian's rpm2cpio
  exits non-zero even when it writes a correct payload, so the payload
  comparison tripped `set -o pipefail`. Use rpm -K and FILEDIGESTS.
- Take the RPM metadata expectations from sign-release-rpms.sh so
  nfpm.yml and the signing script cannot drift apart and strand a
  release part-way through signing.
- Build Dockerfile.goreleaser in CI. docker-release.yml is dispatch-only,
  so the image was otherwise never built until a real publish.
- Assert architecture fields and apk metadata.

CI:

- Pin every action to a commit SHA and add dependabot to keep them fresh.
- Add contents: read to go.yml and vulncheck.yml.
- Remove issues.yaml, which fed miniohq's project board using a secret
  this fork does not have, and repoint the issue template away from
  MinIO's Slack.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Vonng
Vonng merged commit 4c4dcc4 into master Aug 3, 2026
9 of 11 checks passed
@Vonng
Vonng deleted the build/harden-release-pipeline branch August 3, 2026 13:06
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