initial commit
Some checks failed
ci / go (push) Has been cancelled
ci / admin-ui (push) Has been cancelled
ci / runtime-sdk (push) Has been cancelled
ci / helm (push) Has been cancelled
ci / openapi (push) Has been cancelled
ci / container (push) Has been cancelled
ci / release-config (push) Has been cancelled
ci / shared styling (push) Has been cancelled
ci / security (push) Has been cancelled
ci / all green (push) Has been cancelled
Some checks failed
ci / go (push) Has been cancelled
ci / admin-ui (push) Has been cancelled
ci / runtime-sdk (push) Has been cancelled
ci / helm (push) Has been cancelled
ci / openapi (push) Has been cancelled
ci / container (push) Has been cancelled
ci / release-config (push) Has been cancelled
ci / shared styling (push) Has been cancelled
ci / security (push) Has been cancelled
ci / all green (push) Has been cancelled
This commit is contained in:
commit
951dd8d26b
175 changed files with 50041 additions and 0 deletions
439
Makefile
Normal file
439
Makefile
Normal file
|
|
@ -0,0 +1,439 @@
|
|||
# Go Bananas!!
|
||||
#
|
||||
# The Makefile is the primary interface to this repository. Every task a developer
|
||||
# or a CI job needs is a target here, and each target is safe to run repeatedly.
|
||||
#
|
||||
# Conventions:
|
||||
# * `make help` lists everything.
|
||||
# * Targets are grouped by phase and the phases run in order for `make all`.
|
||||
# * Anything that changes the machine (installing a tool, pushing an image) is
|
||||
# marked ##@destructive so it is obvious in `make help`.
|
||||
# * Variables at the top are overridable: `make IMAGE_TAG=v2 build`.
|
||||
#
|
||||
# The `##@` markers are read by the self-documenting help target, which is why
|
||||
# they are inline comments rather than a separate block.
|
||||
|
||||
SHELL := /usr/bin/env bash
|
||||
.SHELLFLAGS := -eu -o pipefail -c
|
||||
.DEFAULT_GOAL := help
|
||||
.DELETE_ON_ERROR:
|
||||
.SUFFIXES:
|
||||
|
||||
# --------------------------------------------------------------- variables ----
|
||||
|
||||
BINARY := go-bananas
|
||||
CMD := ./cmd/go-bananas
|
||||
BIN_DIR := bin
|
||||
DIST_DIR := dist
|
||||
WEB_DIR := web
|
||||
SDK_DIR := sdk
|
||||
|
||||
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)
|
||||
COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
||||
BUILD_DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
|
||||
REGISTRY ?= nexus.urpi.be
|
||||
IMAGE_NAME ?= $(REGISTRY)/$(BINARY)
|
||||
IMAGE_TAG ?= $(VERSION)
|
||||
PLATFORM ?= linux/amd64,linux/arm64
|
||||
|
||||
GO ?= go
|
||||
NPM ?= npm
|
||||
|
||||
# Development tool versions, pinned so that every contributor and every CI run use
|
||||
# the same linter. They are pinned here rather than in a separate tools module
|
||||
# because `go install pkg@version` resolves the version itself and refuses a
|
||||
# -modfile, which would make a tools.mod decorative rather than binding. `make
|
||||
# tools-upgrade` bumps all three in one place.
|
||||
AIR_VERSION ?= v1.67.4
|
||||
GOLANGCI_VERSION ?= v2.14.0
|
||||
SQLC_VERSION ?= v1.31.1
|
||||
HELM ?= helm
|
||||
DOCKER ?= docker
|
||||
|
||||
# Module cache and build cache live outside the tree so that a bind-mounted
|
||||
# working directory does not slowly fill the developer's disk.
|
||||
GO_CACHE ?= $(CURDIR)/.cache/go-build
|
||||
GOMODCACHE ?= $(CURDIR)/.cache/go-mod
|
||||
|
||||
# The Go packages belonging to this module, excluding the JavaScript trees.
|
||||
#
|
||||
# Go does not ignore node_modules: any directory under the module root with Go
|
||||
# files in it is part of `./...`, and a dependency that happens to ship a stray
|
||||
# package would then be compiled and linted as if it were ours. `./internal/...`
|
||||
# and `./cmd/...` are listed instead of filtering, so the omission is visible here
|
||||
# rather than hidden in a pipe.
|
||||
GO_PACKAGES = ./cmd/... ./internal/...
|
||||
|
||||
# The full set of ldflags. Kept in one variable so that `go build`, `go install`
|
||||
# and goreleaser cannot drift apart and produce differently-identified binaries.
|
||||
LDFLAGS := -s -w \
|
||||
-X github.com/urpi/go-bananas/internal/app.Version=$(VERSION) \
|
||||
-X github.com/urpi/go-bananas/internal/app.Commit=$(COMMIT) \
|
||||
-X github.com/urpi/go-bananas/internal/app.BuildDate=$(BUILD_DATE)
|
||||
|
||||
GOFLAGS_BUILD := -trimpath -ldflags "$(LDFLAGS)"
|
||||
|
||||
.DEFAULT_COLOR := \033[0m
|
||||
.BOLD := \033[1m
|
||||
.DIM := \033[2m
|
||||
.GREEN := \033[32m
|
||||
.YELLOW := \033[33m
|
||||
.RED := \033[31m
|
||||
|
||||
##@ General
|
||||
|
||||
.PHONY: help
|
||||
help: ## Show this help
|
||||
@printf "$(BOLD)go-bananas$(DEFAULT_COLOR) — runtime design-token service\n\n"
|
||||
@printf "$(DIM)Version$(DEFAULT_COLOR) $(VERSION) ($(COMMIT))\n\n"
|
||||
@# The awk pass reads both the "##@" group markers and the "##" target help in
|
||||
@# one scan so that groups appear in file order rather than in two separate
|
||||
@# alphabetical lists. A trailing "##@destructive" is stripped from the
|
||||
@# description and rendered as a marker instead.
|
||||
@awk 'BEGIN {FS = ":.*##"} \
|
||||
/^##@/ { printf "\n$(BOLD)%s$(DEFAULT_COLOR)\n", substr($$0, 5); next } \
|
||||
/^[a-zA-Z0-9_-]+:.*?##/ { \
|
||||
help = $$0; sub(/^[^:]*:.*## /, "", help); \
|
||||
mark = ""; \
|
||||
if (help ~ /##@destructive/) { mark = "$(YELLOW) [modifies this machine]$(DEFAULT_COLOR)"; \
|
||||
sub(/ *##@destructive/, "", help) } \
|
||||
printf " $(BOLD)%-20s$(DEFAULT_COLOR) %s%s\n", $$1, help, mark \
|
||||
}' $(MAKEFILE_LIST)
|
||||
@printf "\n$(DIM)Override any variable, e.g. make IMAGE_TAG=v2.1.0 image-push$(DEFAULT_COLOR)\n"
|
||||
|
||||
.PHONY: version
|
||||
version: ## Print the version that would be built
|
||||
@echo "$(VERSION) ($(COMMIT)) built $(BUILD_DATE)"
|
||||
|
||||
##@ Development
|
||||
|
||||
.PHONY: install
|
||||
install: ## Install Go and Node dependencies
|
||||
$(GO) mod download
|
||||
cd $(WEB_DIR) && $(NPM) install
|
||||
cd $(SDK_DIR) && $(NPM) install
|
||||
|
||||
.PHONY: dev
|
||||
dev: ## Run the API with hot reload (Ctrl-C to stop)
|
||||
@command -v air >/dev/null 2>&1 || { \
|
||||
echo "air is not installed; run 'make tools' or see docs/development.md"; exit 1; }
|
||||
@BANANAS_ENVIRONMENT=development \
|
||||
BANANAS_AUTH_MODE=dev \
|
||||
BANANAS_HTTP_ADDR=:8080 \
|
||||
BANANAS_DATABASE_PATH=./data/go-bananas.db \
|
||||
BANANAS_STATIC_DIR=$(WEB_DIR)/dist \
|
||||
BANANAS_SDK_DIR=$(SDK_DIR)/dist \
|
||||
air -c .air.toml
|
||||
|
||||
.PHONY: dev-api
|
||||
dev-api: ## Run only the API server, no frontend
|
||||
@BANANAS_ENVIRONMENT=development \
|
||||
BANANAS_AUTH_MODE=dev \
|
||||
BANANAS_HTTP_ADDR=:8080 \
|
||||
BANANAS_DATABASE_PATH=./data/go-bananas.db \
|
||||
BANANAS_STATIC_DIR= BANANAS_SDK_DIR= \
|
||||
$(GO) run -ldflags "$(LDFLAGS)" $(CMD)
|
||||
|
||||
.PHONY: dev-web
|
||||
dev-web: ## Run the Vite dev server for the admin UI, proxying the API
|
||||
cd $(WEB_DIR) && $(NPM) run dev
|
||||
|
||||
.PHONY: dev-all
|
||||
dev-all: ## Run the API and the frontend dev server together
|
||||
@echo "API on http://localhost:8080, admin UI on http://localhost:5173"
|
||||
@trap 'kill 0' EXIT; \
|
||||
$(MAKE) dev-api & \
|
||||
$(MAKE) dev-web & \
|
||||
wait
|
||||
|
||||
.PHONY: tools
|
||||
tools: ## Install the pinned development tools (air, golangci-lint, sqlc) ##@destructive
|
||||
$(GO) install github.com/air-verse/air@$(AIR_VERSION)
|
||||
$(GO) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(GOLANGCI_VERSION)
|
||||
$(GO) install github.com/sqlc-dev/sqlc/cmd/sqlc@$(SQLC_VERSION)
|
||||
@echo "Tools installed into $$( $(GO) env GOBIN )"
|
||||
@echo "golangci-lint $(GOLANGCI_VERSION), air $(AIR_VERSION), sqlc $(SQLC_VERSION)"
|
||||
|
||||
.PHONY: tools-upgrade
|
||||
tools-upgrade: ## Bump the pinned development tools to their latest releases ##@destructive
|
||||
@for tool in \
|
||||
github.com/air-verse/air:AIR_VERSION \
|
||||
github.com/golangci/golangci-lint/v2:GOLANGCI_VERSION \
|
||||
github.com/sqlc-dev/sqlc:SQLC_VERSION; do \
|
||||
pkg=$${tool%%:*}; var=$${tool##*:}; \
|
||||
latest=$$($(GO) list -m -versions $$pkg | tr ' ' '\n' | tail -1); \
|
||||
[ -n "$$latest" ] || { echo "could not resolve $$pkg"; exit 1; }; \
|
||||
sed -i.bak "s|^$$var .*|$$var ?= $$latest|" Makefile && rm -f Makefile.bak; \
|
||||
echo "$$var -> $$latest"; \
|
||||
done
|
||||
@echo "Run 'make tools' to install them and commit the Makefile change."
|
||||
|
||||
.PHONY: clean
|
||||
clean: ## Remove build output and local data
|
||||
rm -rf $(BIN_DIR) $(DIST_DIR) data .cache
|
||||
cd $(WEB_DIR) && rm -rf dist
|
||||
cd $(SDK_DIR) && rm -rf dist
|
||||
@echo "Cleaned."
|
||||
|
||||
.PHONY: clean-cache
|
||||
clean-cache: ## Remove every build cache, including the module cache ##@destructive
|
||||
$(GO) clean -cache -modcache
|
||||
rm -rf .cache
|
||||
cd $(WEB_DIR) && rm -rf node_modules/.vite
|
||||
cd $(SDK_DIR) && rm -rf node_modules/.vite
|
||||
|
||||
##@ Build
|
||||
|
||||
.PHONY: build
|
||||
build: build-go build-web build-sdk ## Build every artefact
|
||||
|
||||
.PHONY: build-go
|
||||
build-go: ## Build the server binary into bin/
|
||||
@mkdir -p $(BIN_DIR)
|
||||
CGO_ENABLED=0 $(GO) build -trimpath -ldflags "$(LDFLAGS)" -o $(BIN_DIR)/$(BINARY) $(CMD)
|
||||
@echo "Built $(BIN_DIR)/$(BINARY)"
|
||||
|
||||
.PHONY: build-web
|
||||
build-web: ## Build the admin UI into web/dist
|
||||
cd $(WEB_DIR) && $(NPM) run build
|
||||
|
||||
.PHONY: build-sdk
|
||||
build-sdk: ## Build the runtime SDK bundles into sdk/dist
|
||||
cd $(SDK_DIR) && $(NPM) run build
|
||||
|
||||
.PHONY: run
|
||||
run: build-go ## Build and run the server with the current assets
|
||||
@mkdir -p data
|
||||
BANANAS_ENVIRONMENT=development \
|
||||
BANANAS_AUTH_MODE=dev \
|
||||
BANANAS_STATIC_DIR=$(WEB_DIR)/dist \
|
||||
BANANAS_SDK_DIR=$(SDK_DIR)/dist \
|
||||
./$(BIN_DIR)/$(BINARY)
|
||||
|
||||
.PHONY: release
|
||||
release: ## Build release binaries for every supported platform ##@destructive
|
||||
@command -v goreleaser >/dev/null 2>&1 || { \
|
||||
echo "goreleaser is not installed; see docs/development.md"; exit 1; }
|
||||
goreleaser release --clean
|
||||
|
||||
.PHONY: release-snapshot
|
||||
release-snapshot: ## Build release binaries without publishing ##@destructive
|
||||
goreleaser release --snapshot --clean --skip=publish
|
||||
|
||||
.PHONY: sbom
|
||||
sbom: ## Generate a CycloneDX SBOM for the current version ##@destructive
|
||||
@command -v syft >/dev/null 2>&1 || { \
|
||||
echo "syft is not installed"; exit 1; }
|
||||
syft dir:. -o cyclonedx-json=sbom-$(VERSION).json
|
||||
|
||||
##@ Quality
|
||||
|
||||
.PHONY: check
|
||||
check: fmt-check lint test ## Run every check
|
||||
|
||||
.PHONY: fmt
|
||||
fmt: ## Format the Go code
|
||||
$(GO) fmt ./...
|
||||
|
||||
.PHONY: fmt-check
|
||||
fmt-check: ## Fail if the Go code is not formatted
|
||||
@unformatted="$$(gofmt -l . | grep -v '^vendor/' || true)"; \
|
||||
if [ -n "$$unformatted" ]; then \
|
||||
echo "These files are not gofmt'd:"; echo "$$unformatted"; exit 1; \
|
||||
fi
|
||||
@echo "Go formatting is clean."
|
||||
|
||||
.PHONY: lint
|
||||
lint: lint-go lint-web lint-sdk ## Run every linter
|
||||
|
||||
.PHONY: lint-go
|
||||
lint-go: ## Run golangci-lint
|
||||
@command -v golangci-lint >/dev/null 2>&1 || { \
|
||||
echo "golangci-lint is not installed; run 'make tools'"; exit 1; }
|
||||
golangci-lint run $(GO_PACKAGES)
|
||||
|
||||
.PHONY: lint-web
|
||||
lint-web: ## Lint and typecheck the admin UI
|
||||
cd $(WEB_DIR) && $(NPM) run lint
|
||||
cd $(WEB_DIR) && $(NPM) run typecheck
|
||||
|
||||
.PHONY: lint-sdk
|
||||
lint-sdk: ## Lint and typecheck the runtime SDK
|
||||
cd $(SDK_DIR) && $(NPM) run typecheck
|
||||
|
||||
.PHONY: fmt-web
|
||||
fmt-web: ## Format the frontend and SDK sources
|
||||
cd $(WEB_DIR) && $(NPM) run format
|
||||
cd $(SDK_DIR) && $(NPM) exec prettier --write .
|
||||
|
||||
.PHONY: tidy
|
||||
tidy: ## Tidy the Go module
|
||||
$(GO) mod tidy
|
||||
|
||||
##@ Test
|
||||
|
||||
.PHONY: test
|
||||
test: test-go test-web test-sdk ## Run every test suite
|
||||
|
||||
.PHONY: test-go
|
||||
test-go: ## Run the Go tests
|
||||
$(GO) test -race -count=1 $(GO_PACKAGES)
|
||||
|
||||
.PHONY: test-cover
|
||||
test-cover: ## Run the Go tests and write a coverage profile
|
||||
$(GO) test -race -count=1 -coverprofile=coverage.out -covermode=atomic $(GO_PACKAGES)
|
||||
$(GO) tool cover -func=coverage.out | tail -1
|
||||
@echo "Profile written to coverage.out"
|
||||
|
||||
.PHONY: test-web
|
||||
test-web: ## Run the admin UI tests
|
||||
cd $(WEB_DIR) && $(NPM) test
|
||||
|
||||
.PHONY: test-sdk
|
||||
test-sdk: ## Run the runtime SDK tests
|
||||
cd $(SDK_DIR) && $(NPM) test
|
||||
|
||||
.PHONY: bench
|
||||
bench: ## Run the token engine benchmarks
|
||||
$(GO) test -bench=. -benchmem ./internal/tokenengine/
|
||||
|
||||
##@ Docker
|
||||
|
||||
.PHONY: image
|
||||
image: ## Build the container image for the host architecture
|
||||
$(DOCKER) buildx build \
|
||||
--build-arg VERSION=$(VERSION) \
|
||||
--build-arg COMMIT=$(COMMIT) \
|
||||
--build-arg BUILD_DATE=$(BUILD_DATE) \
|
||||
--tag $(IMAGE_NAME):$(IMAGE_TAG) \
|
||||
--tag $(IMAGE_NAME):latest \
|
||||
--load \
|
||||
.
|
||||
|
||||
.PHONY: image-multi
|
||||
image-multi: ## Build the multi-architecture image without pushing ##@destructive
|
||||
$(DOCKER) buildx build \
|
||||
--platform $(PLATFORM) \
|
||||
--build-arg VERSION=$(VERSION) \
|
||||
--build-arg COMMIT=$(COMMIT) \
|
||||
--build-arg BUILD_DATE=$(BUILD_DATE) \
|
||||
--tag $(IMAGE_NAME):$(IMAGE_TAG) \
|
||||
.
|
||||
|
||||
.PHONY: image-push
|
||||
image-push: ## Build and push the multi-architecture image ##@destructive
|
||||
$(DOCKER) buildx build \
|
||||
--platform $(PLATFORM) \
|
||||
--build-arg VERSION=$(VERSION) \
|
||||
--build-arg COMMIT=$(COMMIT) \
|
||||
--build-arg BUILD_DATE=$(BUILD_DATE) \
|
||||
--push \
|
||||
--tag $(IMAGE_NAME):$(IMAGE_TAG) \
|
||||
.
|
||||
|
||||
.PHONY: image-run
|
||||
image-run: ## Run the image locally on port 8080
|
||||
$(DOCKER) run --rm -it \
|
||||
-p 8080:8080 \
|
||||
-e BANANAS_ENVIRONMENT=development \
|
||||
-e BANANAS_AUTH_MODE=dev \
|
||||
-v go-bananas-data:/srv/data \
|
||||
$(IMAGE_NAME):$(IMAGE_TAG)
|
||||
|
||||
.PHONY: compose-up
|
||||
compose-up: ## Start the local stack with docker compose
|
||||
$(DOCKER) compose up --build
|
||||
|
||||
.PHONY: compose-down
|
||||
compose-down: ## Stop the local stack ##@destructive
|
||||
$(DOCKER) compose down
|
||||
|
||||
.PHONY: compose-logs
|
||||
compose-logs: ## Follow the local stack logs
|
||||
$(DOCKER) compose logs -f
|
||||
|
||||
.PHONY: compose-shell
|
||||
compose-shell: ## Open a shell in the running service ##@destructive
|
||||
$(DOCKER) compose exec go-bananas /bin/sh
|
||||
|
||||
##@ Helm
|
||||
|
||||
.PHONY: helm-lint
|
||||
helm-lint: ## Lint the chart
|
||||
$(HELM) lint deploy/helm/go-bananas --strict
|
||||
|
||||
.PHONY: helm-matrix
|
||||
helm-matrix: ## Render the chart across a matrix of valid and invalid configurations
|
||||
./hack/helm-matrix.sh
|
||||
|
||||
.PHONY: helm-template
|
||||
helm-template: ## Render the chart with the default values
|
||||
$(HELM) template go-bananas deploy/helm/go-bananas
|
||||
|
||||
.PHONY: helm-template-auth
|
||||
helm-template-auth: ## Render the chart configured for OIDC
|
||||
$(HELM) template go-bananas deploy/helm/go-bananas \
|
||||
--set identity.mode=oidc \
|
||||
--set identity.oidc.issuer=https://auth-dev.urpi.be/realms/urpi \
|
||||
--set identity.oidc.clientId=go-bananas \
|
||||
--set identity.oidc.generateSecret=false \
|
||||
--set identity.oidc.existingSecret=go-bananas-oidc \
|
||||
--set config.publicBaseUrl=https://themes-dev.example.com
|
||||
|
||||
.PHONY: helm-install
|
||||
helm-install: ## Install the chart into the current kube context ##@destructive
|
||||
$(HELM) upgrade --install go-bananas deploy/helm/go-bananas \
|
||||
--namespace go-bananas --create-namespace \
|
||||
--values deploy/helm/go-bananas/values.yaml \
|
||||
--wait --timeout 5m
|
||||
|
||||
.PHONY: helm-uninstall
|
||||
helm-uninstall: ## Remove the release ##@destructive
|
||||
$(HELM) uninstall go-bananas --namespace go-bananas
|
||||
|
||||
##@ Docs
|
||||
|
||||
.PHONY: docs-serve
|
||||
docs-serve: ## Serve the documentation locally
|
||||
@command -v mkdocs >/dev/null 2>&1 || { echo "mkdocs is not installed"; exit 1; }
|
||||
mkdocs serve
|
||||
|
||||
.PHONY: docs-build
|
||||
docs-build: ## Build the documentation ##@destructive
|
||||
mkdocs build --strict
|
||||
|
||||
.PHONY: api-spec
|
||||
api-spec: ## Print the OpenAPI document summary
|
||||
@grep -E '^\s{2}/' openapi.yaml | sed 's/:$//' | tr -d ' ' | sed 's|^| |'
|
||||
|
||||
##@ Contract
|
||||
|
||||
.PHONY: check-contract
|
||||
check-contract: ## Drive the shared styling contract and the shipped controls in a real browser ##@destructive
|
||||
./hack/check-contract.sh
|
||||
|
||||
.PHONY: check-pilot
|
||||
check-pilot: ## Prove both adopting applications follow the contract without editing their CSS ##@destructive
|
||||
./hack/check-pilot-go-loose.sh
|
||||
./hack/check-pilot-go-tell.sh
|
||||
|
||||
##@ CI helpers
|
||||
|
||||
.PHONY: ci
|
||||
ci: check ## Everything CI runs, in one target
|
||||
|
||||
.PHONY: verify
|
||||
verify: ci helm-lint helm-matrix check-contract check-pilot ## The full pre-merge gate
|
||||
|
||||
.PHONY: deps-outdated
|
||||
deps-outdated: ## Report outdated Go and Node dependencies
|
||||
$(GO) list -u -m all
|
||||
@echo
|
||||
cd $(WEB_DIR) && $(NPM) outdated || true
|
||||
|
||||
.PHONY: deps-update
|
||||
deps-update: ## Update Go and Node dependencies ##@destructive
|
||||
$(GO) get -u ./... && $(GO) mod tidy
|
||||
cd $(WEB_DIR) && $(NPM) update
|
||||
cd $(SDK_DIR) && $(NPM) update
|
||||
Loading…
Add table
Add a link
Reference in a new issue