Skip to content

chore(release): verify SHA512 against actual archive (#588)#589

Merged
kcenon merged 1 commit into
developfrom
chore/issue-588-verify-sha512-against-actual-archive
May 3, 2026
Merged

chore(release): verify SHA512 against actual archive (#588)#589
kcenon merged 1 commit into
developfrom
chore/issue-588-verify-sha512-against-actual-archive

Conversation

@kcenon

@kcenon kcenon commented May 3, 2026

Copy link
Copy Markdown
Owner

Closes #588

Part of kcenon/common_system#674.

What

Adds a defense-in-depth verify-archive pre-job to .github/workflows/on-release-sync-registry.yml that downloads the published GitHub release archive and computes its SHA512 before delegating to the shared sync workflow that writes the SHA into portfile.cmake. On any fetch failure, empty archive, or empty-input hash, the job exits 1 with a clear error annotation before the sync workflow runs.

Why

Detected via microsoft/vcpkg#51511 and kcenon/vcpkg-registry#87 - every kcenon port shipped a mismatched SHA512 because the release automation never compared its computed value against the actual archive. Cold-cache vcpkg consumers (new CI runners, fresh users) hit 100% install failure when the SHA in vcpkg-registry/ports/kcenon-database-system/portfile.cmake does not match the bytes at https://github.com/kcenon/database_system/archive/refs/tags/v<version>.tar.gz.

The downstream reusable workflow (kcenon/common_system/.github/workflows/sync-vcpkg-registry.yml) was hardened in kcenon/common_system#676 to compare its computed SHA against the actual archive. This PR adds an independent check in this repo so a release whose archive is unfetchable or empty fails fast in this repo's release run, with a clear log line, before the sync workflow is ever called.

Where

File Change
.github/workflows/on-release-sync-registry.yml New pre-job verify-archive and needs: verify-archive on the existing sync job

Audit summary (other workflows considered)

Workflow Touches portfile SHA? Action
on-release-sync-registry.yml Calls reusable SHA-computing workflow in common_system Hardened (this PR) - adds independent pre-verification
release.yml No (builds and publishes platform artifacts) No change needed
vcpkg-overlay.yml No (local overlay-port build/test, no SHA write) No change needed
ci.yml, sanitizers.yml, coverage.yml, integration*.yml, cve-scan.yml, osv-scanner.yml, static-analysis.yml, sbom.yml, benchmarks.yml, build-Doxygen.yaml, doc-audit.yml No portfile SHA computation No change needed

The actual SHA computation step lives in common_system's reusable workflow (already hardened by #676). The sensible local addition is a pre-flight verification job in this repo's caller, so a bad release fails fast before delegating.

How

The new verify-archive job runs before the existing sync job (declared via needs: verify-archive). It re-fetches the archive with curl -fsSL --retry 3 to a file (not piped) so a 404 cannot silently produce the empty-input SHA512 cf83e1357eefb8bdf.... It additionally rejects:

  1. Any HTTP error from curl (-fsSL ensures non-zero exit).
  2. An empty archive file (! -s "${VERIFY_FILE}").
  3. The empty-input SHA512 constant explicitly, as a belt-and-braces final safety net.

Runtime: ~1-2 s on a typical database_system archive (~670 KB).

Test Plan

How a reviewer can validate the new job fires

  1. Cut a release tag (v0.x.y) - the existing Sync Registry on Release workflow triggers verify-archive, then on success delegates to the sync reusable workflow.
  2. Inspect the run log for the new job. On a healthy release, the step prints:
    Re-fetching https://github.com/kcenon/database_system/archive/refs/tags/v0.x.y.tar.gz for independent verification...
    Release archive verified at https://github.com/kcenon/database_system/archive/refs/tags/v0.x.y.tar.gz
      size:   <bytes>
      sha512: <128-char hex digest>
    

Locally executed and confirmed before push

  • Match path (real v0.1.1 archive): curl -fsSL returns 0, file size 669807 bytes, SHA512 989aeb716da9e79f... (non-empty hash).
  • Bad URL path (nonexistent tag v999.999.999): curl -fsSL returns 22 (404), the if ! branch fires exit 1 with Failed to download release archive for verification: <URL>.
  • Empty file path: rejected by [[ ! -s ... ]] check.
  • Empty-input SHA path: rejected by explicit comparison against the known constant.

The download-to-file pattern (rather than a pipe) is required to make these failure modes detectable - piping into sha512sum would otherwise mask the curl failure with the empty-input hash.

YAML structure validated with js-yaml (jobs: verify-archive, sync; sync.needs: verify-archive).

Breaking Changes

None. The new job is additive; on a successful release it adds ~1-2 s and a few log lines before the existing sync runs. On a SHA mismatch or unfetchable archive (the failure modes this PR is designed to detect) it short-circuits the existing run before the sync workflow is invoked, which is the desired behavior.

Add a defense-in-depth pre-verification job to on-release-sync-registry.yml
that downloads the published GitHub release archive and computes its SHA512
before delegating to the shared sync workflow that writes the SHA into
portfile.cmake.

The downstream reusable workflow
(kcenon/common_system/.github/workflows/sync-vcpkg-registry.yml) was hardened
in kcenon/common_system#676 to compare its computed SHA against the actual
archive. This change adds an independent check in this repo so a release
that produces an unfetchable or empty archive fails fast in this repo's
release run, with a clear log line, before the sync workflow ever runs.

The check uses file-based hashing (curl -fsSL --retry 3 ... -o tmpfile)
rather than piping curl into sha512sum, so a fetch failure cannot silently
produce the empty-input SHA512 (cf83e1357eefb8bdf...). The empty-input
hash is also explicitly rejected as a final safety net.

Audit:
  - on-release-sync-registry.yml: thin caller of common_system reusable
    workflow; this PR adds an independent pre-verification job here.
  - release.yml: builds and publishes platform artifacts, no SHA write.
  - vcpkg-overlay.yml: local overlay-port build/test, no SHA write.
  - All other workflows (ci, sanitizers, coverage, integration, etc.):
    no portfile SHA computation.

Closes #588
Part of kcenon/common_system#674
@kcenon kcenon merged commit 7bd17d6 into develop May 3, 2026
9 checks passed
@kcenon kcenon deleted the chore/issue-588-verify-sha512-against-actual-archive branch May 3, 2026 13:15
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