Introduces a static-binary build and Debian package (amd64/arm64) with version/commit/date stamped via -ldflags. Ships section-1 manpages for ctool, ctfetch, and ctail. Adds a `version` subcommand reachable as `ctool version`, `ctool -version`, `ctool --version`, `ctool fetch version`, `ctool tail version`, and via the ctfetch/ctail symlinks. Adds tests covering the dispatcher, fetch/tail argument parsing, and the formatter/helper functions. Adds a retrofit design document modelled on the vpp-maglev one, with FRs and NFRs for each tool and the dispatcher. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
161 lines
6.5 KiB
Makefile
161 lines
6.5 KiB
Makefile
BINARIES := ctool
|
|
MODULE := git.ipng.ch/certificate-transparency/ctfetch
|
|
|
|
NATIVE_ARCH := $(shell go env GOARCH)
|
|
VERSION := 0.1.0
|
|
COMMIT_HASH := $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
|
DATE := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
LDFLAGS := -X 'main.version=$(VERSION)' \
|
|
-X 'main.commit=$(COMMIT_HASH)' \
|
|
-X 'main.date=$(DATE)'
|
|
|
|
# CGO_ENABLED=0 produces fully static binaries: no libc dependency, so the
|
|
# debian package runs on any Linux-amd64/arm64 host regardless of glibc
|
|
# version (or musl). The only behavioural change is that Go's net package
|
|
# uses the pure-Go resolver instead of libc's getaddrinfo, which skips
|
|
# /etc/nsswitch.conf and NSS modules — fine for DNS-only lookups, which
|
|
# is all ctool does when resolving log hostnames.
|
|
export CGO_ENABLED := 0
|
|
|
|
# GO_VERSION is what install-deps-go downloads from go.dev when the
|
|
# system Go is missing or older than this. Matches the go.mod floor.
|
|
# Override on the command line to pull a specific patch release:
|
|
# make install-deps GO_VERSION=1.25.0
|
|
GO_VERSION ?= 1.24.6
|
|
|
|
# GOLANGCI_LINT_VERSION is the minimum golangci-lint version that
|
|
# install-deps-go-tools accepts. install-deps-go-tools always `go
|
|
# install`s @latest, then asserts the resulting binary reports a
|
|
# version >= this floor as a sanity check.
|
|
GOLANGCI_LINT_VERSION ?= 1.64.0
|
|
|
|
.PHONY: all build build-amd64 build-arm64 test lint fixstyle pkg-deb clean install-deps install-deps-apt install-deps-go install-deps-go-tools
|
|
|
|
all: build
|
|
|
|
build:
|
|
mkdir -p build/$(NATIVE_ARCH)
|
|
go build -ldflags "$(LDFLAGS)" -o build/$(NATIVE_ARCH)/ctool ./cmd/ctool/
|
|
|
|
build-amd64:
|
|
mkdir -p build/amd64
|
|
GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o build/amd64/ctool ./cmd/ctool/
|
|
|
|
build-arm64:
|
|
mkdir -p build/arm64
|
|
GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o build/arm64/ctool ./cmd/ctool/
|
|
|
|
# pkg-deb produces one .deb per architecture. Each package contains a
|
|
# single statically-linked ctool binary plus ctfetch and ctail symlinks,
|
|
# and the three section-1 manpages.
|
|
pkg-deb: build-amd64 build-arm64
|
|
debian/build-deb.sh ctool amd64 $(VERSION)
|
|
debian/build-deb.sh ctool arm64 $(VERSION)
|
|
|
|
test:
|
|
go test ./...
|
|
|
|
lint:
|
|
golangci-lint run ./...
|
|
|
|
fixstyle:
|
|
gofmt -w .
|
|
|
|
# install-deps is an opt-in "set up a fresh developer box" target. Tested
|
|
# on Debian Trixie; the apt half should also work on Bookworm and recent
|
|
# Ubuntu LTS. Splits into three sub-targets so they can be run individually:
|
|
#
|
|
# install-deps-apt — Debian-packaged build-time deps (git, make,
|
|
# dpkg-dev, curl, tar).
|
|
# install-deps-go — ensure a Go toolchain >= $(GO_VERSION) is on
|
|
# the system. Downloads the upstream tarball
|
|
# into /usr/local/go when the system Go is
|
|
# missing or older than the go.mod floor.
|
|
# install-deps-go-tools — `go install` the helpers this repo needs
|
|
# (golangci-lint) and assert it is new enough
|
|
# to understand current Go syntax.
|
|
#
|
|
# Each sub-target is idempotent and safe to re-run.
|
|
install-deps: install-deps-apt install-deps-go install-deps-go-tools
|
|
@echo ""
|
|
@echo "==> All build dependencies installed."
|
|
@echo " Make sure these are on PATH:"
|
|
@echo " /usr/local/go/bin (Go toolchain)"
|
|
@echo " \$$(go env GOPATH)/bin (golangci-lint, ...)"
|
|
|
|
install-deps-apt:
|
|
@set -eu; \
|
|
if [ "$$(id -u)" = 0 ]; then SUDO=""; else SUDO="sudo"; fi; \
|
|
echo "==> Installing apt packages (git, make, dpkg-dev, curl, tar)"; \
|
|
$$SUDO apt-get update; \
|
|
$$SUDO apt-get install -y --no-install-recommends \
|
|
git make dpkg-dev ca-certificates curl tar
|
|
|
|
# install-deps-go short-circuits when go env GOVERSION already reports a
|
|
# version >= GO_VERSION. Otherwise it downloads the official upstream
|
|
# tarball (https://go.dev/dl/) and extracts it to /usr/local/go, matching
|
|
# the layout that go.dev recommends and that most Debian setups use for
|
|
# "Go newer than apt provides".
|
|
install-deps-go:
|
|
@set -eu; \
|
|
if [ "$$(id -u)" = 0 ]; then SUDO=""; else SUDO="sudo"; fi; \
|
|
echo "==> Checking Go toolchain (required: $(GO_VERSION)+)"; \
|
|
if command -v go >/dev/null 2>&1; then \
|
|
CURRENT=$$(go env GOVERSION 2>/dev/null | sed 's/^go//'); \
|
|
OLDEST=$$(printf '%s\n%s\n' "$(GO_VERSION)" "$$CURRENT" | sort -V | head -n1); \
|
|
if [ "$$OLDEST" = "$(GO_VERSION)" ] && [ -n "$$CURRENT" ]; then \
|
|
echo " go$$CURRENT already installed (>= $(GO_VERSION)), skipping."; \
|
|
exit 0; \
|
|
fi; \
|
|
echo " go$$CURRENT is older than $(GO_VERSION), upgrading."; \
|
|
else \
|
|
echo " no Go toolchain on PATH, installing."; \
|
|
fi; \
|
|
DEB_ARCH=$$(dpkg --print-architecture); \
|
|
case "$$DEB_ARCH" in \
|
|
amd64) GOARCH=amd64 ;; \
|
|
arm64) GOARCH=arm64 ;; \
|
|
armhf) GOARCH=armv6l ;; \
|
|
*) echo " unsupported architecture: $$DEB_ARCH" >&2; exit 1 ;; \
|
|
esac; \
|
|
TARBALL="go$(GO_VERSION).linux-$$GOARCH.tar.gz"; \
|
|
URL="https://go.dev/dl/$$TARBALL"; \
|
|
echo " downloading $$URL"; \
|
|
curl -fsSL -o "/tmp/$$TARBALL" "$$URL"; \
|
|
echo " installing to /usr/local/go"; \
|
|
$$SUDO rm -rf /usr/local/go; \
|
|
$$SUDO tar -C /usr/local -xzf "/tmp/$$TARBALL"; \
|
|
rm -f "/tmp/$$TARBALL"; \
|
|
echo " installed $$(/usr/local/go/bin/go version)"
|
|
|
|
install-deps-go-tools:
|
|
@set -eu; \
|
|
if ! command -v go >/dev/null 2>&1; then \
|
|
export PATH="/usr/local/go/bin:$$PATH"; \
|
|
fi; \
|
|
echo "==> Installing Go tools via 'go install'"; \
|
|
echo " github.com/golangci/golangci-lint/v2/cmd/golangci-lint"; \
|
|
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest; \
|
|
GOBIN="$$(go env GOBIN)"; \
|
|
if [ -z "$$GOBIN" ]; then GOBIN="$$(go env GOPATH)/bin"; fi; \
|
|
echo "==> Asserting golangci-lint version >= $(GOLANGCI_LINT_VERSION)"; \
|
|
if ! "$$GOBIN/golangci-lint" version >/dev/null 2>&1; then \
|
|
echo " ERROR: $$GOBIN/golangci-lint is not executable" >&2; \
|
|
exit 1; \
|
|
fi; \
|
|
INSTALLED=$$("$$GOBIN/golangci-lint" version 2>&1 | sed -En 's/.*has version v?([0-9][0-9.]*).*/\1/p' | head -n1); \
|
|
if [ -z "$$INSTALLED" ]; then \
|
|
echo " ERROR: could not parse golangci-lint version output" >&2; \
|
|
"$$GOBIN/golangci-lint" version >&2; \
|
|
exit 1; \
|
|
fi; \
|
|
OLDEST=$$(printf '%s\n%s\n' "$(GOLANGCI_LINT_VERSION)" "$$INSTALLED" | sort -V | head -n1); \
|
|
if [ "$$OLDEST" != "$(GOLANGCI_LINT_VERSION)" ]; then \
|
|
echo " ERROR: golangci-lint $$INSTALLED is older than the required $(GOLANGCI_LINT_VERSION)" >&2; \
|
|
exit 1; \
|
|
fi; \
|
|
echo " golangci-lint $$INSTALLED (>= $(GOLANGCI_LINT_VERSION)) OK"
|
|
|
|
clean:
|
|
rm -rf build/
|