Ctrl K
ComunidadGuías…

Makefile

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# server-control-panel Makefile
# Single-tenant Linux control plane. Stack: Go 1.25 backend + embedded HTML SPA.

.PHONY: help build node-agent dev test fmt vet check tools tailwind minify health logs backup backup-containers clean docs docs-check docs-data mobile-openapi-spec sdui-contract sdui-golden sdui-check

BIN_DIR := bin
SERVER_BIN := $(BIN_DIR)/server-control-panel-new
CTL_BIN := $(BIN_DIR)/panelctl-new
WAD_BIN := $(BIN_DIR)/wad-new
AGENT_BIN := $(BIN_DIR)/node-agent-new

help: ## Show this help
	@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "  %-15s %s\n", $$1, $$2}' $(MAKEFILE_LIST)

build: minify ## Build cmd/server, cmd/panelctl and cmd/wad into bin/ (run `make tailwind` first after adding CSS classes)
	CGO_ENABLED=0 go build -o $(SERVER_BIN) ./cmd/server
	CGO_ENABLED=0 go build -o $(CTL_BIN) ./cmd/panelctl
	CGO_ENABLED=0 go build -o $(WAD_BIN) ./cmd/wad
	@echo "✓ binaries in $(BIN_DIR)/"

# node-agent has its OWN target and is deliberately NOT a dependency of `build`.
#
# The reason is operational, not aesthetic: a deploy runs `make build` to
# ship the PANEL, which is the operator's main working
# tool. Coupling the two would let a compile error in the agent BLOCK the
# panel deploy — the agent would take down the very tool used to fix the
# agent.
#
# What is NOT lost by the split: `go build ./...` in CI already ensures the
# agent COMPILES on every change. What is avoided is coupling the ARTIFACT:
# each binary ships and rolls back on its own.
node-agent: ## Build only cmd/node-agent (kept out of the panel build on purpose)
	@# BUILD STAMP, and why it is worth it here.
	@# A rollback drill once left FIVE artifacts in bin/ on the node, with names
	@# that differed only by timestamp — and TWO of them with the same content, because
	@# the source was identical and the Go build is reproducible. Finding out which one
	@# was live meant hashing all five. The process could not say where it came from.
	@# The stamp trades bit-for-bit reproducibility for TRACEABILITY: every build is
	@# distinct, and the agent itself announces in the journal which artifact it is.
	CGO_ENABLED=0 go build -ldflags "-X main.stamp=$$(git rev-parse --short HEAD 2>/dev/null || echo no-git)-$$(date -u +%Y%m%dT%H%M%SZ)" -o $(AGENT_BIN) ./cmd/node-agent
	@echo "✓ $(AGENT_BIN)"

ESBUILD := .tools/node_modules/.bin/esbuild

tools: ## Install the local tooling into .tools/ (esbuild to minify, playwright-core for the rendering pin test)
	@# .tools/ is not versioned, so the dependency is declared here: without
	@# it a clean clone cannot run the pin tests and nothing says why.
	@mkdir -p .tools
	cd .tools && npm install --no-audit --no-fund esbuild playwright-core
	@echo "✓ tooling in .tools/. The screen pin tests use the system Chrome or a"
	@echo "  playwright browser; if neither is installed: npx playwright install chromium"

minify: ## Generate <x>.min.js for the app assets (best-effort; without esbuild the originals are served)
	@# PROVENANCE STAMP: every .min.js ends with the sha256 of the .js that
	@# produced it. The server only swaps the original for the minified file when the
	@# stamp matches (internal/webassets/minified.go). Without it, the .min.js — which
	@# is GENERATED and UNTRACKED — survives a change to its source and keeps being
	@# served: that is how a bundle from 08/26 erased AdGuard from the app on
	@# 08/30 and took down the whole SPA with a ReferenceError during Alpine boot.
	@if [ -x "$(ESBUILD)" ]; then \
	  for f in internal/webassets/web/vendor/panel/app/*.js; do \
	    case "$$f" in *.min.js) continue;; esac; \
	    o="$${f%.js}.min.js"; \
	    if "$(ESBUILD)" "$$f" --minify-whitespace --minify-syntax --target=es2020 > "$$o.tmp" 2>/dev/null; then \
	      printf '\n//# panel-src-sha256=%s\n' "$$(sha256sum "$$f" | cut -d" " -f1)" >> "$$o.tmp"; \
	      mv "$$o.tmp" "$$o"; \
	    else \
	      rm -f "$$o.tmp" "$$o"; \
	      echo "  minify failed on $$f -- serving the original"; \
	    fi; \
	  done; \
	  echo "\342\234\223 app assets minified (with provenance stamp)"; \
	else \
	  : "Delete rather than keep: an orphaned minified file would be embedded in the binary"; \
	  rm -f internal/webassets/web/vendor/panel/app/*.min.js; \
	  echo "  esbuild missing from .tools/ -- serving the assets unminified"; \
	fi

DOCS_HTML := internal/webassets/docs/report.html

docs-check: ## Validate the nesting of the technical report pages (served gated at /_docs)
	@python3 scripts/check-docs-structure.py "$(DOCS_HTML)"

docs-data: ## Regenerate the report's metrics/routes from the repo (GEN blocks)
	@./scripts/gen-docs-data.sh

dev: build ## Build + run the server from bin/
	$(SERVER_BIN)

test: ## Run go test ./...
	go test ./...

fmt: ## gofmt -w
	gofmt -w cmd/ internal/

vet: ## go vet ./...
	go vet ./...

check: vet test ## vet + test (CI-style)

mobile-openapi-spec: ## Generate android/data/mobile-api-client/openapi/mobile-v1.yaml from the huma registry in internal/mobilebff
	go run ./cmd/mobile-openapi-gen

sdui-contract: ## Generate contracts/sdui/contract.json from the Go types in internal/mobilebff/sdui
	go run ./cmd/sdui-contract

sdui-golden: ## Regenerate contracts/sdui/fixtures/screens/*.json from the real Builders (admin + non-admin)
	go test ./internal/mobilebff/sdui/ -run TestGoldenScreens -update

sdui-check: ## SDUI contract gate: committed contract + compatibility with already published apps + screen goldens
	./scripts/check-sdui-contract.sh

tailwind: ## Regenerate /vendor/tailwind.css (run after adding a new class)
	./scripts/build-tailwind.sh

health: ## panelctl health (deep check)
	@$(CTL_BIN) health 2>/dev/null || panelctl health

logs: ## Tail the last 50 audit events
	@$(CTL_BIN) logs 2>/dev/null || panelctl logs

backup: build ## panelctl backup → ~/panel-backup-<ts>.tar.gz
	@$(CTL_BIN) backup

backup-containers: build ## backup + tarball /var/lib/panel-whatsapp/
	@$(CTL_BIN) backup --containers

docs: ## Open the HTML technical report
	@if command -v xdg-open >/dev/null 2>&1; then xdg-open "$(DOCS_HTML)" >/dev/null 2>&1 & \
	else echo "Technical report (self-contained, open it in a browser):"; echo "  $(CURDIR)/$(DOCS_HTML)"; fi

clean: ## Remove the binaries staged as bin/*-new
	rm -f $(SERVER_BIN) $(CTL_BIN) $(WAD_BIN) $(AGENT_BIN)

.DEFAULT_GOAL := help