These are the product’s technical docs at this revision. Historical version names and status notes are preserved; see Releases for download qualifications.
Read as MarkdownGo-only release packaging
On this page
Build the local packager with Go 1.26 or newer and Git 2.x. It uses the Go standard library and invokes only Git and Go, using argument arrays. It runs without Python, a Unix shell, Docker, provider CLIs or a provider account.
go build -trimpath -o hn-release ./cmd/hn-release
hn-release --source . --rev COMMIT --version 0.0.2-dev --out ../release-0.0.2-dev
On Windows, build hn-release.exe and invoke hn-release.exe (or its full
path). No shell syntax or platform archive utility is required by the command.
The parent of the output directory must already exist; the output directory
itself must be new. Even an empty existing directory or a symbolic link is
refused. Build failures and cancellation leave no published output directory.
The final local directory transfer is not a crash-atomic filesystem transaction;
after a process or machine crash, inspect any partial directory and select a new
output directory for a fresh run.
--rev, --version and --out are required. The source defaults to the current
directory. A release version has the form X.Y.Z or X.Y.Z-prerelease, without
a leading v, path separators, whitespace or build metadata. The version is
injected into main.version; the normal source build retains 0.0.1-dev.
Historical source without a linker-settable variable is refused rather than
quietly producing an executable with the wrong version.
The default targets are linux/amd64, linux/arm64, darwin/amd64 and
darwin/arm64. The default variants are standard and native-only.
For a subset, use comma-separated --targets and --variants, for example:
hn-release --rev COMMIT --version 0.0.2-dev --out ../release-linux --targets linux/amd64 --variants native-only
Unknown or duplicate targets/variants are refused. Windows CLI distribution is
outside this release matrix. native-only builds with nogithub,noforge:
nogithub excludes GitHub before all-adapter noforge support is integrated,
and remains GitHub-specific. The combined tags exclude all installed network
adapters once noforge is integrated. They retain native Git collaboration.
Source and build inputs
Commit the source before packaging. Tracked worktree/index changes are refused.
Before checking cleanliness, the command inspects effective local Git
configuration (including worktree configuration and includes) without running
helpers. Configured filter.*.clean or filter.*.process commands are refused,
even for an otherwise clean checkout. Use a clean checkout without executable
filters. Filesystem monitors are disabled. Partial-clone/promisor configuration
and indexed submodules are refused before inspection can start fetch/transport
helpers or recurse into another repository's executable configuration. Source
objects must already be present locally.
Untracked and ignored files are excluded, including local binaries and private
working files. The named revision is resolved once to its commit and tree;
changing HEAD or adding refs/replace cannot silently substitute its contents.
The exact committed tree is read from Git blobs rather than git archive, so
export-ignore and export-subst do not remove or rewrite committed source.
Intentionally committed material is included, including historical/governance
files; this command is not a secret scrubber.
Links, submodules, nonportable paths, Windows-reserved names and case-colliding
paths are refused before writing output. Archive paths always use /.
Committed executable files use mode 0755; other files use 0644.
All archive member times use the source commit timestamp; owner/group names,
IDs, access/change times and gzip headers are normalized. Members and checksum
entries are sorted. Source archive members are exactly the regular committed
tree, under one versioned root directory.
Builds extract that tree into a fresh temporary directory. The command disables
CGO, workspace selection, ambient Go flags/experiments, VCS stamping and module
networking; it uses -mod=readonly, -trimpath, -buildvcs=false and linker
flags -s -w -buildid= -X main.version=VERSION. Target baselines are
GOAMD64=v1 and GOARM64=v8.0. GOTOOLCHAIN=local prevents an implicit compiler
download. The selected Go compiler must already be installed. The ordinary Go
compiler cache may be reused; source, output and temporary build paths do not
enter archive provenance or executable bytes.
Assets and verification
The full matrix generates eleven files:
- Eight
hubnot_VERSION_OS_ARCH[_native-only].tar.gzbinary archives. hubnot_VERSION_source.tar.gzwith the exact committed source.PROVENANCE.jsonbinding source commit/tree/timestamp, compiler/version and every archive digest, including each binary's build inputs/executable digest.SHA256SUMScovering every generated asset except itself.
Each binary archive includes hn, LICENSE, README.md, optional
CHANGELOG.md, the committed docs/ tree, INSTALL.md and BUILD.json under
its asset root. BUILD.json records source/compiler/version/target/variant,
controlled build flags/environment and the executable SHA-256. It does not claim
a digest of the containing archive. PROVENANCE.json inventories those final
archives without a circular self-digest; its own digest is in SHA256SUMS.
Schemas are hn.release/1 and hn.release-build/1.
Run the command twice using the same committed source, Go compiler, version, target set and variant set, choosing different new output directories. Compare every file byte-for-byte, independently inspect archive member paths, contents and modes, and recompute the listed SHA-256 values. Reordering the requested target/variant sets does not change outputs. A changed compiler or committed tree is a changed input and requires new evidence.
The package tests independently read the gzip/tar archives, verify their metadata and exact source selection, execute the Linux AMD64 fixture binary to check its reported version, and recompute executable/archive/checksum bindings. They also cover dirty input, replace refs, hostile filenames, duplicate/unknown inputs, output collisions, compiler failures and cancellation.
Platform evidence and publication boundary
Before packaging a migration change, run the filesystem portability gates on Linux and macOS with their normal temporary environments. The hosted PR workflow runs those same Go commands. Do not add physical-path or TMPDIR workarounds to make acceptance pass. Case-collision fixtures must construct committed Git trees rather than assume the checkout's filesystem is case-sensitive. Published binary runtime qualification remains a separate check for each target and variant; a source test is not a substitute.
| Platform | WP01 verification scope |
|---|---|
| Linux AMD64 packager host | Executed packaging and archive/refusal tests with Go 1.26.4. |
| Linux/macOS AMD64/ARM64 artifact targets | Cross-compilation and archive inspection; runtime execution must be reported separately for each target. |
| macOS packager host | Cross-compilation only; host runtime remains unverified. |
| Windows packager host | Cross-compilation only; host runtime remains unverified. |
Cross-compile the packager by setting GOOS=darwin or GOOS=windows and the
desired GOARCH in the invoking environment, then running
go build -trimpath -o OUTPUT ./cmd/hn-release. This is compilation evidence,
not evidence that it was executed on those hosts. Record exact source hashes,
commands, results and host observations with the review evidence.
Packaging creates local reviewable assets. Publication, tag creation, signing,
Apple notarization and runtime qualification are separate operations. No command
here publishes a release, changes tags or modifies project policy. Published
v0.0.1-dev, its assets and its historical Python packaging asset remain
unchanged; use this Go command prospectively for subsequent releases.