initial commit
This commit is contained in:
commit
23816d00f7
71 changed files with 14497 additions and 0 deletions
288
Makefile
Normal file
288
Makefile
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
# =============================================================================
|
||||
# go-doc — documentation & audience feedback platform
|
||||
#
|
||||
# make help list every target
|
||||
# make dev run infrastructure + backend + frontend together
|
||||
# make test run unit, integration and BDD suites
|
||||
# make build embed the React bundle into the portable Go binary
|
||||
# make docker build the all-in-one image
|
||||
# make docker-push build and push the image to the private registry
|
||||
# make docker-run run the image on :8080
|
||||
# make helm-deploy-development deploy to development
|
||||
# make helm-deploy-production deploy to production
|
||||
# =============================================================================
|
||||
|
||||
SHELL := /bin/bash
|
||||
.SHELLFLAGS := -eu -o pipefail -c
|
||||
|
||||
GO ?= go
|
||||
NPM ?= npm
|
||||
COMPOSE ?= docker compose
|
||||
HELM ?= helm
|
||||
|
||||
ROOT := $(shell pwd)
|
||||
WORKSPACE ?= $(dir $(ROOT))
|
||||
BACKEND_DIR := $(ROOT)/backend
|
||||
FRONTEND_DIR := $(ROOT)/frontend
|
||||
DATA_DIR := $(ROOT)/data
|
||||
WEBUI_DIST := $(BACKEND_DIR)/webui/dist
|
||||
|
||||
BINARY := $(ROOT)/bin/godoc
|
||||
BACKEND_ADDR ?= 0.0.0.0:8080
|
||||
HOST_ADDR ?= 127.0.0.1:8080
|
||||
VITE_PORT ?= 5173
|
||||
|
||||
# Docker/Registry
|
||||
IMAGE ?= go-doc
|
||||
TAG ?= latest
|
||||
REGISTRY_IMAGE ?= nexus.urpi.be/docker-hosted/go-doc
|
||||
|
||||
# Helm
|
||||
HELM_CHART := $(ROOT)/helm/go-doc
|
||||
HELM_RELEASE ?= go-doc
|
||||
HELM_NAMESPACE ?= go-doc
|
||||
KUBECONFIG ?= $(HOME)/.kube/config
|
||||
GO_LOOSE_CA_SECRET ?= local-ca
|
||||
|
||||
# Go Loose credentials passed via environment or .env
|
||||
GO_LOOSE_SET = $(if $(GO_LOOSE_CLIENT_ID),--set-string goLoose.clientID=$(GO_LOOSE_CLIENT_ID)) \
|
||||
$(if $(GO_LOOSE_CLIENT_SECRET),--set-string goLoose.clientSecret=$(GO_LOOSE_CLIENT_SECRET)) \
|
||||
$(if $(GO_LOOSE_CA_SECRET),--set-string goLoose.ca.existingSecret=$(GO_LOOSE_CA_SECRET))
|
||||
|
||||
# Parent directory that holds the go-* projects to document. Override with
|
||||
# WORKSPACE=/path/to/projects when the projects live elsewhere.
|
||||
DOCS_WORKSPACE ?= $(patsubst %/,%,$(WORKSPACE))
|
||||
DOCGEN_INTERVAL ?= 5s
|
||||
|
||||
DOCS_COUNT ?= 120
|
||||
COMMENTS_PER_DOC ?= 25
|
||||
SEED_WORKERS ?= 8
|
||||
|
||||
GO_SOURCES := $(shell find $(BACKEND_DIR) -name '*.go' -type f 2>/dev/null)
|
||||
FRONTEND_SOURCES := $(shell find $(FRONTEND_DIR)/src -type f 2>/dev/null)
|
||||
|
||||
.DEFAULT_GOAL := help
|
||||
.PHONY: help infra-up infra-down infra-logs backend-run frontend-run dev test \
|
||||
test-unit test-integration test-bdd test-race build build-frontend \
|
||||
build-backend fmt vet tidy seed seed-perf clean distclean run docker-build \
|
||||
docker docker-push docker-run helm-lint helm-deploy-development \
|
||||
helm-deploy-production helm-down-development helm-down-production \
|
||||
docs-sync docs-watch docs-dry-run docs-list
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## Help
|
||||
## ---------------------------------------------------------------------------
|
||||
help: ## Show this help
|
||||
@printf '\n\033[1mgo-doc\033[0m — available targets\n\n'
|
||||
@grep -hE '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
|
||||
| sort \
|
||||
| awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}'
|
||||
@printf '\n'
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## Infrastructure
|
||||
## ---------------------------------------------------------------------------
|
||||
infra-up: ## Start local development containers detached
|
||||
@if $(COMPOSE) version >/dev/null 2>&1; then \
|
||||
$(COMPOSE) up -d --remove-orphans; \
|
||||
else \
|
||||
echo "error: '$(COMPOSE)' is unavailable. Install Docker Compose v2." >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
infra-down: ## Tear down infrastructure and remove volumes
|
||||
@if $(COMPOSE) version >/dev/null 2>&1; then \
|
||||
$(COMPOSE) down --volumes --remove-orphans; \
|
||||
else \
|
||||
echo "docker compose unavailable; nothing to tear down"; \
|
||||
fi
|
||||
|
||||
infra-logs: ## Tail infrastructure logs
|
||||
$(COMPOSE) logs -f
|
||||
|
||||
docker-build: ## Build the container images
|
||||
$(COMPOSE) build
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## Run
|
||||
## ---------------------------------------------------------------------------
|
||||
backend-run: ## Run the Go API natively on 0.0.0.0:8080
|
||||
@mkdir -p $(DATA_DIR)
|
||||
@echo "→ backend http://$(HOST_ADDR)"
|
||||
@cd $(BACKEND_DIR) && GO_DOC_DATA_DIR=$(DATA_DIR) $(GO) run main.go -addr $(BACKEND_ADDR)
|
||||
|
||||
frontend-run: ## Run the Vite dev server on port 5173
|
||||
@echo "→ frontend http://$(VITE_PORT)"
|
||||
@cd $(FRONTEND_DIR) && $(NPM) run dev -- --port $(VITE_PORT)
|
||||
|
||||
dev: ## Run backend, frontend and infrastructure concurrently
|
||||
@$(MAKE) --no-print-directory infra-up
|
||||
@echo "→ backend http://$(HOST_ADDR)"
|
||||
@echo "→ frontend http://$(VITE_PORT) (Ctrl-C stops everything)"
|
||||
@trap 'echo; echo "→ stopping dev stack"; kill 0' EXIT INT TERM; \
|
||||
( cd $(BACKEND_DIR) && GO_DOC_DATA_DIR=$(DATA_DIR) $(GO) run main.go -addr $(BACKEND_ADDR) ) & \
|
||||
( cd $(FRONTEND_DIR) && $(NPM) run dev -- --port $(VITE_PORT) ) & \
|
||||
wait
|
||||
|
||||
run: build ## Build the single-file binary and run it
|
||||
@echo "→ serving SPA + API on http://$(HOST_ADDR)"
|
||||
@$(BINARY) -addr $(BACKEND_ADDR) -data $(DATA_DIR)
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## Test
|
||||
## ---------------------------------------------------------------------------
|
||||
test: fmt vet ## Run every suite: unit, integration, BDD, race
|
||||
@echo "→ go test ./... -count=1"
|
||||
@cd $(BACKEND_DIR) && $(GO) test ./... -count=1
|
||||
@echo "→ race detector on the storage engine and API"
|
||||
@cd $(BACKEND_DIR) && $(GO) test ./storage/... ./tests/... -race -count=1
|
||||
@echo "✓ all suites passed"
|
||||
|
||||
test-unit: ## Run storage engine unit tests only
|
||||
@cd $(BACKEND_DIR) && $(GO) test ./storage/... -count=1 -v
|
||||
|
||||
test-integration: ## Run end-to-end API tests against the real filesystem
|
||||
@cd $(BACKEND_DIR) && $(GO) test ./tests/ -run Integration -count=1 -v
|
||||
|
||||
test-bdd: ## Run the BDD feature suites
|
||||
@cd $(BACKEND_DIR) && $(GO) test ./tests/bdd/... -count=1 -v
|
||||
|
||||
test-race: ## Run all tests under the race detector
|
||||
@cd $(BACKEND_DIR) && $(GO) test ./... -race -count=1
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## Build
|
||||
## ---------------------------------------------------------------------------
|
||||
build: build-frontend build-backend ## Build the SPA and embed it in the Go binary
|
||||
@echo "✓ $(BINARY) serves both the SPA and /api"
|
||||
|
||||
build-frontend: $(FRONTEND_SOURCES) ## Compile the React bundle into frontend/dist
|
||||
@cd $(FRONTEND_DIR) && $(NPM) install --no-audit --no-fund
|
||||
@cd $(FRONTEND_DIR) && $(NPM) run build
|
||||
|
||||
build-backend: $(GO_SOURCES) ## Stage assets into webui/dist and compile the binary
|
||||
@test -f $(FRONTEND_DIR)/dist/index.html || { \
|
||||
echo "error: frontend/dist/index.html missing — run 'make build-frontend' first" >&2; \
|
||||
exit 1; \
|
||||
}
|
||||
@mkdir -p $(WEBUI_DIST) $(dir $(BINARY))
|
||||
@rm -rf $(WEBUI_DIST)
|
||||
@mkdir -p $(WEBUI_DIST)
|
||||
@cp -r $(FRONTEND_DIR)/dist/. $(WEBUI_DIST)/
|
||||
@echo "→ embedded assets: $$(find $(WEBUI_DIST) -type f | wc -l) files"
|
||||
@cd $(BACKEND_DIR) && CGO_ENABLED=0 $(GO) build -trimpath -ldflags '-s -w' -o $(BINARY) .
|
||||
@echo "✓ built $(BINARY) ($$(du -h $(BINARY) | cut -f1))"
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## Quality
|
||||
## ---------------------------------------------------------------------------
|
||||
fmt: ## gofmt the backend
|
||||
@cd $(BACKEND_DIR) && $(GO) fmt ./... >/dev/null
|
||||
@echo "✓ gofmt"
|
||||
|
||||
vet: ## go vet the backend
|
||||
@cd $(BACKEND_DIR) && $(GO) vet ./...
|
||||
@echo "✓ go vet"
|
||||
|
||||
tidy: ## Tidy go.mod
|
||||
@cd $(BACKEND_DIR) && $(GO) mod tidy
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## Documentation generation
|
||||
## ---------------------------------------------------------------------------
|
||||
## Every go-* project under WORKSPACE is analysed and imported into data/docs.
|
||||
## Generated pages are wrapped in <!-- go-doc:generated ---> markers, so a
|
||||
## re-sync replaces only the machine-written part and keeps anything you wrote
|
||||
## outside the markers. Pass DOCGEN_ARGS to reach the CLI directly, e.g.
|
||||
## make docs-sync DOCGEN_ARGS="-apps go-tell -force"
|
||||
|
||||
docs-sync: ## Analyse every go-* project under WORKSPACE and import its docs (DOCGEN_ARGS)
|
||||
@mkdir -p $(DATA_DIR)/docs
|
||||
@cd $(BACKEND_DIR) && $(GO) run ./scripts/docgen \
|
||||
-root $(DOCS_WORKSPACE) -data $(DATA_DIR) $(DOCGEN_ARGS)
|
||||
|
||||
docs-watch: ## Keep importing documentation as projects change (Ctrl-C to stop)
|
||||
@mkdir -p $(DATA_DIR)/docs
|
||||
@cd $(BACKEND_DIR) && $(GO) run ./scripts/docgen \
|
||||
-root $(DOCS_WORKSPACE) -data $(DATA_DIR) -watch -interval $(DOCGEN_INTERVAL) $(DOCGEN_ARGS)
|
||||
|
||||
docs-dry-run: ## Analyse and render without writing anything
|
||||
@cd $(BACKEND_DIR) && $(GO) run ./scripts/docgen \
|
||||
-root $(DOCS_WORKSPACE) -data $(DATA_DIR) -dry-run $(DOCGEN_ARGS)
|
||||
|
||||
docs-list: ## List the go-* projects that a sync would import
|
||||
@printf 'workspace: %s\n\n' '$(DOCS_WORKSPACE)'
|
||||
@ls -1 $(DOCS_WORKSPACE) 2>/dev/null | grep '^go-' | grep -v '^go-doc$$' | sed 's/^/ /'
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## Data
|
||||
## ---------------------------------------------------------------------------
|
||||
seed: ## Seed 120 generated documents + thousands of comments (DOCS_COUNT, COMMENTS_PER_DOC)
|
||||
@cd $(BACKEND_DIR) && $(GO) run ./scripts/seed_perf_data.go \
|
||||
-data $(DATA_DIR) -docs $(DOCS_COUNT) -comments $(COMMENTS_PER_DOC) -workers $(SEED_WORKERS)
|
||||
|
||||
seed-perf: seed ## Alias for seed
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## Clean
|
||||
## ---------------------------------------------------------------------------
|
||||
clean: ## Remove build artefacts
|
||||
@rm -rf $(ROOT)/bin $(FRONTEND_DIR)/dist
|
||||
@echo "✓ cleaned build artefacts (backend/webui/dist left intact)"
|
||||
|
||||
distclean: clean ## Also restore the placeholder frontend bundle
|
||||
@rm -rf $(WEBUI_DIST)
|
||||
@mkdir -p $(WEBUI_DIST)
|
||||
@cp $(BACKEND_DIR)/webui/dist.placeholder/index.html $(WEBUI_DIST)/index.html
|
||||
@echo "✓ webui/dist reset to the placeholder bundle"
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## Docker
|
||||
## ---------------------------------------------------------------------------
|
||||
docker: ## Build the all-in-one image
|
||||
docker build -t $(IMAGE):$(TAG) -f $(BACKEND_DIR)/Dockerfile .
|
||||
|
||||
docker-push: ## Build and push the image to the private registry
|
||||
docker tag $(IMAGE):$(TAG) $(REGISTRY_IMAGE):$(TAG)
|
||||
docker push $(REGISTRY_IMAGE):$(TAG)
|
||||
|
||||
docker-run: ## Run the image on :8080
|
||||
docker run --rm -p 8080:8080 --env-file $(ROOT)/.env $(IMAGE):$(TAG)
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## Helm
|
||||
## ---------------------------------------------------------------------------
|
||||
helm-lint: ## Lint the helm chart
|
||||
$(HELM) lint $(HELM_CHART) -f $(HELM_CHART)/values-dev.yaml
|
||||
$(HELM) lint $(HELM_CHART) -f $(HELM_CHART)/values-prd.yaml
|
||||
$(HELM) template $(HELM_RELEASE) $(HELM_CHART) \
|
||||
-f $(HELM_CHART)/values-dev.yaml >/dev/null
|
||||
$(HELM) template $(HELM_RELEASE) $(HELM_CHART) \
|
||||
-f $(HELM_CHART)/values-prd.yaml \
|
||||
--set-string goLoose.clientID=lint --set-string goLoose.clientSecret=lint >/dev/null
|
||||
|
||||
# Go Loose credentials are never stored in the values files. Pass them on the
|
||||
# command line, from a secret store, or with --set-file:
|
||||
# make helm-deploy-production \
|
||||
# --set goLoose.clientID=$(GO_LOOSE_CLIENT_ID) \
|
||||
# --set goLoose.clientSecret=$(GO_LOOSE_CLIENT_SECRET) \
|
||||
# --set goLoose.ca.existingSecret=local-ca
|
||||
helm-deploy-development: ## Deploy to development
|
||||
KUBECONFIG="$(KUBECONFIG)" $(HELM) upgrade --install $(HELM_RELEASE) $(HELM_CHART) \
|
||||
--namespace $(HELM_NAMESPACE)-development --create-namespace \
|
||||
-f $(HELM_CHART)/values-dev.yaml \
|
||||
--rollback-on-failure --wait --timeout 10m
|
||||
|
||||
helm-deploy-production: ## Deploy to production
|
||||
set -a; [ ! -f $(ROOT)/.env ] || . $(ROOT)/.env; set +a; \
|
||||
KUBECONFIG="$(KUBECONFIG)" $(HELM) upgrade --install $(HELM_RELEASE) $(HELM_CHART) \
|
||||
--namespace go-insane-prd --create-namespace \
|
||||
-f $(HELM_CHART)/values-prd.yaml \
|
||||
$(GO_LOOSE_SET) \
|
||||
--rollback-on-failure --wait --timeout 10m
|
||||
|
||||
helm-down-development: ## Tear down development release
|
||||
KUBECONFIG="$(KUBECONFIG)" $(HELM) uninstall $(HELM_RELEASE) -n $(HELM_NAMESPACE)-development
|
||||
|
||||
helm-down-production: ## Tear down production release
|
||||
KUBECONFIG="$(KUBECONFIG)" $(HELM) uninstall $(HELM_RELEASE) -n $(HELM_NAMESPACE)-production
|
||||
Loading…
Add table
Add a link
Reference in a new issue