Architecture — Releaser (releaser/)
Release tooling for building distribution archives and Docker images. For system-wide overview, see the root ARCHITECTURE.md.
Structure
releaser/
├── release.sh ← top-level entry point: orchestrates multi-arch Docker build + optional push
├── build_clients.sh ← builds CLI client binaries for all target platforms (pure Go cross-compilation)
└── build_server_release.sh ← runs inside Docker: builds server and assembles the release archiveSupporting files referenced by the release process:
server/gen_build_info.sh ← generates version, git info, client manifest as JSON
changelog/ ← one file per version tag (used to build release history in build info)
Dockerfile ← multi-stage build: frontend → clients → Go cross-compile → release archive → runtime imageRelease Pipeline
Entry Points (Makefile)
| Target | Command | Description |
|---|---|---|
make release | releaser/release.sh | Build release archives + client binaries locally (no push) |
make release-and-push-to-docker-hub | PUSH_TO_DOCKER_HUB=true releaser/release.sh | Build + push multi-arch Docker images |
make docker | docker buildx build --load -t rootgg/plik:dev . | Quick local Docker image (single arch) |
make clients | releaser/build_clients.sh | Build CLI clients for all platforms |
release.sh — Orchestrator
Runs on the host machine. Orchestrates the entire release from the project root:
- Version detection: Calls
server/gen_build_info.sh versionto extract the version from the latest git tag (git describe --tags --abbrev=0) - Mint check: Verifies the git repo is clean (
mint=true= no uncommitted changes). Warns if dirty. - Release check: Verifies HEAD matches the version tag (
release=true). Warns if untagged. - Export clients: Runs
docker buildx buildtargetingplik-clients-archive, renames binaries toplik-{version}-{os}-{arch}[.exe]inreleases/ - Build archives: Runs
docker buildx buildtargetingplik-release-archive, outputting.tar.gzarchives toreleases/ - Checksums: Generates
sha256sum.txtfor all release artifacts (archives + client binaries) - Docker push (optional): If
PUSH_TO_DOCKER_HUBis set, builds the final Docker image stage and pushes with tags:rootgg/plik:dev(always)rootgg/plik:{version}(only ifrelease=true)rootgg/plik:latest(only ifrelease=trueand version contains no-suffix, e.g.-RC1,-alpha,-testall prevent tagging as latest)
Environment Variables
| Variable | Default | Description |
|---|---|---|
DOCKER_IMAGE | rootgg/plik | Docker Hub image name |
TAG | dev | Docker tag for non-release builds |
TARGETS | linux/amd64,linux/i386,linux/arm64,linux/arm | Target platforms for Docker buildx |
CLIENT_TARGETS | (from build_clients.sh default) | Override client cross-compilation targets |
CC | (auto-detected) | Override cross compiler |
PUSH_TO_DOCKER_HUB | (unset) | If set, push images to Docker Hub |
Dockerfile — Multi-Stage Build
| Stage | Base | Platform | Purpose |
|---|---|---|---|
plik-frontend-builder | node:24-alpine | $BUILDPLATFORM | Builds Vue webapp (make clean-frontend frontend) |
plik-client-builder | golang:1-bookworm | $BUILDPLATFORM | Builds all CLI clients via releaser/build_clients.sh (runs once, pure Go) |
plik-builder | golang:1-bookworm | $BUILDPLATFORM | Cross-compiles server via releaser/build_server_release.sh, using pre-built clients and webapp |
plik-clients-archive | scratch | — | Exports bare client binaries (used with --output by release.sh) |
plik-release-archive | scratch | — | Exports .tar.gz archives (used with --output for local builds) |
plik-image | alpine:3.21 | per-platform | Runtime image — copies release/ directory, runs plikd as non-root user (UID 1000) |
Optimization: Client binaries are pure Go cross-compilations (no CGO) and produce identical output regardless of host platform. Building them once in
plik-client-builderand sharing across all platform stages avoids redundant compilation (previously 4× per client target).
build_clients.sh — Client Builder
Builds CLI client binaries for all target platforms. Can run standalone or inside Docker:
- Iterate targets: Loops over
CLIENT_TARGETS(comma-separatedOS/ARCHpairs) - Cross-compile: For each target, sets
GOOS/GOARCHand runsmake client - Output: Creates
clients/<os>-<arch>/plik[.exe]+MD5SUMper binary, plusclients/bash/plik.sh
Default Client Targets
darwin/amd64, freebsd/386, freebsd/amd64, linux/386, linux/amd64,
linux/arm, linux/arm64, openbsd/386, openbsd/amd64, windows/amd64, windows/386build_server_release.sh — Server Builder (runs inside Docker)
Called by the Dockerfile inside plik-builder. Performs server compilation and release assembly:
- Clean: Runs
make clean - Verify frontend: Asserts
webapp/distexists (copied from the frontend builder stage) - Verify clients: Asserts
clients/exists (copied from the client builder stage) - Build server: Cross-compiles the server binary with
CGO_ENABLED=1using the appropriate cross compiler:amd64→ native386→i686-linux-gnu-gccarm→arm-linux-gnueabi-gccarm64→aarch64-linux-gnu-gcc
- Assemble release: Creates a
release/directory containing:release/ ├── clients/ ← all cross-compiled client binaries + MD5 checksums + bash client ├── changelog/ ← version changelog files ├── webapp/dist/ ← built web frontend └── server/ ├── plikd ← server binary └── plikd.cfg ← default config - Create archive: Packages everything as
plik-server-{version}-{os}-{arch}.tar.gz
Version & Build Info (gen_build_info.sh)
This script generates build metadata consumed by the server at startup and exposed via GET /version.
Modes
| Argument | Output |
|---|---|
version | Just the version string (from git describe --tags) |
info | Human-readable one-liner |
base64 | Full JSON, base64-encoded (embedded as ldflags at compile time) |
| (none) | Full JSON to stdout |
Generated JSON
{
"version": "1.3.8",
"date": 1707000000,
"user": "builder",
"host": "buildhost",
"goVersion": "go1.26 linux/amd64",
"gitShortRevision": "abc1234",
"gitFullRevision": "abc1234567890...",
"isRelease": true,
"isMint": true,
"clients": [
{ "name": "Linux 64bit", "md5": "...", "path": "clients/linux-amd64/plik", "os": "linux", "arch": "amd64" }
],
"releases": [
{ "name": "1.3.8", "date": 1707000000 }
]
}Key fields:
isRelease:trueif HEAD commit matches the version tag — controls whether Docker Hub gets:{version}tag (and:latestfor stable releases, i.e. versions without a-suffix)isMint:trueif the working tree is clean (no uncommitted changes) — release.sh warns if dirtyclients: Enumerated fromclients/directory, used by the web UI to display download linksreleases: Built fromchangelog/directory entries matched against git tags
How to Cut a Release
- Update
changelog/{version}with release notes - Create a release from GitHub (this creates the tag)
- The
releaseGitHub Actions workflow runs automatically — it builds archives, client binaries, Docker images, and uploads everything to the release page
Testing the Release Process Locally
The release build uses docker buildx for multi-platform images. The default Docker driver does not support multi-platform builds. You need to create a builder first:
docker buildx create --name plik-builder --useThen run the full release locally:
make releaseFor a quick single-platform test (no special builder needed):
TARGETS=linux/amd64 make release