One toolchain across the estate. The tree carried 1.26.0, .1, .3, .4 and .5
at once, so which compiler built a binary depended on which repo it came
from.
Co-authored-by: Hanzo Dev <[email protected]>
The runtime base named neither, and BuildKit refuses that at parse time
— reference.ErrObjectRequired, reported as `object required` — before it
opens a socket. It reads like an unreachable registry and is not one,
which is a long way to walk from the message.
Digests pin what the build actually gets; the tags stay so the reference
still says which image it is.
Co-authored-by: Hanzo Dev <[email protected]>
REPO_OWNER/REPO_NAME built the GitHub API and download URLs from
railwayapp/railpack, so the installer could never find a release under
this fork -- hanzoai/pack has never had one.
REPO_NAME did double duty as both the repository slug (used in the API
and download URLs, needs to be "pack") and the installed command name
(used by `which`/`rm` on uninstall, needs to stay "railpack", the actual
compiled binary name per .goreleaser.yml). Collapsing both into "pack"
would make uninstall run `which pack`, which on many machines resolves to
the unrelated Cloud Native Buildpacks CLI. Split it into REPO_NAME (repo
slug and archive-name prefix, matching the project_name pinned in
.goreleaser.yml) and a new BINARY_NAME (the installed executable), and
routed each use to the right one.
RELEASE.md's GHCR links and package-registry URLs updated to match.
Do not merge until hanzoai/pack has an actual release: push a v* tag once
the prior two commits are on main and the release workflow has published
the builder, runtime, and frontend images. Before that, the download URL
this script builds 404s by construction.
Co-authored-by: Hanzo Dev <[email protected]>
RailpackBuilderImage and RailpackRuntimeImage named
ghcr.io/railwayapp/railpack-{builder,runtime}, so every `pack build`
pulled the upstream vendor's images instead of our own. Point them at
ghcr.io/hanzoai/pack-{builder,runtime}, published by the release
pipeline as of the prior commit.
Also updates the local-dev mirrors of the same reference: the
mise-builder-shell task, the run-with-frontend script, the mise clean
task's image cleanup list, and a stale comment in buildkit/frontend.go.
Snapshots refreshed with the project's own task
(UPDATE_SNAPS=true go test -short ./...) and inspected line by line:
every changed line is exactly the builder/runtime image string, nothing
else. The pre-existing, unrelated php-vanilla frankenphp version drift
that the same refresh also touches was left untouched here.
Do not merge until a release tag has gone through the pipeline from the
prior commit and ghcr.io/hanzoai/pack-builder and pack-runtime actually
exist -- until then this is a correct diff sitting ahead of its own
prerequisite, not something to land on main.
Co-authored-by: Hanzo Dev <[email protected]>
PRODUCTION_GITHUB_REPOSITORY was still hardcoded to the upstream org/repo,
so every derived name (builder, runtime, frontend image) resolved under
ghcr.io/railwayapp/*. Flipping this one knob is enough: the existing
template arithmetic in mise.ci.toml already produces
ghcr.io/hanzoai/pack-builder, ghcr.io/hanzoai/pack-runtime, and
ghcr.io/hanzoai/pack-frontend from it, matching how the rest of the repo
(hanzo.yml, README, go.mod) already names this project.
Also pins goreleaser's project_name explicitly instead of leaving it to
implicit directory-name inference, since install.sh's download URL has to
agree with whatever name goreleaser gives its release archives. Removes an
unused IMAGE_NAME env var left over in the publish-runtime job.
This does not yet change what `pack build` pulls at runtime (core/generate
and core/plan still point at railwayapp) or install.sh (hanzoai/pack has no
releases yet) -- both wait on this pipeline actually publishing once.
Co-authored-by: Hanzo Dev <[email protected]>
Rewrites our own comments, help text, and example READMEs that named
Railway or linked railway.app so they describe what they do instead.
Retargets the changelog generator and RELEASE.md's Actions/release
links at this repo. Leaves upstream issue links, the MIT copyright,
and the builder/runtime/frontend image references untouched -- those
still point at ghcr.io/railwayapp because we don't publish our own
copies of those images yet.
Co-authored-by: Hanzo Dev <[email protected]>
- Migrate module path to github.com/hanzoai/pack across all Go packages
- Remove legacy upstream docs and competitor brand references
- Modernize LLM.md and mise.toml for pristine Hanzo Pack builder
Non-test file http_check.go uses StringOrArray, which lived in run_test.go.
go vet compiles test files, masking the build failure until a real
go build runs. Extract the decoder type and update README to Hanzo Pack.
recipe_test.go is package main at the repo root and calls Detect, fileset
and Plan.Recipe. None of those exist in the tree, and it imports
moby/docker-image-spec, which go.sum no longer carries, so go vet ./...
stops at the root package before it type-checks anything:
recipe_test.go:10:2: missing go.sum entry for module providing package
github.com/moby/docker-image-spec/specs-go/v1
Without the file the root is not a package and go vet ./... is clean.
Co-authored-by: Hanzo Dev <[email protected]>
The nine commits here were a second answer to a question railpack has answered
across 1,077 — and the half we would have had to write and then keep right is
the long tail: every language, every package manager, every version file, every
lockfile dialect. That tail IS the product. Writing it again is how you get a
builder that handles the three languages you tested and mis-detects the fourth
in silence.
Merged rather than force-pushed. The original commits stay in the history as
ancestors instead of being overwritten, and the forge's pre-receive hook was
right to refuse the force — unrelated history landing on main is exactly what
that protection is for. Its own detect.go, recipe.go and build.go go, because
upstream's are the ones that will be maintained.
Upstream is a remote. This stays mergeable, and anything that could go upstream
should: a new language or a fixed detector belongs in a PR to railpack, where
more people keep it right than us.
MIT, upstream's, unchanged. The code is theirs and the fork is ours; relicensing
it under a house licence would be a claim about provenance that is not true.
Co-authored-by: Hanzo Dev <[email protected]>
There was an implementation here: nine commits, four Go files, its own detect.go
and recipe.go. It was a second answer to a question railpack has been answering
for 1,077 commits — and the half we would have had to write and then keep right
is the long tail. Every language, every package manager, every version file,
every lockfile dialect. That tail is the entire product, and writing it again is
how you get a builder that handles the three languages you tested and silently
mis-detects the fourth.
Upstream is MIT and stays MIT. The code is theirs, the fork is ours, and
relicensing someone's MIT work under a house licence is a claim about provenance
that is not true.
The nine commits are kept as the `pre-fork` branch, not deleted.
`upstream` is a remote, so this stays mergeable. Local changes should be the ones
that cannot go upstream — our registry, our fabric, our brand. A new language or
a fixed detector belongs in a PR to railpack, maintained by more people than us.
Co-authored-by: Hanzo Dev <[email protected]>
github.com has no runner for hanzo-build-linux-amd64, so a caller under
.github/workflows is a gate that can never be scheduled. This is the ~7-line
caller on the plane that can (git.hanzo.ai git-runner fleet), pinned @v1.
Co-authored-by: Hanzo Dev <[email protected]>
Superseded: the Hanzo GitHub App pushes a webhook, so the forge tracks GitHub
without a per-repo workflow. This file called git.hanzo.ai/api/v1/.../mirror-sync
— a Gitea API for a system we no longer drive — and would sit inert in every repo.
One mechanism, in one place, instead of ~350 copies of a cron.
git.hanzo.ai mirrors this repo by PULL on a ~10-minute interval, and arcd runs
CI/CD there — so every push waited out that interval before anything built.
This asks Gitea to pull HEAD immediately.
Latency only: the repo already mirrors via the App webhook, so a missing
HANZO_GIT_TOKEN or a failed curl is non-fatal and never fails the push.
Idempotent (mirror-sync just pulls HEAD) and concurrency-coalesced.
This workflow ran on a self-hosted actions-runner-controller pool. ARC is
decommissioned: CI executes inside git.hanzo.ai (Gitea Actions, .hanzo/workflows)
and delivery is cd.hanzo.ai reconciling the reviewed image pin in
hanzoai/universe. GitHub is a mirror and runs nothing.
Removed rather than repointed — there is no GitHub-side pool to move to, and
leaving it would keep ARC load-bearing.
Image lane proven byte-identical across all 5 recipes; static-output export
against a real buildkitd not yet finished. Do not merge until the filesystem
result is proven to export end-to-end + red-reviewed.
pack is the one packer for the fabric: detect a Go/Node/Python/static
context and emit a runnable OCI image with no Dockerfile. Detection and
LLB generation are pure functions (Detect + Recipe), unit-tested by
marshalling the graph so no buildkitd is needed; build.go is the only
impure code and drives BuildKit through dockerui, mirroring the reference
dockerfile frontend. Pinned to moby/buildkit v0.16.0 to match the fabric
daemon. A Dockerfile (dockerfile.v0) remains the escape hatch.