-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathMakefile
More file actions
256 lines (227 loc) · 9.24 KB
/
Makefile
File metadata and controls
256 lines (227 loc) · 9.24 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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# @cpt-algo:cpt-cypilot-spec-init-structure-change-infrastructure:p1
.PHONY: test test-verbose test-quick test-coverage test-coverage-diff validate validate-examples validate-feature validate-code validate-code-feature self-check validate-kits validate-kits-sdlc vulture vulture-ci pylint install install-pipx install-proxy clean help check-pytest check-pytest-cov check-pipx check-vulture check-pylint check-versions update spec-coverage ci lint-ci
# Detect container architecture for act (arm64 on Apple Silicon, amd64 otherwise)
UNAME_M := $(shell uname -m)
ifeq ($(UNAME_M),arm64)
ACT_ARCH := linux/arm64
else ifeq ($(UNAME_M),aarch64)
ACT_ARCH := linux/arm64
else
ACT_ARCH := linux/amd64
endif
ACT_FLAGS ?= --container-architecture $(ACT_ARCH)
PYTHON ?= python3
PIPX ?= pipx
CPT ?= cpt
PYTEST_PIPX ?= $(PIPX) run --spec pytest pytest
PYTEST_PIPX_COV ?= $(PIPX) run --spec pytest-cov pytest
VULTURE_PIPX ?= $(PIPX) run --spec vulture vulture
PYLINT_PIPX ?= $(PIPX) run --spec pylint pylint
DIFF_COVER_PIPX ?= $(PIPX) run --spec diff-cover diff-cover
DIFF_COVER_COMPARE ?= main
DIFF_COVER_MIN ?= 80
VULTURE_MIN_CONF ?= 0
PYLINT_TARGETS ?= src/cypilot_proxy skills/cypilot/scripts/cypilot
# Default target
help:
@echo "Cypilot Makefile"
@echo ""
@echo "Available targets:"
@echo " make test - Run all tests"
@echo " make test-verbose - Run tests with verbose output"
@echo " make test-quick - Run fast tests only (skip slow integration tests)"
@echo " make test-coverage - Run tests with coverage report"
@echo " make test-coverage-diff - Coverage for diff vs main (≥$(DIFF_COVER_MIN)%)"
@echo " make validate-examples - Validate requirements examples under examples/requirements"
@echo " make validate - Validate core methodology spec"
@echo " make self-check - Validate SDLC examples against their templates"
@echo " make validate-kits - Validate all registered kits"
@echo " make validate-kits-sdlc - Validate kits/sdlc kit by path"
@echo " make check-versions - Check version consistency across components"
@echo " make spec-coverage - Check spec coverage (≥90% overall, ≥60% per file)"
@echo " make vulture - Scan python code for dead code (report only, does not fail)"
@echo " make vulture-ci - Scan python code for dead code (fails if findings)"
@echo " make ci - Run full CI pipeline locally"
@echo " make lint-ci - Lint GitHub Actions workflow files"
@echo " make install - Install Python dependencies"
@echo " make install-proxy - Reinstall cpt proxy from local source"
@echo " make update - Update .bootstrap from local source"
@echo " make clean - Remove Python cache files"
@echo " make help - Show this help message"
# Run all tests
check-pipx:
@command -v $(PIPX) >/dev/null 2>&1 || { \
echo ""; \
echo "ERROR: pipx not found"; \
echo ""; \
echo "Install it with:"; \
echo " brew install pipx"; \
echo " pipx ensurepath"; \
echo ""; \
exit 1; \
}
check-pytest: check-pipx
@$(PYTEST_PIPX) --version >/dev/null 2>&1 || { \
echo ""; \
echo "ERROR: pytest is not runnable via pipx"; \
echo ""; \
echo "Install it with:"; \
echo " make install"; \
echo ""; \
exit 1; \
}
check-pytest-cov: check-pytest
@$(PYTEST_PIPX_COV) --help 2>/dev/null | grep -q -- '--cov' || { \
echo ""; \
echo "ERROR: pytest-cov not available (missing --cov option)"; \
echo ""; \
echo "Install it with:"; \
echo " make install"; \
echo ""; \
exit 1; \
}
check-vulture: check-pipx
@$(VULTURE_PIPX) --version >/dev/null 2>&1 || { \
echo ""; \
echo "ERROR: vulture is not runnable via pipx"; \
echo ""; \
echo "Install it with:"; \
echo " pipx install vulture"; \
echo "or just run: make vulture (pipx run will download it)"; \
echo ""; \
exit 1; \
}
check-pylint: check-pipx
@$(PYLINT_PIPX) --version >/dev/null 2>&1 || { \
echo ""; \
echo "ERROR: pylint is not runnable via pipx"; \
echo ""; \
echo "Install it with:"; \
echo " pipx install pylint"; \
echo "or just run: make pylint (pipx run will download it)"; \
echo ""; \
exit 1; \
}
test: check-pytest
@echo "Running Cypilot tests with pipx..."
$(PYTEST_PIPX) tests/ -v --tb=short
# Run tests with verbose output
test-verbose: check-pytest
@echo "Running Cypilot tests (verbose) with pipx..."
$(PYTEST_PIPX) tests/ -vv
# Run quick tests only
test-quick: check-pytest
@echo "Running quick tests with pipx..."
$(PYTEST_PIPX) tests/ -v -m "not slow"
# Run tests with coverage
test-coverage: check-pytest-cov
@echo "Running tests with coverage..."
$(PYTEST_PIPX_COV) tests/ \
--cov=skills/cypilot/scripts/cypilot \
--cov-report=term-missing \
--cov-report=json:coverage.json \
--cov-report=xml:coverage.xml \
--cov-report=html \
-v --tb=short
@$(PYTHON) scripts/check_coverage.py coverage.json --root skills/cypilot/scripts/cypilot --min 90
@echo ""
@echo "Coverage report generated:"
@echo " HTML: htmlcov/index.html"
@echo " XML: coverage.xml"
@echo " Open with: open htmlcov/index.html"
@if git rev-parse --verify $(DIFF_COVER_COMPARE) >/dev/null 2>&1 && \
! git diff --quiet $(DIFF_COVER_COMPARE) -- 2>/dev/null; then \
echo ""; \
echo "Checking diff coverage vs $(DIFF_COVER_COMPARE) (min $(DIFF_COVER_MIN)%)..."; \
$(DIFF_COVER_PIPX) coverage.xml \
--compare-branch=$(DIFF_COVER_COMPARE) \
--fail-under=$(DIFF_COVER_MIN) \
--diff-range-notation='..' \
--show-uncovered; \
else \
echo ""; \
echo "Skipping diff coverage (no diff vs $(DIFF_COVER_COMPARE) or branch not found)"; \
fi
# Run diff-coverage standalone (reuses existing coverage.xml)
test-coverage-diff:
@if [ ! -f coverage.xml ]; then \
echo "ERROR: coverage.xml not found. Run 'make test-coverage' first."; \
exit 1; \
fi
@if git rev-parse --verify $(DIFF_COVER_COMPARE) >/dev/null 2>&1 && \
! git diff --quiet $(DIFF_COVER_COMPARE) -- 2>/dev/null; then \
echo "Checking diff coverage vs $(DIFF_COVER_COMPARE) (min $(DIFF_COVER_MIN)%)..."; \
$(DIFF_COVER_PIPX) coverage.xml \
--compare-branch=$(DIFF_COVER_COMPARE) \
--fail-under=$(DIFF_COVER_MIN) \
--diff-range-notation='..' \
--show-uncovered; \
else \
echo "Skipping diff coverage (no diff vs $(DIFF_COVER_COMPARE) or branch not found)"; \
fi
vulture: check-vulture
@echo "Running vulture dead-code scan (excluding tests by scanning only skills/cypilot/scripts/cypilot)..."
@echo "Tip: raise/lower VULTURE_MIN_CONF to reduce false positives (current: $(VULTURE_MIN_CONF))."
@$(VULTURE_PIPX) skills/cypilot/scripts/cypilot vulture_whitelist.py --min-confidence $(VULTURE_MIN_CONF) || true
vulture-ci: check-vulture
@echo "Running vulture dead-code scan (CI mode, fails if findings)..."
$(VULTURE_PIPX) skills/cypilot/scripts/cypilot vulture_whitelist.py --min-confidence $(VULTURE_MIN_CONF)
pylint: check-pylint
@echo "Running pylint..."
PYTHONPATH=src:skills/cypilot/scripts $(PYLINT_PIPX) $(PYLINT_TARGETS)
# Spec coverage check (Cypilot system only)
spec-coverage:
@echo "Checking spec coverage (Cypilot system)..."
$(PYTHON) .bootstrap/.core/skills/cypilot/scripts/cypilot.py spec-coverage --system cypilot --min-coverage 90 --min-file-coverage 60 --min-granularity 0.45
# Check version consistency
check-versions:
@$(PYTHON) scripts/check_versions.py
# Update .bootstrap from local source
update:
$(CPT) update --source . --force
# Validate core methodology spec
validate:
$(CPT) validate
# Validate SDLC examples against templates
self-check:
@echo "Running self-check: validating SDLC examples against templates..."
$(CPT) self-check
# Validate all registered kits
validate-kits:
@echo "Validating all registered kits..."
$(CPT) validate-kits
# Validate kits/sdlc kit by path
validate-kits-sdlc:
@echo "Validating kits/sdlc..."
$(CPT) validate-kits kits/sdlc
# Install Python dependencies
install-pipx: check-pipx
@echo "Installing pytest + pytest-cov via pipx..."
@$(PIPX) install pytest >/dev/null 2>&1 || $(PIPX) upgrade pytest
@$(PIPX) inject pytest pytest-cov
@echo "Done. If pytest is not found, run: pipx ensurepath (then restart your shell)."
install: install-pipx
# Reinstall cpt/cypilot proxy from local source
install-proxy: check-pipx
$(PIPX) install --force .
# Lint CI workflow files
lint-ci:
@echo "Linting GitHub Actions workflows..."
actionlint
# Run CI via act in Docker (mirrors .github/workflows/ci.yml exactly)
# Runs jobs sequentially — stops on first failure.
# Auto-detects arm64/amd64. Override: make ci ACT_FLAGS="--your-flags"
ci: lint-ci
@for job in $$(act push --list $(ACT_FLAGS) 2>/dev/null | tail -n +2 | awk '{print $$2}' | grep -v '^sonarqube$$'); do \
echo "▶ Running job: $$job"; \
act push -j $$job $(ACT_FLAGS) || exit 1; \
done
@echo ""
@echo "✓ All CI jobs passed."
# Clean Python cache
clean:
@echo "Cleaning Python cache files..."
find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
find . -type f -name "*.pyc" -delete
find . -type d -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true
@echo "Clean complete"