Files
wehub-resource-sync 161ef94b4f
Check engine pin consistency / Dockerfile / CI pin consistency (push) Successful in 8s
Sirius CI/CD Pipeline / Detect Changes (push) Successful in 23s
Validate Docker Configuration / Validate Docker Compose Configuration (push) Successful in 47s
Sirius CI/CD Pipeline / Build API (${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Build UI (${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Engine Manifest (push) Has been cancelled
Sirius CI/CD Pipeline / Merge API Manifest (push) Has been cancelled
Sirius CI/CD Pipeline / Merge UI Manifest (push) Has been cancelled
Sirius CI/CD Pipeline / Build Engine (${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Build Infra (${{ matrix.service }}, ${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Infra Manifest (sirius-postgres) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Infra Manifest (sirius-rabbitmq) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Infra Manifest (sirius-valkey) (push) Has been cancelled
Sirius CI/CD Pipeline / Integration Test (push) Has been cancelled
Sirius CI/CD Pipeline / Public Stack Contract (push) Has been cancelled
Sirius CI/CD Pipeline / Dispatch Demo Deployment (sirius-demo branch) (push) Has been cancelled
Sirius CI/CD Pipeline / Dispatch Demo Canary (main branch) (push) Has been cancelled
Sirius CI/CD Pipeline / Guard Registry Namespace (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:32:25 +08:00

238 lines
13 KiB
Makefile

# Sirius developer Makefile.
#
# This file lives at the repo root and contains short, ergonomic targets
# for the inner-loop dev workflow. The container-testing Makefile in
# testing/container-testing/ remains the authoritative test runner; do
# not duplicate test targets here.
#
# Conventions:
# - All targets are phony unless documented.
# - Targets that touch a running container assume `docker compose -f
# docker-compose.yaml -f docker-compose.dev.yaml up -d` has been run.
# - HOST_GOARCH is detected from `uname -m`; override on the command
# line for cross-arch dev (e.g. building amd64 binaries on an arm64
# mac that talks to an amd64 container).
#
# See documentation/dev/README.development.md for the full dev workflow
# and documentation/dev/architecture/README.engine-component-pinning.md
# for the pin policy that bounds these targets.
SHELL := /bin/bash
# Where each minor-project lives on disk relative to the repo root.
SIRIUS_ROOT := $(abspath $(CURDIR))
PROJECTS_ROOT := $(abspath $(SIRIUS_ROOT)/../minor-projects)
APP_AGENT_DIR := $(PROJECTS_ROOT)/app-agent
APP_TERMINAL_DIR := $(PROJECTS_ROOT)/app-terminal
APP_SCANNER_DIR := $(PROJECTS_ROOT)/app-scanner
# Container that hosts the agent / terminal / scanner Go binaries.
ENGINE_CONTAINER ?= sirius-engine
# Cross-compile target arch. Override with HOST_GOARCH=amd64 if needed.
UNAME_M := $(shell uname -m)
ifeq ($(UNAME_M),arm64)
HOST_GOARCH ?= arm64
else ifeq ($(UNAME_M),aarch64)
HOST_GOARCH ?= arm64
else
HOST_GOARCH ?= amd64
endif
# Where each binary lives inside the container.
#
# In production-mode images (target: runtime), start-enhanced.sh resolves
# AGENT_PATH to /app-agent-src (because /app-agent has no go.mod in that
# image) and runs $AGENT_PATH/server. Writing to /app-agent-src/server is
# therefore the right destination for production hot-swaps.
#
# In dev-mode (target: development) the engine bind-mounts the host's
# local repo over /app-agent and runs Air; the Air output (/app-agent/
# tmp/main) is the live binary, not /app-agent-src/server. Use the
# `make engine-mode` target to detect which mode the running container
# is in before invoking these.
AGENT_CONTAINER_BIN := /app-agent-src/server
TERMINAL_CONTAINER_BIN := /app-terminal/terminal
SCANNER_CONTAINER_BIN := /app-scanner/scanner
.PHONY: help \
engine-mode \
engine-rebuild-from-local \
agent-hot-swap-from-local \
terminal-hot-swap-from-local \
scanner-hot-swap-from-local \
engine-restart \
engine-logs \
_require-production-mode
# ─────────────────────────────────────────────────────────────────────
# Internal guard: hot-swap targets only meaningfully replace the live
# binary when the engine is in production mode. In dev mode:
# - /app-terminal and /app-scanner are bind-mounted, so a docker-cp
# into them writes through to the host repo (polluting it with a
# compiled artifact).
# - The live binary in dev is Air's ./tmp/main, not the production
# binary path, so the swap is functionally a no-op anyway.
# Bypass with FORCE_HOT_SWAP=1 if you really know what you want.
# ─────────────────────────────────────────────────────────────────────
_require-production-mode:
@if ! docker ps --format '{{.Names}}' | grep -qx '$(ENGINE_CONTAINER)'; then \
echo "Error: $(ENGINE_CONTAINER) is not running. Start it with 'docker compose up -d'."; \
exit 1; \
fi
@mode=$$(docker exec $(ENGINE_CONTAINER) printenv GO_ENV 2>/dev/null); \
mode=$${mode:-production}; \
if [ "$$mode" = "development" ] && [ -z "$$FORCE_HOT_SWAP" ]; then \
echo "Refusing to hot-swap: $(ENGINE_CONTAINER) is in dev mode (GO_ENV=development)."; \
echo ""; \
echo " In dev mode Air rebuilds from source on every save; the hot-swap"; \
echo " targets would (a) write a binary into your bind-mounted host repo,"; \
echo " and (b) be ignored at runtime (Air runs ./tmp/main, not the prod"; \
echo " binary path). Edit source and let Air handle it."; \
echo ""; \
echo " If you really want to run anyway, set FORCE_HOT_SWAP=1."; \
exit 1; \
fi
help:
@echo "Sirius dev-loop targets (run from the repo root)"
@echo "================================================"
@echo ""
@echo "Hot-swap (cross-compile locally, copy into running container, restart):"
@echo " agent-hot-swap-from-local Rebuild app-agent from $(APP_AGENT_DIR)"
@echo " terminal-hot-swap-from-local Rebuild app-terminal from $(APP_TERMINAL_DIR)"
@echo " scanner-hot-swap-from-local Rebuild app-scanner from $(APP_SCANNER_DIR)"
@echo " engine-rebuild-from-local Hot-swap all three at once"
@echo ""
@echo "Container management:"
@echo " engine-mode Show whether $(ENGINE_CONTAINER) is in dev or production mode"
@echo " engine-restart Restart $(ENGINE_CONTAINER)"
@echo " engine-logs Tail $(ENGINE_CONTAINER) logs"
@echo ""
@echo "Override HOST_GOARCH=amd64 to cross-compile for an amd64 container."
@echo "Cross-compiling app-scanner currently falls back to a CGO-disabled"
@echo "build because libpcap headers may not be available locally; the"
@echo "scanner target prints a clear warning if CGO is required."
@echo ""
@echo "These targets are an inner-loop convenience. The authoritative"
@echo "build path is sirius-engine/Dockerfile + GitHub-hosted minor-"
@echo "projects. Once your local change is good, push it and bump the"
@echo "Dockerfile/CI pin per documentation/dev/architecture/README.engine-component-pinning.md."
# ─────────────────────────────────────────────────────────────────────
# Agent: cross-compile cmd/server, copy into container, restart engine.
# ─────────────────────────────────────────────────────────────────────
agent-hot-swap-from-local: _require-production-mode
@test -d "$(APP_AGENT_DIR)" || { echo "Error: $(APP_AGENT_DIR) not found"; exit 1; }
@echo ">> Cross-compiling app-agent for linux/$(HOST_GOARCH)"
cd "$(APP_AGENT_DIR)" && \
CGO_ENABLED=0 GOOS=linux GOARCH=$(HOST_GOARCH) \
go build -ldflags="-w -s" -o /tmp/sirius-agent-server-local ./cmd/server/main.go
@echo ">> Copying binary into $(ENGINE_CONTAINER):$(AGENT_CONTAINER_BIN)"
docker cp /tmp/sirius-agent-server-local $(ENGINE_CONTAINER):$(AGENT_CONTAINER_BIN)
@rm -f /tmp/sirius-agent-server-local
@echo ">> Restarting $(ENGINE_CONTAINER) so the new binary takes effect"
docker restart $(ENGINE_CONTAINER) >/dev/null
@echo ">> Done. Tail logs with: make engine-logs"
# ─────────────────────────────────────────────────────────────────────
# Terminal: cross-compile cmd, copy into container, restart engine.
# ─────────────────────────────────────────────────────────────────────
terminal-hot-swap-from-local: _require-production-mode
@test -d "$(APP_TERMINAL_DIR)" || { echo "Error: $(APP_TERMINAL_DIR) not found"; exit 1; }
@echo ">> Cross-compiling app-terminal for linux/$(HOST_GOARCH)"
cd "$(APP_TERMINAL_DIR)" && \
CGO_ENABLED=0 GOOS=linux GOARCH=$(HOST_GOARCH) \
go build -ldflags="-w -s" -o /tmp/sirius-terminal-local ./cmd/main.go
@echo ">> Copying binary into $(ENGINE_CONTAINER):$(TERMINAL_CONTAINER_BIN)"
docker cp /tmp/sirius-terminal-local $(ENGINE_CONTAINER):$(TERMINAL_CONTAINER_BIN)
@rm -f /tmp/sirius-terminal-local
@echo ">> Restarting $(ENGINE_CONTAINER) so the new binary takes effect"
docker restart $(ENGINE_CONTAINER) >/dev/null
@echo ">> Done. Tail logs with: make engine-logs"
# ─────────────────────────────────────────────────────────────────────
# Scanner: cross-compile main.go, copy into container, restart engine.
# Scanner needs CGO + libpcap. We try CGO_ENABLED=1 first; if libpcap
# is missing on the host, the user must do an in-container build
# (see Phase 6c of SHA-AUDIT-2026-04.md).
# ─────────────────────────────────────────────────────────────────────
scanner-hot-swap-from-local: _require-production-mode
@test -d "$(APP_SCANNER_DIR)" || { echo "Error: $(APP_SCANNER_DIR) not found"; exit 1; }
@echo ">> Cross-compiling app-scanner for linux/$(HOST_GOARCH) (CGO required)"
@# NOTE: the "( ... )" subshell grouping is required. `if ! cd X && go build`
@# is parsed by bash as `if (! cd X) && go build`, which silently skips the
@# build when cd succeeds — exactly the wrong behavior for a build pipeline.
@if ! ( cd "$(APP_SCANNER_DIR)" && \
CGO_ENABLED=1 GOOS=linux GOARCH=$(HOST_GOARCH) \
go build -ldflags="-w -s" -o /tmp/sirius-scanner-local ./main.go ) 2>/tmp/sirius-scanner-build.err; then \
echo ""; \
echo "ERROR: Local cross-compile failed. The scanner needs libpcap headers"; \
echo " and a working linux/$(HOST_GOARCH) C cross-toolchain."; \
echo " (On macOS, the system clang cannot satisfy linux cgo deps;"; \
echo " this is expected — see workaround below.)"; \
echo ""; \
head -20 /tmp/sirius-scanner-build.err; \
echo ""; \
echo "Workaround: build inside the container instead, e.g."; \
echo " docker exec $(ENGINE_CONTAINER) bash -c \\"; \
echo " 'cd /app-scanner && CGO_ENABLED=1 GOOS=linux go build -o /app-scanner/scanner main.go'"; \
echo "Then: docker restart $(ENGINE_CONTAINER)"; \
rm -f /tmp/sirius-scanner-build.err /tmp/sirius-scanner-local; \
exit 1; \
fi
@rm -f /tmp/sirius-scanner-build.err
@echo ">> Copying binary into $(ENGINE_CONTAINER):$(SCANNER_CONTAINER_BIN)"
docker cp /tmp/sirius-scanner-local $(ENGINE_CONTAINER):$(SCANNER_CONTAINER_BIN)
@rm -f /tmp/sirius-scanner-local
@echo ">> Restarting $(ENGINE_CONTAINER) so the new binary takes effect"
docker restart $(ENGINE_CONTAINER) >/dev/null
@echo ">> Done. Tail logs with: make engine-logs"
# ─────────────────────────────────────────────────────────────────────
# Convenience: hot-swap all three. Best effort; failures don't abort
# the whole sequence so a partial dev run still completes.
# ─────────────────────────────────────────────────────────────────────
engine-rebuild-from-local:
@echo "==> agent-hot-swap-from-local"
-$(MAKE) -s agent-hot-swap-from-local
@echo ""
@echo "==> terminal-hot-swap-from-local"
-$(MAKE) -s terminal-hot-swap-from-local
@echo ""
@echo "==> scanner-hot-swap-from-local"
-$(MAKE) -s scanner-hot-swap-from-local
engine-restart:
docker restart $(ENGINE_CONTAINER)
engine-logs:
docker logs -f --tail 100 $(ENGINE_CONTAINER)
# ─────────────────────────────────────────────────────────────────────
# Diagnostic: which mode is the engine running in? Hot-swap targets
# only meaningfully replace the live binary in production mode; in dev
# mode Air owns the binary, so use plain file edits instead.
# ─────────────────────────────────────────────────────────────────────
engine-mode:
@if ! docker ps --format '{{.Names}}' | grep -qx '$(ENGINE_CONTAINER)'; then \
echo "$(ENGINE_CONTAINER) is not running."; \
exit 1; \
fi
@mode=$$(docker exec $(ENGINE_CONTAINER) printenv GO_ENV 2>/dev/null); \
mode=$${mode:-production}; \
echo "$(ENGINE_CONTAINER) GO_ENV=$$mode"; \
if [ "$$mode" = "development" ]; then \
echo ""; \
echo " Dev mode is active. Air rebuilds on save from your local repos:"; \
echo " $(APP_AGENT_DIR)"; \
echo " $(APP_TERMINAL_DIR)"; \
echo " $(APP_SCANNER_DIR)"; \
echo " *-hot-swap-from-local targets will copy a binary in but Air"; \
echo " will rebuild from source after the engine restart, so the"; \
echo " swap is non-persistent. Edit source files instead."; \
else \
echo ""; \
echo " Production mode. Hot-swap targets are appropriate here."; \
fi