ultimate-gojust
- title
- ultimate-gojust
- type
- toolbox
- summary
- Drop-in Justfile covering Go build, cross-compile, lint, hot reload and database migrations
- tags
- golang, build-automation, just
- language
- Just
- license
- MIT
- created
- 2026-04-07
- updated
- 2026-04-07
A drop-in Justfile that covers the full Go project lifecycle: project scaffolding, building with version injection, cross-compilation, testing with coverage, linting, security scanning, hot reload, Docker, and database migrations. It's the just-based sibling of ultimate-gomake (same author, same features, different runner).
How it works
The justfile is a single file you copy into your project root. It uses just's env_var_or_default() for a configuration cascade: CLI args override env vars, which override .env file values, which override hardcoded defaults. This means you can do just GOOS=darwin build without editing anything.
Version embedding
The build recipe automatically extracts version info from git and injects it via ldflags:
version := `git describe --tags --always --dirty 2>/dev/null || echo "dev"`
git_commit := `git rev-parse --short HEAD 2>/dev/null || echo "unknown"`
ld_flags := "-s -w \
-X '$(go list -m)/pkg/version.Version=" + version + "' \
-X '$(go list -m)/pkg/version.Commit=" + git_commit + "' \
-X '$(go list -m)/pkg/version.Branch=" + git_branch + "' \
-X '$(go list -m)/pkg/version.BuildTime=" + build_time + "' \
-X '$(go list -m)/pkg/version.BuildBy=" + build_by + "'"
This expects a pkg/version package with exported string vars. The -s -w flags strip debug info and DWARF tables for smaller binaries.
Cross-compilation
The build-all recipe loops over seven OS/arch combinations (linux amd64/arm64/armv7, darwin amd64/arm64, windows amd64/arm64), builds static binaries with CGO_ENABLED=0, and tarballs each output. The Windows builds get .exe suffixed automatically.
Dev tooling
just deps installs golangci-lint, gofumpt, govulncheck, mockgen, and Air (hot reloader). just dev downloads an Air config if missing and starts watching for changes. just lint runs golangci-lint with --fix. just security runs govulncheck.
Database migrations
Uses golang-migrate with PostgreSQL and MySQL support. just db-migrate runs pending migrations, just db-rollback reverts one step, just db-reset drops everything. All read DATABASE_URL from the environment.
Entrypoint convention
The repo assumes main/main.go as the build entrypoint, which is uncommon โ the standard Go convention is cmd/<name>/main.go for projects with one or more binaries. The build recipe would need adjustment for cmd/ layouts:
build:
mkdir -p {{bin_dir}}
{{go}} build \
-ldflags '{{ld_flags}}' \
-o {{bin_dir}}/{{project_name}} \
./cmd/{{project_name}}
For multi-binary projects, you'd loop over directories under cmd/.
Interesting patterns to borrow
The most reusable parts for any Go Justfile:
- ldflags version injection โ wire git metadata into binaries at compile time, no code generation needed
- Configuration cascade via
env_var_or_default()โ makes the same Justfile work across dev, CI, and production without forks - Cross-compile loop โ a compact way to produce release binaries for all platforms
- Tool pinning via
go install ...@latestin adepsrecipe โ keeps the team on the same toolchain
Limitations
- Single-binary only โ no built-in support for
cmd/multi-binary layouts - Tool versions pinned to
@latestrather than specific versions, which can cause CI flakiness - The
initrecipe downloads a.gitignorefrom gitignore.io (an external dependency that may go away) - No Makefile equivalent included in this repo (but
ultimate-gomakeexists separately)
49 stars, MIT license. Repo: https://github.com/binbandit/ultimate-gojust