diff --git a/.gitignore b/.gitignore index eabcfb3..3e85f49 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -# built binaries (repo root only — not the cmd/ source dirs) -/catalog-diff -# cross-compiled release artifacts (e.g. catalog-diff-linux-amd64) -/catalog-diff-* +# build output: binaries, completions, cross-compiled release artifacts and +# packages all land under dist/ dist/ diff --git a/.woodpecker/release.yaml b/.woodpecker/release.yaml index bc9e653..edcb424 100644 --- a/.woodpecker/release.yaml +++ b/.woodpecker/release.yaml @@ -17,8 +17,8 @@ steps: memory: 2Gi cpu: 2 - # Build every binary into dist/ (consumed by the RPM step) plus the - # cross-platform binaries attached to the Gitea release. + # Build every binary into dist/bin (consumed by the RPM step) plus the + # cross-platform binaries attached to the Gitea release, in dist/release. - name: build image: git.unkin.net/unkin/almalinux9-gobuilder:20260606 commands: @@ -27,12 +27,13 @@ steps: # for the shell instead of substituting them (as pipeline vars) at parse # time. ${CI_COMMIT_TAG} is a real Woodpecker var and stays single-$. - | - for name in catalog-diff; do + mkdir -p dist/release + for name in $$(make print-binaries); do for osarch in linux/amd64 linux/arm64 darwin/amd64 darwin/arm64; do os="$${osarch%/*}"; arch="$${osarch#*/}" GOOS="$$os" GOARCH="$$arch" \ go build -ldflags="-s -w -X main.version=${CI_COMMIT_TAG}" \ - -o "$${name}-$${os}-$${arch}" "./cmd/$${name}" + -o "dist/release/$${name}-$${os}-$${arch}" "./cmd/$${name}" done done depends_on: [test] @@ -126,11 +127,12 @@ steps: NOTES=$$(git log --pretty=format:"- %s") fi tea releases create --tag "${CI_COMMIT_TAG}" --title "${CI_COMMIT_TAG}" --note "$${NOTES}" --login gitea --repo "${CI_REPO}" + # Everything to attach lives in dist/release, so the asset list is the + # directory rather than a hand-kept list of binary names. RPM=$$(ls dist/*.rpm 2>/dev/null | head -1) - ASSETS="catalog-diff-linux-amd64 catalog-diff-linux-arm64 catalog-diff-darwin-amd64 catalog-diff-darwin-arm64" - [ -n "$$RPM" ] && ASSETS="$$ASSETS $$RPM" - sha256sum $$ASSETS > sha256sums.txt - tea releases assets create "${CI_COMMIT_TAG}" $$ASSETS sha256sums.txt \ + if [ -n "$$RPM" ]; then cp "$$RPM" dist/release/; fi + (cd dist/release && sha256sum * >../sha256sums.txt && mv ../sha256sums.txt .) + tea releases assets create "${CI_COMMIT_TAG}" dist/release/* \ --login gitea --repo "${CI_REPO}" depends_on: [upload-rpm] backend_options: diff --git a/AGENTS.md b/AGENTS.md index e2bc53f..0fa72fa 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,9 +30,9 @@ scripts/build-rpm.sh # completions + nfpm packaging .woodpecker/ # CI: build, test, pre-commit (PR) + release (tag) ``` -Adding a binary: create `cmd//`, add the name to `BINARIES` in the -Makefile and to `scripts/build-rpm.sh`, and add its files to -`packaging/nfpm.yaml`. +Adding a binary: create `cmd//`. The Makefile, `scripts/build-rpm.sh`, +`packaging/nfpm.yaml` and the release pipeline all take the shipped list from +`cmd/`, so nothing else needs editing. ## Transport diff --git a/Makefile b/Makefile index 6a33732..a510f08 100644 --- a/Makefile +++ b/Makefile @@ -1,25 +1,31 @@ -# All shipped binaries. Every tool is a separate main package under cmd/, so -# adding one is a matter of adding its name here. -BINARIES := catalog-diff catalog-impact +# All shipped binaries, discovered from cmd/. Every tool is a separate main +# package there, so adding one needs no edit here. +BINARIES := $(notdir $(wildcard cmd/*)) DIST := dist +BINDIR := $(DIST)/bin +COMPDIR := $(DIST)/completions VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo dev) GOFLAGS := -ldflags="-s -w -X main.version=$(VERSION)" OS ?= $(shell go env GOOS) ARCH ?= $(shell go env GOARCH) -.PHONY: all build test lint fmt pre-commit clean install completions rpm rpm-package patch minor major _tag +.PHONY: all build test lint fmt pre-commit clean install completions print-binaries rpm rpm-package patch minor major _tag all: build -# Build every binary into dist/ so the nfpm packaging step +# Build every binary into dist/bin so the nfpm packaging step # (scripts/build-rpm.sh) can find them. Each main package needs its own -o, so # they are built individually rather than with a single ./... invocation. build: @for b in $(BINARIES); do \ echo "building $$b"; \ - CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) go build $(GOFLAGS) -o $(DIST)/$$b ./cmd/$$b || exit 1; \ + CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) go build $(GOFLAGS) -o $(BINDIR)/$$b ./cmd/$$b || exit 1; \ done +# The binary list, for CI steps that cross-compile the same set. +print-binaries: + @echo $(BINARIES) + test: go test -v -race ./... @@ -33,18 +39,19 @@ pre-commit: pre-commit run --all-files clean: - rm -rf $(DIST) $(BINARIES) + rm -rf $(DIST) install: go install $(GOFLAGS) ./... -# Generate bash/zsh/fish completions for every binary into dist/completions. +# Generate bash/zsh/fish completions for every binary into dist/completions, +# named and laid out exactly as they install (the RPM globs these directories). completions: build - @mkdir -p $(DIST)/completions + @mkdir -p $(COMPDIR)/bash $(COMPDIR)/zsh $(COMPDIR)/fish @for b in $(BINARIES); do \ - $(DIST)/$$b completion bash > $(DIST)/completions/$$b.bash; \ - $(DIST)/$$b completion zsh > $(DIST)/completions/_$$b; \ - $(DIST)/$$b completion fish > $(DIST)/completions/$$b.fish; \ + $(BINDIR)/$$b completion bash > $(COMPDIR)/bash/$$b; \ + $(BINDIR)/$$b completion zsh > $(COMPDIR)/zsh/_$$b; \ + $(BINDIR)/$$b completion fish > $(COMPDIR)/fish/$$b.fish; \ done # Build the binaries then package them (with completions) into an RPM via nfpm. diff --git a/README.md b/README.md index 8d5b79b..ae02b83 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ persisted on the server. ```bash dnf install puppet-catalog-tools # from the artifactapi rpm-internal repo # or -make build # -> dist/ +make build # -> dist/bin/ ``` # catalog-diff diff --git a/packaging/nfpm.yaml b/packaging/nfpm.yaml index ba195ef..e9bab8a 100644 --- a/packaging/nfpm.yaml +++ b/packaging/nfpm.yaml @@ -22,44 +22,26 @@ replaces: provides: - puppet-catalog-tools +# Globs, so a new tool under cmd/ ships without editing this file. contents: - - src: dist/catalog-diff - dst: /usr/bin/catalog-diff + - src: dist/bin/* + dst: /usr/bin file_info: mode: 0755 owner: root group: root - - src: dist/catalog-impact - dst: /usr/bin/catalog-impact - file_info: - mode: 0755 - owner: root - group: root - - # Shell completions (generated by scripts/build-rpm.sh before packaging). - - src: dist/completions/catalog-diff.bash - dst: /usr/share/bash-completion/completions/catalog-diff + # Shell completions (generated by scripts/build-rpm.sh before packaging, + # already named as they install). + - src: dist/completions/bash/* + dst: /usr/share/bash-completion/completions file_info: mode: 0644 - - src: dist/completions/_catalog-diff - dst: /usr/share/zsh/site-functions/_catalog-diff + - src: dist/completions/zsh/* + dst: /usr/share/zsh/site-functions file_info: mode: 0644 - - src: dist/completions/catalog-diff.fish - dst: /usr/share/fish/vendor_completions.d/catalog-diff.fish - file_info: - mode: 0644 - - - src: dist/completions/catalog-impact.bash - dst: /usr/share/bash-completion/completions/catalog-impact - file_info: - mode: 0644 - - src: dist/completions/_catalog-impact - dst: /usr/share/zsh/site-functions/_catalog-impact - file_info: - mode: 0644 - - src: dist/completions/catalog-impact.fish - dst: /usr/share/fish/vendor_completions.d/catalog-impact.fish + - src: dist/completions/fish/* + dst: /usr/share/fish/vendor_completions.d file_info: mode: 0644 diff --git a/scripts/build-rpm.sh b/scripts/build-rpm.sh index 382e1cc..b88b361 100755 --- a/scripts/build-rpm.sh +++ b/scripts/build-rpm.sh @@ -12,24 +12,37 @@ cd "${ROOT_DIR}" VERSION="${1:-${CI_COMMIT_TAG:-0.0.0-dev}}" VERSION="${VERSION#v}" # strip a leading v PACKAGE="puppet-catalog-tools" -BINARIES=(catalog-diff catalog-impact) DIST="dist" +BIN_DIR="${DIST}/bin" +COMP_DIR="${DIST}/completions" + +# Every tool is a main package under cmd/, so the shipped list is the contents +# of cmd/ — the same list the Makefile builds. +BINARIES=() +for dir in cmd/*/; do + BINARIES+=("$(basename "${dir}")") +done +if [ ${#BINARIES[@]} -eq 0 ]; then + echo "ERROR: no binaries found under cmd/" >&2 + exit 1 +fi for b in "${BINARIES[@]}"; do - if [ ! -f "${DIST}/${b}" ]; then - echo "ERROR: ${DIST}/${b} not found; run 'make build' first" >&2 + if [ ! -f "${BIN_DIR}/${b}" ]; then + echo "ERROR: ${BIN_DIR}/${b} not found; run 'make build' first" >&2 exit 1 fi done # Generate shell completions from the freshly built binaries so they always -# match the shipped flags/subcommands. -COMP_DIR="${DIST}/completions" -mkdir -p "${COMP_DIR}" +# match the shipped flags/subcommands. They are written under the name and +# directory they install as, because nfpm globs these directories. +rm -rf "${COMP_DIR}" +mkdir -p "${COMP_DIR}/bash" "${COMP_DIR}/zsh" "${COMP_DIR}/fish" for b in "${BINARIES[@]}"; do - "./${DIST}/${b}" completion bash >"${COMP_DIR}/${b}.bash" - "./${DIST}/${b}" completion zsh >"${COMP_DIR}/_${b}" - "./${DIST}/${b}" completion fish >"${COMP_DIR}/${b}.fish" + "./${BIN_DIR}/${b}" completion bash >"${COMP_DIR}/bash/${b}" + "./${BIN_DIR}/${b}" completion zsh >"${COMP_DIR}/zsh/_${b}" + "./${BIN_DIR}/${b}" completion fish >"${COMP_DIR}/fish/${b}.fish" done export PACKAGE_NAME="${PACKAGE}"