-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathMakefile
More file actions
171 lines (138 loc) · 5.37 KB
/
Copy pathMakefile
File metadata and controls
171 lines (138 loc) · 5.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# Copyright 2026 Smith authors
# SPDX-License-Identifier: Apache-2.0
#
# Smith — project Makefile
# =============================================================================
# Targets mirror CI (.github/workflows/ci.yml) so a green `make ci` locally
# means a green pipeline. Package management uses `uv`.
SHELL := /bin/bash
.SHELLFLAGS := -eu -o pipefail -c
.DEFAULT_GOAL := help
PYTHON ?= python3
UV ?= uv
POLICY := assets/policy.rego
LICENSE_TOOL := src/smith/tools/license_headers.py
# The OPA scorecard harness ships inside the package; in a repo/skill checkout
# it lives under src/. `make test` runs from the skill root (BASE_URL).
HARNESS := src/smith/policy_testing
# OPA server (policy testing)
OPA_CONTAINER := smith-opa
OPA_IMAGE := openpolicyagent/opa:1.8.0-static
# =============================================================================
# Help
# =============================================================================
.PHONY: help
help:
@echo "Smith — Makefile (uv-based)"
@echo ""
@echo "Setup: install Create a uv venv and install Smith (editable) + [dev] extras"
@echo "Lint & format: lint / format ruff + black over src/ (lint is read-only)"
@echo " lint-policy Lint assets/policy.rego with Regal (or OPA)"
@echo "License headers: license / license-check"
@echo "Test: test Policy scorecard (starts OPA in Docker, runs the harness)"
@echo " opaserver/start|stop|status"
@echo "Package: package/dist, wheel, sdist, verify, publish-test, publish, clean"
@echo "Gate: build (CLI smoke), audit, ci (lint + lint-policy + license-check)"
# =============================================================================
# Setup
# =============================================================================
.PHONY: install
install:
@test -d .venv || $(UV) venv
@$(UV) pip install -e ".[dev]"
@echo "✅ Smith installed (uv venv). Try: smith --help"
# =============================================================================
# Lint & format (ruff + black; config + pins in pyproject.toml [dev])
# =============================================================================
# Pinned linters run in isolated uvx envs (matches the CI pins) so linting never
# drags in the heavy runtime dependency tree.
RUFF := uvx ruff@0.15.20
BLACK := uvx black@26.5.1
.PHONY: lint
lint:
@$(RUFF) check src && $(BLACK) --check src
@echo "✅ lint passed"
.PHONY: format fmt
format fmt:
@$(RUFF) check --fix src && $(BLACK) src
.PHONY: lint-policy
lint-policy:
@if command -v regal >/dev/null 2>&1; then \
regal lint $(POLICY); \
elif command -v opa >/dev/null 2>&1; then \
opa check $(POLICY); \
else \
echo "ERROR: install Regal (https://github.com/StyraInc/regal) or OPA to lint policies"; \
exit 1; \
fi
# =============================================================================
# License headers
# =============================================================================
.PHONY: license
license:
@$(PYTHON) $(LICENSE_TOOL) --fix
.PHONY: license-check
license-check:
@$(PYTHON) $(LICENSE_TOOL) --check
# =============================================================================
# Policy testing (OPA server + scorecard harness)
# =============================================================================
.PHONY: opaserver/start
opaserver/start:
@echo "Starting OPA server on :8181 (policy: $(POLICY))"
@docker run -d --name $(OPA_CONTAINER) --rm -p 8181:8181 \
-v "$(CURDIR)/$(POLICY):/policy/policy.rego" $(OPA_IMAGE) \
run --server /policy/policy.rego --addr=0.0.0.0:8181 >/dev/null
.PHONY: opaserver/stop
opaserver/stop:
@-docker stop $(OPA_CONTAINER) >/dev/null 2>&1 || true
.PHONY: opaserver/status
opaserver/status:
@docker ps -q --filter "name=$(OPA_CONTAINER)" --filter "status=running"
.PHONY: test
test: opaserver/stop opaserver/start
@sleep 3
@PATH="$(CURDIR)/.venv/bin:$$PATH" SMITH_ROOT="$(CURDIR)" \
bash $(HARNESS)/score_card.sh "$(CURDIR)" >/dev/null || true
@$(MAKE) --no-print-directory opaserver/stop
@cat references/scorecard/scorecard_summary.txt 2>/dev/null || true
.PHONY: audit
audit:
@uvx pip-audit || true
# =============================================================================
# Package & publish (uv)
# =============================================================================
.PHONY: package dist
package dist: clean
@$(UV) build
@echo "✅ Built sdist + wheel under dist/"
.PHONY: wheel
wheel:
@$(UV) build --wheel
.PHONY: sdist
sdist:
@$(UV) build --sdist
.PHONY: verify
verify: dist
@$(UV) run --with twine twine check dist/*
.PHONY: publish-test
publish-test: verify
@$(UV) publish --publish-url https://test.pypi.org/legacy/ dist/*
.PHONY: publish
publish: verify
@$(UV) publish dist/*
.PHONY: clean
clean:
@rm -rf dist build *.egg-info src/*.egg-info .pytest_cache .ruff_cache
@find . -type d -name __pycache__ -prune -exec rm -rf {} + 2>/dev/null || true
# =============================================================================
# Gate
# =============================================================================
.PHONY: build
build:
@test -d .venv || $(UV) venv
@$(UV) pip install -e .
@$(UV) run smith --help >/dev/null && echo "✅ CLI smoke test passed (smith --help)"
.PHONY: ci
ci: lint lint-policy license-check
@echo "✅ CI gate passed (lint + lint-policy + license-check)"