Skip to content

feat(resourcepack): publish SHA-1 and a JSON manifest alongside SHA256 - #27

Merged
TheMeinerLP merged 1 commit into
mainfrom
feat/resourcepack-sha1-manifest
Aug 10, 2026
Merged

feat(resourcepack): publish SHA-1 and a JSON manifest alongside SHA256#27
TheMeinerLP merged 1 commit into
mainfrom
feat/resourcepack-sha1-manifest

Conversation

@TheMeinerLP

@TheMeinerLP TheMeinerLP commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Why

SHA-1 is the hash Minecraft actually uses: resource-pack-sha1 in server.properties and the second argument of setResourcePack(url, hash) are both SHA-1. This workflow only ever published SHA256 — and its header comment claimed that was the value handed to the client. A consumer had no way to obtain the hash it actually needs.

What changes

SHA-1 is added, SHA256 stays. Every archive now ships a checksum file per algorithm plus a JSON manifest:

releases/my-pack-1.4.2.zip          releases/my-pack-latest.zip
releases/my-pack-1.4.2.zip.sha1     releases/my-pack-latest.zip.sha1
releases/my-pack-1.4.2.zip.sha256   releases/my-pack-latest.zip.sha256
releases/my-pack-1.4.2.zip.json     releases/my-pack-latest.zip.json

The manifest carries version, URL, size, commit and every hash in one request. The latest manifest additionally resolves which version the alias currently points at — something no checksum file can express. hashes is an object rather than flat fields, so another algorithm is one more key and not a schema break; schemaVersion marks a real break if one ever happens.

Maintainability — exactly one place names an algorithm. HASH_ALGOS: "sha1 sha256" at the top of the job. Checksum files, manifest entries, the Discord message and the job summary all derive from it; Discord and the summary read their values out of the manifest with jq rather than naming hashes themselves. Adding sha512 means one list entry plus the matching outputs: declaration, which GitHub requires to be static. The validate step rejects a typo in that list before anything is built.

Two refactors carry that:

  • URL construction moved into the meta step. Endpoint, bucket and prefix are plain inputs and never needed the upload to have happened. That lets the build step write a finished manifest instead of the upload step stitching metadata together afterwards.
  • The build step emits the upload plan (src⇥key⇥content-type⇥cache-control). The upload step just iterates over it and knows nothing about algorithms or file names — "what gets published" and "how it gets uploaded" are now separate.

Discord and the job summary lead with SHA-1, noting resource-pack-sha1, because that is the value someone copies into a server config.

Compatibility

Not a breaking change. version, file-name, sha256, url and latest-url are untouched; sha1, manifest-url and latest-manifest-url are additions. Existing consumers keep working unchanged and get the new files for free.

Verification

The run blocks were extracted from the YAML and executed against a test pack with ${{ }} expressions resolved (aws and curl stubbed):

  • Release and snapshot channel, latest-alias true and false — every run clean, with the upload plan carrying the correct keys and cache policies (versioned keys immutable, all latest keys must-revalidate).
  • Reproducibility: two runs, identical SHA-1 and SHA256.
  • sha1sum -c and sha256sum -c pass against both copies — the alias checksum files record the alias' own file name.
  • HASH_ALGOS guard: an empty list and a typo (shaXYZ) fail with an explicit message; sha1 sha256 sha512 passes.
  • bash -n clean across all eight run blocks; markdownlint reports only the four table issues on line 203 that already exist on main.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XjNkUEGG5ASJLryBY2wQST

SHA-1 is the hash Minecraft actually uses - `resource-pack-sha1` in
server.properties and the second argument of `setResourcePack(url, hash)`
are both SHA-1. The workflow only ever published SHA256, and its header
comment claimed that was the value handed to the client, so a caller had
no way to get the hash it needs.

Every archive now ships a checksum file per algorithm plus a JSON manifest
carrying version, URL, size, commit and all hashes at once. The `latest`
manifest also resolves which version the alias currently points at, which
no checksum file can express.

Which algorithms get published is the `HASH_ALGOS` list at the top of the
job - the only place in the file that names one. Checksum files, manifest
entries, the Discord message and the job summary all derive from it, and
the validate step rejects a typo there before anything is built. Adding
sha512 is one list entry plus the matching `outputs:` declaration, which
GitHub requires to be static.

To support that, URL construction moved into the meta step (endpoint,
bucket and prefix are plain inputs and never needed the upload to have
happened), which lets the build step write a finished manifest instead of
the upload step stitching metadata together afterwards. The build step
also emits the upload plan - which local file goes to which key, with
which content type and cache policy - leaving the upload step purely
mechanical and free of any knowledge of algorithms or file names.

Existing outputs are untouched; sha1, manifest-url and latest-manifest-url
are additions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XjNkUEGG5ASJLryBY2wQST
@TheMeinerLP
TheMeinerLP merged commit 01215ee into main Aug 10, 2026
4 checks passed
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