diff --git a/.github/actions/free-disk-space/action.yml b/.github/actions/free-disk-space/action.yml new file mode 100644 index 00000000..be961695 --- /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: Purge preinstalled software + 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 adaa227f..aecc996a 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,10 +58,15 @@ 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) +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. @@ -91,7 +99,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..2f96e4ca 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 .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) +build-current-platform: MAVEN_OPTIONS = -Denforcer.skipRules=requireFilesExist .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..31be8a3a --- /dev/null +++ b/build/release.mk @@ -0,0 +1,19 @@ +##@ 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 + @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