From bcc283c6b554723dd128b276acdd9ae490685b83 Mon Sep 17 00:00:00 2001 From: Marc Nuri Date: Thu, 21 May 2026 12:22:42 +0200 Subject: [PATCH 1/4] chore(build): align Makefile with project conventions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure the Makefile to follow the same conventions used in kubernetes-mcp-server, podman-mcp-server, and com.marcnuri.automated-tasks: - Add suva.sh-style `make help` with `##@` category banners (Build / Test / Code Quality / Development / Release) and per-target `##` doc strings. - Switch `clean` to the `CLEAN_TARGETS +=` pattern so per-concern modules can contribute their own paths. - Split `release` into `build/release.mk`, auto-included via `-include build/*.mk` so additional concerns (CI, packaging) can land without churning the top-level Makefile. - Wire `scripts/check-authors.sh` in as a first-class `make check-authors` target so the linter is discoverable via `make help`. `ARGS='--fix'` forwards flags to the script. - Drop `build-native-wasi` — the WASI experiment is abandoned per CLAUDE.md and slated for removal. Update AGENTS.md so the layout table, build & test block, and conventions reference `make help`, the `build/*.mk` includes, and `make check-authors`. --- AGENTS.md | 10 +++-- Makefile | 103 ++++++++++++++++++++++++++--------------------- build/release.mk | 15 +++++++ 3 files changed, 80 insertions(+), 48 deletions(-) create mode 100644 build/release.mk diff --git a/AGENTS.md b/AGENTS.md index adaa227f..79c01e8c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,14 +25,17 @@ Multi-module Maven build (parent `pom.xml`) + a sibling Go module under `native/ | `native/internal/test/` | Go test helpers (envtest). | | `native/wasm/`, `native/out/` | TinyGo/WASI experiment entrypoint (see `lib/wasi/` note); build output for shared libraries. | | `docs/research/` | Audits and decision records (e.g. native-codebase audit). Snapshots — may be stale; check the date. | -| `scripts/check-authors.sh` | Validates `@author` Javadoc tags. | -| `Makefile` | Build/test/release entrypoints (see [Build & test](#build--test)). | +| `scripts/check-authors.sh` | Validates `@author` Javadoc tags (invoked via `make check-authors`). | +| `Makefile`, `build/*.mk` | Build/test/release entrypoints. Top-level Makefile auto-includes `build/*.mk` (e.g. `build/release.mk`). Run `make help` for the categorized target list. See [Build & test](#build--test). | ## Build & test The Maven parent has `requireFilesExist` enforcer that needs all 5 native binaries in `native/out/`. Submodule `helm-java` and `lib/api` skip the rule, but a top-level `./mvnw install` will fail without them. ```bash +# Discover all targets (categorized: Build / Test / Code Quality / Development / Release) +make help + # Local dev (current platform only — skips the cross-platform enforcer check) make build-current-platform # = build-native + mvn clean verify with -Denforcer.skipRules=requireFilesExist @@ -55,6 +58,7 @@ make test-go # = cd native && go clean -testcache && go te make build-all # cross-platform natives + Java build make update-go-deps # bulk-bump non-indirect Go deps make license # apply license-header.txt to .go/.java files +make check-authors # verify @author tags (ARGS='--fix' suggests additions) make release V=1.2.3 VS=1.3.0 # tag release and bump to next snapshot (maintainer only) ``` @@ -91,7 +95,7 @@ Verbs with both forms: `install`, `template`, `show`, `upgrade`. Most others are **Java** - Source/target 1.8 — no `var`, no `Map.of(...)`, no Optional in APIs, no records. - Apache 2.0 header on every `.go` and `.java` file (`make license` enforces). -- `@author` Javadoc tags maintained (`scripts/check-authors.sh`). +- `@author` Javadoc tags maintained (`make check-authors`). - Tests: JUnit 5 + AssertJ. **No mocking libraries** — use real impls (Testcontainers/KinD for k8s). **Go** diff --git a/Makefile b/Makefile index dd50da3b..976ab56f 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,18 @@ -CGO_ENABLED=1 -LD_FLAGS=-s -w -COMMON_BUILD_ARGS=-ldflags "$(LD_FLAGS)" -buildmode=c-shared -MAVEN_OPTIONS= -LICENSE_FILE=license-header.txt +# If you update this file, please follow +# https://suva.sh/posts/well-documented-makefiles + +.DEFAULT_GOAL := help + +CGO_ENABLED = 1 +LD_FLAGS = -s -w +COMMON_BUILD_ARGS = -ldflags "$(LD_FLAGS)" -buildmode=c-shared +MAVEN_OPTIONS = +LICENSE_FILE = license-header.txt + # Detect OS to be able to run build-native target and provide a name -OS_NAME=linux -ARCH=amd64 -EXTENSION=so +OS_NAME = linux +ARCH = amd64 +EXTENSION = so ifeq ($(OS), Windows_NT) OS_NAME := windows-4.0 EXTENSION := dll @@ -23,64 +29,62 @@ else endif NATIVE_NAME := $(OS_NAME)-$(ARCH).$(EXTENSION) +CLEAN_TARGETS := +CLEAN_TARGETS += native/out/*.h native/out/*.so native/out/*.dylib native/out/*.dll + +# The help will print out all targets with their descriptions organized below their categories. The categories are represented by `##@` and the target descriptions by `##`. +# The awk command is responsible for reading the entire set of makefiles included in this invocation, looking for lines of the file as xyz: ## something, and then pretty-format the target and help. Then, if there's a line with ##@ something, that gets pretty-printed as a category. +# More info over the usage of ANSI control characters for terminal formatting: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters +# More info over awk command: http://linuxcommand.org/lc3_adv_awk.php +# +# Notice that we have a little modification on the awk command to support slash in the recipe name: +# origin: /^[a-zA-Z_0-9-]+:.*?##/ +# modified /^[a-zA-Z_0-9\/\.-]+:.*?##/ +.PHONY: help +help: ## Display this help + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9\/\.-]+:.*?##/ { printf " \033[36m%-30s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + .PHONY: clean -clean: +clean: ## Clean up all build artifacts (Go, Maven, native binaries) cd native && go clean ./... mvn clean - rm -f native/out/*.h native/out/*.so native/out/*.dylib native/out/*.dll + rm -f $(CLEAN_TARGETS) -.PHONY: test-go -test-go: - cd native && go clean -testcache && go test ./... +##@ Build .PHONY: build-native -build-native: +build-native: ## Build the native shared library for the current platform cd native && go build $(COMMON_BUILD_ARGS) -o ./out/helm-$(NATIVE_NAME) .PHONY: build-native-cross-platform -build-native-cross-platform: +build-native-cross-platform: ## Build native shared libraries for all 5 supported platforms (requires Docker) go install src.techknowlogick.com/xgo@latest xgo -image ghcr.io/techknowlogick/xgo:go-1.25.7 $(COMMON_BUILD_ARGS) -out native/out/helm --targets */arm64,*/amd64 ./native -.PHONY: build-native-wasi -build-native-wasi: - #cd native && GOOS=wasip1 GOARCH=wasm go build -o ./out/helm.wasm ./wasm/main.go - # Andrea recommends using TinyGo - # Doesn't work, need to find the right combination of ENV variables - #cd native && GOOS=wasip1 GOARCH=wasm tinygo build -o ./out/helm.wasm - # Working Version: - cd native && tinygo build -target=wasi -o ./out/helm.wasm ./wasm/main.go - .PHONY: build-java -build-java: +build-java: ## Build and verify the Java artifacts (mvn clean verify) mvn $(MAVEN_OPTIONS) clean verify +build-current-platform: MAVEN_OPTIONS = -Denforcer.skipRules=requireFilesExist .PHONY: build-current-platform -build-current-platform: MAVEN_OPTIONS=-Denforcer.skipRules=requireFilesExist -build-current-platform: build-native build-java +build-current-platform: build-native build-java ## Build native + Java for the current platform (skips cross-platform enforcer) .PHONY: build-all -build-all: build-native-cross-platform build-java +build-all: build-native-cross-platform build-java ## Build all 5 native platforms and the Java artifacts + +##@ Test + +.PHONY: test-go +test-go: ## Run Go tests in native/ + cd native && go clean -testcache && go test ./... .PHONY: test -test: test-go - -.PHONY: release -release: - @if [ -z "$(V)" ]; then echo "V is not set"; exit 1; fi - @if [ -z "$(VS)" ]; then echo "VS is not set"; exit 1; fi - @mvn versions:set -DnewVersion=$(V) -DgenerateBackupPoms=false - @git add . - @git commit -m "[RELEASE] Updated project version to v$(V)" - @git tag v$(V) - @git push origin v$(V) - @mvn versions:set -DnewVersion=$(VS)-SNAPSHOT -DgenerateBackupPoms=false - @git add . - @git commit -m "[RELEASE] v$(V) released, prepare for next development iteration" - @git push origin main +test: test-go ## Run all tests + +##@ Code Quality .PHONY: license -license: +license: ## Apply the Apache 2.0 license header to all .go and .java files @license_len=$$(cat $(LICENSE_FILE) | wc -l) && \ files=$$(git ls-files | grep -E "\.go|\.java") && \ for file in $$files; do \ @@ -89,8 +93,14 @@ license: ( ( cat $(LICENSE_FILE); echo; cat $$file ) > $$file.temp; mv $$file.temp $$file ) \ done +.PHONY: check-authors +check-authors: ## Check Java files for missing @author tags (use ARGS='--fix' to see suggestions) + @./scripts/check-authors.sh $(ARGS) + +##@ Development + .PHONY: update-go-deps -update-go-deps: +update-go-deps: ## Update non-indirect Go dependencies and tidy @echo ">> updating Go dependencies" @cd native && for m in $$(go list -mod=readonly -m -f '{{ if and (not .Indirect) (not .Main)}}{{.Path}}{{end}}' all); do \ go get $$m; \ @@ -99,3 +109,6 @@ update-go-deps: ifneq (,$(wildcard native/vendor)) cd native && go mod vendor endif + +# Include additional make targets +-include build/*.mk diff --git a/build/release.mk b/build/release.mk new file mode 100644 index 00000000..7a661722 --- /dev/null +++ b/build/release.mk @@ -0,0 +1,15 @@ +##@ Release + +.PHONY: release +release: ## Release a new version (maintainer only; usage: make release V=1.2.3 VS=1.3.0) + @if [ -z "$(V)" ]; then echo "V is not set"; exit 1; fi + @if [ -z "$(VS)" ]; then echo "VS is not set"; exit 1; fi + @mvn versions:set -DnewVersion=$(V) -DgenerateBackupPoms=false + @git add . + @git commit -m "[RELEASE] Updated project version to v$(V)" + @git tag v$(V) + @git push origin v$(V) + @mvn versions:set -DnewVersion=$(VS)-SNAPSHOT -DgenerateBackupPoms=false + @git add . + @git commit -m "[RELEASE] v$(V) released, prepare for next development iteration" + @git push origin main From 3d9dc4a705ade906dab83a2038858389f319886a Mon Sep 17 00:00:00 2001 From: Marc Nuri Date: Thu, 21 May 2026 12:34:59 +0200 Subject: [PATCH 2/4] chore(build): keep .PHONY adjacent to build-current-platform rule Place `.PHONY: build-current-platform` above the target-specific `MAVEN_OPTIONS` assignment so `.PHONY` stays adjacent to the target's main rule, matching the convention used elsewhere in the file. Behavior is identical. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 976ab56f..de90f018 100644 --- a/Makefile +++ b/Makefile @@ -65,8 +65,8 @@ build-native-cross-platform: ## Build native shared libraries for all 5 supporte build-java: ## Build and verify the Java artifacts (mvn clean verify) mvn $(MAVEN_OPTIONS) clean verify -build-current-platform: MAVEN_OPTIONS = -Denforcer.skipRules=requireFilesExist .PHONY: build-current-platform +build-current-platform: MAVEN_OPTIONS = -Denforcer.skipRules=requireFilesExist build-current-platform: build-native build-java ## Build native + Java for the current platform (skips cross-platform enforcer) .PHONY: build-all From 37ae1f93666c0d8eb4eff6bb351e316d568ee060 Mon Sep 17 00:00:00 2001 From: Marc Nuri Date: Thu, 21 May 2026 12:41:26 +0200 Subject: [PATCH 3/4] chore(ci): wrap mvn deploy in make and extract free-disk-space action Two cross-cutting cleanups across the build/release/snapshots workflows: - Add `make maven-deploy` to `build/release.mk` wrapping `mvn -Prelease clean deploy`, and replace the inline command in release.yml and snapshots.yml. Single source of truth for the Maven Central publish command. - Extract the ~20-line apt-get disk-cleanup shell block (duplicated in 3 workflows) to `.github/actions/free-disk-space` as a composite action. CI-only sudo work belongs in a composite action, not a Makefile target. Update AGENTS.md so `make maven-deploy` is listed and the CI block references both release.yml/snapshots.yml and the new composite action. --- .github/actions/free-disk-space/action.yml | 28 ++++++++++++++++++++++ .github/workflows/build.yml | 22 +---------------- .github/workflows/release.yml | 24 ++----------------- .github/workflows/snapshots.yml | 24 ++----------------- AGENTS.md | 6 ++++- build/release.mk | 4 ++++ 6 files changed, 42 insertions(+), 66 deletions(-) create mode 100644 .github/actions/free-disk-space/action.yml diff --git a/.github/actions/free-disk-space/action.yml b/.github/actions/free-disk-space/action.yml new file mode 100644 index 00000000..92637cb0 --- /dev/null +++ b/.github/actions/free-disk-space/action.yml @@ -0,0 +1,28 @@ +name: Free up disk space +description: Remove preinstalled software (dotnet, mono, browsers, Android SDK, …) to reclaim disk space on ubuntu-latest runners. +runs: + using: composite + steps: + - name: Free up disk space + shell: bash + run: | + sudo apt-get purge -y \ + 'aspnetcore.*' \ + 'dotnet.*' \ + 'firefox.*' \ + 'google-chrome.*' \ + 'mysql.*' \ + 'php.*' \ + 'mono-.*' \ + 'libmono.*' \ + 'azure-cli' \ + 'powershell' \ + '^llvm-.*' \ + '^clang-.*' + sudo apt-get autoremove -y + sudo apt-get clean + # Remove Android SDK + sudo rm -rf /usr/local/lib/android 2>/dev/null || true + # Remove .NET + sudo rm -rf /usr/share/dotnet 2>/dev/null || true + df -h diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a5a16a94..f3cfecfa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,27 +17,7 @@ jobs: - name: Checkout uses: actions/checkout@v6 - name: Free up disk space - run: | - sudo apt-get purge -y \ - 'aspnetcore.*' \ - 'dotnet.*' \ - 'firefox.*' \ - 'google-chrome.*' \ - 'mysql.*' \ - 'php.*' \ - 'mono-.*' \ - 'libmono.*' \ - 'azure-cli' \ - 'powershell' \ - '^llvm-.*' \ - '^clang-.*' - sudo apt-get autoremove -y - sudo apt-get clean - # Remove Android SDK - sudo rm -rf /usr/local/lib/android 2>/dev/null || true - # Remove .NET - sudo rm -rf /usr/share/dotnet 2>/dev/null || true - df -h + uses: ./.github/actions/free-disk-space - name: Setup Go uses: actions/setup-go@v6 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b202f872..38149d92 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,27 +16,7 @@ jobs: - name: Checkout uses: actions/checkout@v6 - name: Free up disk space - run: | - sudo apt-get purge -y \ - 'aspnetcore.*' \ - 'dotnet.*' \ - 'firefox.*' \ - 'google-chrome.*' \ - 'mysql.*' \ - 'php.*' \ - 'mono-.*' \ - 'libmono.*' \ - 'azure-cli' \ - 'powershell' \ - '^llvm-.*' \ - '^clang-.*' - sudo apt-get autoremove -y - sudo apt-get clean - # Remove Android SDK - sudo rm -rf /usr/local/lib/android 2>/dev/null || true - # Remove .NET - sudo rm -rf /usr/share/dotnet 2>/dev/null || true - df -h + uses: ./.github/actions/free-disk-space - name: Setup Go uses: actions/setup-go@v6 with: @@ -54,7 +34,7 @@ jobs: - name: Build run: make build-all - name: Maven Release - run: mvn -Prelease clean deploy + run: make maven-deploy env: MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} diff --git a/.github/workflows/snapshots.yml b/.github/workflows/snapshots.yml index 8ede14ce..98d2cf33 100644 --- a/.github/workflows/snapshots.yml +++ b/.github/workflows/snapshots.yml @@ -16,27 +16,7 @@ jobs: - name: Checkout uses: actions/checkout@v6 - name: Free up disk space - run: | - sudo apt-get purge -y \ - 'aspnetcore.*' \ - 'dotnet.*' \ - 'firefox.*' \ - 'google-chrome.*' \ - 'mysql.*' \ - 'php.*' \ - 'mono-.*' \ - 'libmono.*' \ - 'azure-cli' \ - 'powershell' \ - '^llvm-.*' \ - '^clang-.*' - sudo apt-get autoremove -y - sudo apt-get clean - # Remove Android SDK - sudo rm -rf /usr/local/lib/android 2>/dev/null || true - # Remove .NET - sudo rm -rf /usr/share/dotnet 2>/dev/null || true - df -h + uses: ./.github/actions/free-disk-space - name: Setup Go uses: actions/setup-go@v6 with: @@ -54,7 +34,7 @@ jobs: - name: Build run: make build-all - name: Maven SNAPSHOT Release - run: mvn -Prelease clean deploy + run: make maven-deploy env: MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} diff --git a/AGENTS.md b/AGENTS.md index 79c01e8c..aecc996a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -60,9 +60,13 @@ make update-go-deps # bulk-bump non-indirect Go deps make license # apply license-header.txt to .go/.java files make check-authors # verify @author tags (ARGS='--fix' suggests additions) make release V=1.2.3 VS=1.3.0 # tag release and bump to next snapshot (maintainer only) +make maven-deploy # mvn -Prelease clean deploy (CI only; needs Central credentials) ``` -CI (`.github/workflows/build.yml`): Linux job runs `make test-go` + `make build-all` on Java 8. Matrix jobs run `make build-current-platform` on Windows/macOS with Java 11. +CI: +- `.github/workflows/build.yml`: Linux job runs `make test-go` + `make build-all` on Java 8. Matrix jobs run `make build-current-platform` on Windows/macOS with Java 11. +- `.github/workflows/release.yml` and `snapshots.yml`: Linux Java 8; run `make build-all` then `make maven-deploy`. +- Shared CI infra: `.github/actions/free-disk-space` (composite action) reclaims runner disk space before Ubuntu builds. **Don't cancel running tests** that hit Kubernetes — they leak cluster resources. diff --git a/build/release.mk b/build/release.mk index 7a661722..31be8a3a 100644 --- a/build/release.mk +++ b/build/release.mk @@ -1,5 +1,9 @@ ##@ Release +.PHONY: maven-deploy +maven-deploy: ## Deploy to Maven Central with the release profile (CI; requires credentials and prebuilt native binaries) + mvn -Prelease clean deploy + .PHONY: release release: ## Release a new version (maintainer only; usage: make release V=1.2.3 VS=1.3.0) @if [ -z "$(V)" ]; then echo "V is not set"; exit 1; fi From 89e0cf5873cfa8ec7f78f579632e3d46af5ca293 Mon Sep 17 00:00:00 2001 From: Marc Nuri Date: Thu, 21 May 2026 12:52:27 +0200 Subject: [PATCH 4/4] chore(build): polish review nits - Move `build-current-platform`'s target-specific `MAVEN_OPTIONS` assignment below the main rule so `.PHONY` is directly adjacent to the rule line. - Rename the composite action's inner step to `Purge preinstalled software` so CI logs don't show `Free up disk space / Free up disk space`. --- .github/actions/free-disk-space/action.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/free-disk-space/action.yml b/.github/actions/free-disk-space/action.yml index 92637cb0..be961695 100644 --- a/.github/actions/free-disk-space/action.yml +++ b/.github/actions/free-disk-space/action.yml @@ -3,7 +3,7 @@ description: Remove preinstalled software (dotnet, mono, browsers, Android SDK, runs: using: composite steps: - - name: Free up disk space + - name: Purge preinstalled software shell: bash run: | sudo apt-get purge -y \ diff --git a/Makefile b/Makefile index de90f018..2f96e4ca 100644 --- a/Makefile +++ b/Makefile @@ -66,8 +66,8 @@ build-java: ## Build and verify the Java artifacts (mvn clean verify) mvn $(MAVEN_OPTIONS) clean verify .PHONY: build-current-platform -build-current-platform: MAVEN_OPTIONS = -Denforcer.skipRules=requireFilesExist build-current-platform: build-native build-java ## Build native + Java for the current platform (skips cross-platform enforcer) +build-current-platform: MAVEN_OPTIONS = -Denforcer.skipRules=requireFilesExist .PHONY: build-all build-all: build-native-cross-platform build-java ## Build all 5 native platforms and the Java artifacts