diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fed2619..d0091ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,8 +31,8 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v7 - - name: Install toolchains - run: make install-tools + - name: Install lint and format tooling + run: make install-format-tools install-lint-tools - name: Format check run: make ci-format-check @@ -87,12 +87,13 @@ jobs: - name: Install Python dependencies run: | uv pip install --system -r app/requirements.txt - make install-tools + make install-opa - name: Wait for database run: | - for i in {1..30}; do + for attempt in {1..30}; do pg_isready -h 127.0.0.1 -p 5432 -U postgres -d app_test && exit 0 + echo "Waiting for Postgres ($attempt/30)..." sleep 1 done echo "Postgres did not become ready" >&2 @@ -121,11 +122,8 @@ jobs: go-version-file: go.mod check-latest: true - - name: Install uv - uses: astral-sh/setup-uv@v7 - - name: Prepare tooling - run: make install-tools + run: make install-security-tools - name: Run security checks run: make security @@ -190,16 +188,3 @@ jobs: # Start services briefly to test startup timeout 30s docker compose -f docker-compose.secure.yml up --abort-on-container-exit || true - - opa-policy-test: - name: Test OPA Policies - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup OPA - uses: open-policy-agent/setup-opa@v2 - - - name: Run policy tests - run: make opa-test diff --git a/Makefile b/Makefile index b0f87e1..827195b 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ GOSEC ?= $(GOBIN)/gosec OPA ?= opa export PATH := $(GOBIN):$(PATH) -.PHONY: all tidy build test lint format lint-go lint-python format-go format-python docker-up docker-down docker-logs db-migrate opa-test cert-refresh setup-venv security install-hooks +.PHONY: all tidy build test lint format lint-go lint-python format-go format-python docker-up docker-down docker-logs db-migrate opa-test cert-refresh setup-venv security install-hooks install-tools install-format-tools install-lint-tools install-security-tools install-opa check-tools check-format-tools check-lint-tools check-test-tools all: build @@ -80,14 +80,31 @@ cert-refresh: go run ./cmd/authz cert-refresh # Tool installation and checks -install-tools: - @echo "Installing Go tools..." +install-tools: install-format-tools install-lint-tools install-security-tools install-opa + +install-format-tools: + @echo "Installing format tools..." mkdir -p $(GOBIN) - GOPROXY=https://proxy.golang.org,direct go install github.com/golangci/golangci-lint/cmd/golangci-lint@v$(GOLANGCI_LINT_VERSION) go install golang.org/x/tools/cmd/goimports@v0.36.0 + uv tool install black + uv tool install isort + +install-lint-tools: + @echo "Installing lint tools..." + mkdir -p $(GOBIN) + GOPROXY=https://proxy.golang.org,direct go install github.com/golangci/golangci-lint/cmd/golangci-lint@v$(GOLANGCI_LINT_VERSION) + uv tool install flake8 + uv tool install mypy + +install-security-tools: + @echo "Installing security tools..." + mkdir -p $(GOBIN) go install golang.org/x/vuln/cmd/govulncheck@latest go install github.com/securego/gosec/v2/cmd/gosec@v2.22.6 + +install-opa: @echo "Ensuring OPA CLI is available..." + mkdir -p $(GOBIN) @NEED_OPA=1; \ if command -v opa >/dev/null 2>&1; then \ if opa version >/dev/null 2>&1; then \ @@ -115,11 +132,6 @@ install-tools: chmod +x $(GOBIN)/opa.tmp; \ mv $(GOBIN)/opa.tmp $(GOBIN)/opa; \ fi - @echo "Installing Python tools..." - uv tool install black - uv tool install flake8 - uv tool install isort - uv tool install mypy setup-venv: uv venv $(VENV) @@ -140,6 +152,18 @@ check-tools: @command -v mypy >/dev/null 2>&1 || { echo "mypy not found. Run 'make install-tools'"; exit 1; } @echo "All tools are available!" +check-format-tools: + @command -v black >/dev/null 2>&1 || { echo "black not found. Run 'make install-format-tools'"; exit 1; } + @command -v isort >/dev/null 2>&1 || { echo "isort not found. Run 'make install-format-tools'"; exit 1; } + +check-lint-tools: + @test -x "$(GOLANGCI_LINT)" || { echo "golangci-lint not found at $(GOLANGCI_LINT). Run 'make install-lint-tools'"; exit 1; } + @command -v flake8 >/dev/null 2>&1 || { echo "flake8 not found. Run 'make install-lint-tools'"; exit 1; } + @command -v mypy >/dev/null 2>&1 || { echo "mypy not found. Run 'make install-lint-tools'"; exit 1; } + +check-test-tools: + @command -v pytest >/dev/null 2>&1 || { echo "pytest not found. Install app requirements first"; exit 1; } + security: @echo "Running govulncheck..." @# govulncheck currently fails due to golang.org/x/sync/semaphore type info missing via github.com/jackc/puddle/v2 @@ -150,9 +174,9 @@ security: $(GOSEC) ./... # CI/CD targets -ci-lint: check-tools lint -ci-test: check-tools test -ci-format-check: check-tools +ci-lint: check-lint-tools lint +ci-test: check-test-tools test +ci-format-check: check-format-tools @echo "Checking Go formatting..." @if [ "$$(gofmt -l . | wc -l)" -ne 0 ]; then echo "Go files need formatting. Run 'make format-go'"; exit 1; fi @echo "Checking Python formatting..."