A composite GitHub Action that generates binary delta patches with
zig-bsdiff and publishes them in
the layout the binpatch library reads at download time.
It is the CI-side other half of the binpatch wire contract: the library
applies patch chains it discovers from a registry / release; this Action
produces and publishes those chains. The two must stay in lockstep — the tag
scheme, annotation keys, artifact-type strings, layer titles, and the
uncompressed-binary SHA-256 are all load-bearing. A drift here breaks live delta
upgrades.
Each mode maps 1:1 to a CI job so you can drop it into an existing generate/publish job graph without reshaping it.
mode |
What it does |
|---|---|
generate-ghcr |
Diff freshly built binaries against the previous GHCR nightly, size-gate the patches, leave them in patches/ for a later publish step. |
publish-ghcr |
Push the compressed binaries to the registry (:<nightly-tag>), create the immutable <nightly-tag-prefix><version> tag, and push the patch manifest (:<patch-tag-prefix><version>) with the integrity annotations the client reads. |
generate-release |
Diff freshly built binaries against the previous stable GitHub Release, size-gate, leave them in patches/ for a release-artifact upload (e.g. consumed by Craft). |
- Nightly binaries: tag
<repo>:<nightly-tag>(defaultnightly), immutable copy<repo>:<nightly-tag-prefix><version>(defaultnightly-<version>), artifact-type<artifact-type-prefix>.nightly, layer titles = bare filenames (push runs from insideartifacts-dir). - Patches: manifest tag
<repo>:<patch-tag-prefix><version>(defaultpatch-<version>), artifact-type<artifact-type-prefix>.patch, annotations:from-version=<prevVersion>— the chain back-pointer.sha256-<binaryName>=<hex>— the target integrity anchor, computed from the uncompressed binary. This is the sole trust anchor the client verifies after applying a chain.
- Size gate: a patch larger than
max-ratio% (default 50) of the gzipped binary is dropped (kept under the client's 60%SIZE_THRESHOLD_RATIOwith margin). - Format: patches are TRDIFF10 + zstd, produced by
zig-bsdiff --use-zstd.
Reference the Action by its published ref, e.g. uses: BYK/binpatch/action@v0.1.0
(or by local path uses: ./action if you vendor this repo). The calling job must
provide the built binaries via actions/download-artifact before calling the
Action. The ghcr modes need packages: write permission and a github-token
that can push to the registry.
See action.yml for the full list and defaults. The commonly
overridden ones:
| Input | Default | Notes |
|---|---|---|
mode |
— | required; one of the three modes above. |
version |
"" |
Required for the ghcr modes; unused by generate-release. |
repo |
"" |
Registry repo path (ghcr modes), lowercase. |
registry |
ghcr.io |
OCI registry host. |
new-binaries-dir |
new-binaries |
Uncompressed patch sources. |
new-gz-dir |
new-binaries |
.gz binaries for the size gate. |
binaries-dir |
binaries |
(publish) uncompressed binaries for SHA-256. |
artifacts-dir |
artifacts |
(publish) .gz layers to push. |
patches-dir |
patches |
Where patches are written / read. |
binary-glob |
* |
Selects binaries to diff (e.g. lore-*). |
max-ratio |
50 |
Size-gate percentage. |
from-version |
"" |
publish-ghcr: the previous version the patches diff against. Pass from generate-ghcr.outputs.from-version so the annotation matches the actual source. When empty, falls back to registry re-derive. |
zig-bsdiff-version / zig-bsdiff-sha256 |
pinned | Encoder, SHA-verified. |
oras-version / oras-sha256 |
pinned | OCI client, SHA-verified. |
The patch manifest's from-version annotation must match the actual source
binary the bytes were generated from — binpatch verifies only the final
output SHA. Wire the value from generate-ghcr to publish-ghcr:
- uses: BYK/binpatch/action@vX.Y.Z
id: gen
with:
mode: generate-ghcr
version: ${{ steps.changes.outputs.nightly-version }}
repo: getsentry/cli
new-binaries-dir: ${{ steps.build.outputs.dir }}
new-gz-dir: ${{ steps.build.outputs.gz-dir }}
- uses: BYK/binpatch/action@vX.Y.Z
if: steps.gen.outputs.has-patches == 'true'
with:
mode: publish-ghcr
version: ${{ steps.changes.outputs.nightly-version }}
repo: getsentry/cli
artifacts-dir: ${{ steps.build.outputs.gz-dir }}
binaries-dir: ${{ steps.build.outputs.dir }}
# CRITICAL: stamp the annotation with the value the generate step actually
# used, not a re-derivation of the registry state. See BYK/binpatch#40.
from-version: ${{ steps.gen.outputs.from-version }}| Output | Notes |
|---|---|
has-patches |
'true' when at least one patch survived the size gate. |
from-version |
The previous version the patches diff against (may be empty). |