Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
425 lines (363 loc) · 13.4 KB
/
Copy pathMakefile
File metadata and controls
425 lines (363 loc) · 13.4 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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
.PHONY: all develop test test-fast lint clean doc format build serve
.PHONY: testlab-serve testlab-prune testlab-schedule testlab-run
.PHONY: deploy deploy-docker clean-server clean-and-deploy
.PHONY: test-e2e test-cov test-demos test-tutorials
.PHONY: test-installer build-installers test-apps test-app test-nix
# For tests, set HOP3_DEV_HOST in your environment
all: ruff test lint doc
#
# Help
#
help:
adt help-make
#
# Development
#
## Install dependencies and setup dev environment
develop: install-deps activate-pre-commit configure-git
## Alias for develop
install: install-deps
install-deps:
@echo "--> Installing dependencies"
uv sync --inexact
activate-pre-commit:
@echo "--> Activating pre-commit hook"
pre-commit install
configure-git:
@echo "--> Configuring git"
git config branch.autosetuprebase always
## Check development environment
check-dev-env:
python3 scripts/check-dev-env.py
## Update dependencies
update-deps:
@echo "--> Updating dependencies"
# uv sync --all-groups -U
uv sync --all-packages --all-extras --all-groups -U
uv run pre-commit autoupdate
uv pip list --outdated
uv pip list --format=freeze > compliance/requirements-full.txt
## Run full development stack (web server + uWSGI emperor)
serve:
hop3-server setup
honcho -f Procfile.dev start
## Aliases for serve
dev: serve
run: serve
## Run the Test Lab web UI in dev mode (auto-reload, auth bypassed)
testlab-serve:
TESTLAB_UNSAFE=true uv run hop3-testlab serve --reload
## Prune old Test Lab build logs per the retention policy
testlab-prune:
uv run hop3-testlab prune
## Run the Test Lab nightly scheduler in the foreground
testlab-schedule:
uv run hop3-testlab schedule
## Trigger a run now (full: MODE=ci|dev|nightly, or per-app: APP=<path>; TARGET=hetzner)
testlab-run:
uv run hop3-testlab run --target $(or $(TARGET),hetzner) --trigger manual \
$(if $(APP),--apps $(APP),--mode $(or $(MODE),ci))
## Run only the web server (without uWSGI)
serve-web:
litestar --app asgi:create_app run --debug --reload
#
# Code Quality
#
## Quick lint
ruff:
uv run ruff format --check packages/*/src packages/*/tests
uv run ruff check packages/*/src packages/*/tests
## Lint and type check
lint:
@echo "--> Linting code"
@make ruff
uv run pyrefly check packages/hop3-*/src
# uv run ty check ...
uv run zuban check \
packages/hop3-cli/src \
packages/hop3-installer/src \
packages/hop3-marketplace/src \
packages/hop3-rootd/src \
packages/hop3-server/src \
packages/hop3-testing/src \
packages/hop3-testlab/src \
packages/hop3-tooling/src \
packages/hop3-tui/src
uv run mypy packages/hop3-*/src
cd packages/hop3-server && uv run deptry src
@echo ""
## Alias for lint (used by CI)
check: lint
## Format code
format:
@echo "--> Formatting code"
uv run ruff format packages/*/src packages/*/tests
uv run ruff check --fix packages/*/src packages/*/tests
@make update-tocs
# python scripts/update-copyright.py
@echo ""
update-tocs:
uv run markdown-toc --maxdepth 3 -i README.md
# uv run markdown-toc --maxdepth 3 -i notes/todo/TODO-next.md
# uv run markdown-toc --maxdepth 3 -i notes/todo/TODO-NGI.md
uv run markdown-toc --maxdepth 3 -i notes/testing/status.md
## Run security audit
audit:
@echo "--> Running security audit"
nox -e audit
@echo ""
#
# Testing
#
## Fast lane — unit tests, all packages, no Docker (< 1 min). The inner loop.
test-fast:
@echo "--> Fast tests (unit, all packages, no Docker)"
uv run pytest \
packages/hop3-server/tests/a_unit \
packages/hop3-cli/tests \
packages/hop3-rootd/tests/a_unit \
packages/hop3-installer/tests/a_unit \
packages/hop3-tui/tests/a_unit \
packages/hop3-testing/tests \
packages/hop3-testlab/tests/a_unit \
packages/hop3-marketplace/tests \
packages/hop3-tooling/tests \
docs/tests
@echo ""
## Check tier — full in-process suite, all packages, no Docker. The pre-push gate.
test:
@echo "--> Check tier (unit + integration, all packages, no Docker)"
uv run pytest \
packages/hop3-server/tests/a_unit \
packages/hop3-server/tests/b_integration \
packages/hop3-cli/tests \
packages/hop3-rootd/tests \
packages/hop3-installer/tests/a_unit \
packages/hop3-installer/tests/b_integration \
packages/hop3-tui/tests/a_unit \
packages/hop3-tui/tests/b_integration \
packages/hop3-testing/tests \
packages/hop3-testlab/tests/a_unit \
packages/hop3-marketplace/tests \
packages/hop3-tooling/tests \
docs/tests
@echo ""
## Docker e2e — backups, git-push, real deploys (needs Docker). Part of the check gate.
## Always Docker-only: the root conftest makes HOP3_DEV_HOST/HOP3_TEST_HOST taboo
## for pytest, so no `unset` dance is needed. Remote is opt-in via `--ssh-host`.
test-e2e:
@echo "--> Docker e2e tests (c_e2e) — server + installer + tui"
uv run pytest packages/hop3-server/tests/c_e2e
uv run pytest packages/hop3-installer/tests/c_e2e --docker
uv run pytest packages/hop3-tui/tests/c_e2e
@echo ""
## Coverage — the in-process layers (what coverage.py can actually see)
test-cov:
@echo "--> Coverage (unit + integration)"
uv run pytest --cov=hop3 \
packages/hop3-server/tests/a_unit \
packages/hop3-server/tests/b_integration
@echo ""
## Run demos on Docker (SSH backend: python demos/demo.py run --host $$HOP3_DEV_HOST --local)
test-demos:
@echo "--> Resetting test server (docker)"
hop3-deploy-server --docker --from local --with all --clean
@echo "--> Running demos on Docker backend"
python demos/demo.py run --backend docker --local --quiet
@echo ""
## Run tutorials (validoc doc-as-tests)
test-tutorials:
@echo "--> Running tutorials (validoc)"
python ./scripts/run-all-tutorials.py
@echo ""
#
# App / deploy testing (hop3-test) — deploys real apps to a target.
# `hop3-test` is the interface; the targets below are just front doors. For
# other variants, call the CLI directly:
# list available tests uv run hop3-test list
# deploy from local code uv run hop3-test run --from local [--clean]
# nightly matrix + report uv run hop3-test run --docker --mode nightly --report html
#
## Deploy Hop3 + run the app catalog on Docker (the apps tier)
test-apps:
@echo "--> Testing apps on Docker (hop3-test run)"
uv run hop3-test run --docker
@echo ""
## The sibling catalog checkout. Real applications live there; this repo keeps
## the platform fixtures (test-apps-*, demos, tutorials). `hop3-test` spans both
## by default — override with `hop3-test --catalog <dir>` or CATALOG_APPS here.
CATALOG_APPS ?= ../hop3-catalog/apps
## Test one app or path: make test-app APP=../hop3-catalog/apps/golden/gitea
test-app:
@if [ -z "$(APP)" ]; then echo "Usage: make test-app APP=<app-path-or-name>"; exit 1; fi
uv run hop3-test run --docker $(APP)
## One maturity tier: make test-apps-golden | -beta | -alpha | -broken
## A pattern rule, not five targets — the statuses are hop3-test's to know
## (it rejects an unknown one), and a copy here would be a second list to keep
## in step with the catalog's folders.
test-apps-%:
uv run hop3-test run --docker --status $*
## Deploy Hop3 + run the Nix suite (the M2.2 nix-runtime gate).
## Docker by default; pass HOST=<box> to run it against a real server.
## Deliberately NOT taken from an env var: an ambient value silently
## redirecting a deploy at someone's server is the ADR 043 taboo.
##
## Selected by TECHNOLOGY (`--covers nix`), not by folder. This used to point at
## the catalog's `beta` tier because every Nix recipe happened to live there —
## which stopped being true the moment one was promoted or demoted, and already
## missed the 34 Nix recipes filed under `alpha` and `broken`. Maturity and build
## tech are orthogonal axes; only one of them describes a Nix app. As a gate it
## still runs the publishable tiers only — `alpha`/`broken` Nix recipes are
## reachable with `hop3-test run --status alpha --covers nix`.
NIX_SUITE = apps/test-apps-nix apps/test-apps-nix-gen
test-nix:
@echo "--> Testing Nix apps (hop3-test run --covers nix)$(if $(HOST), on $(HOST), on Docker)"
uv run hop3-test run $(if $(HOST),--host $(HOST),--docker) --with nix \
--status golden --status beta --covers nix $(NIX_SUITE)
## Reproducibility gate: rebuild every nix-gen app and fail if any output drifts
## The catalog files `-nix` and `-nixgen` together under `beta`, but the tier
## does not have to be selected by path: `_nix_gen_recipes` already keeps only
## recipes declaring `[nix].template`, which is exactly the generated ones (19
## of beta's 34; the other 15 are hand-written and carry a hop3.nix instead).
.PHONY: check-reproducible
check-reproducible:
@echo "--> Checking nix-gen reproducibility (nix build --rebuild)"
uv run hop3-tools nix check-reproducible $${HOP3_NIX_SSH:+--ssh $$HOP3_NIX_SSH} \
apps/test-apps-nix-gen $(CATALOG_APPS)/beta
@echo ""
## Advertised gate (nix-gen tier): reproducible build AND clean deploy.
## An app can rebuild bit-identically yet fail to start — directus rebuilt
## deterministically while isolated-vm was uncompiled (blocker #17). Build
## determinism alone never proves the app runs, so an app is advertise-ready
## only when BOTH halves pass. check-reproducible runs first (fail-fast); the
## deploy check (test-nix) runs only if it passes.
.PHONY: gate-nix
## Both halves take the same target: HOP3_NIX_SSH picks the build host,
## HOST the deploy host. Passing neither runs the build locally and the deploy
## on Docker, which is a weaker gate than it looks.
gate-nix:
@echo "--> Advertised gate (nix-gen): reproducible build AND clean deploy"
$(MAKE) check-reproducible
$(MAKE) test-nix HOST=$(HOST)
@echo "==> gate-nix PASSED: nix-gen tier is reproducible AND deploys."
#
# Installer Testing
#
## Build single-file installers
build-installers:
@echo "--> Building single-file installers"
@mkdir -p installer
uv run hop3-install bundle --all --output-dir installer/
@echo ""
## Test installers (Docker by default, use 'hop3-install test --help' for more options)
test-installer: build-installers
@echo "--> Testing installers in Docker"
uv run hop3-install test docker --distro ubuntu --type both --method local
uv run hop3-install test ssh --distro ubuntu --type both --method local
@echo ""
#
# Deployment
#
## Deploy to development server (set HOP3_DEV_HOST)
deploy:
@echo "--> Deploying to ${HOP3_DEV_HOST}"
uv run hop3-deploy-server --from local
## Deploy to local Docker container
deploy-docker:
@echo "--> Deploying to Docker container"
uv run hop3-deploy-server --from local --docker
## Clean development server (WARNING: removes everything)
clean-server:
@echo "--> Cleaning server (WARNING: removes everything)"
-ssh root@${HOP3_DEV_HOST} apt-get purge -y nginx nginx-core nginx-common
ssh root@${HOP3_DEV_HOST} rm -rf /home/hop3 /etc/nginx
## Clean server and redeploy
clean-and-deploy:
make clean-server
make deploy
#
# Build & Release
#
## Build Python packages
build:
@make clean
uv build packages/hop3-server
uv build packages/hop3-rootd
uv build packages/hop3-cli
uv build packages/hop3-installer
uv build packages/hop3-testing
uv build packages/hop3-tui
## Publish to PyPI (legacy, use 'make release' instead)
publish: clean build
twine upload --skip-existing dist/*
## Release all packages to PyPI (checks versions, builds, uploads)
release:
python scripts/release.py
## Dry-run release (build but don't upload)
release-dry-run:
python scripts/release.py --dry-run
## Generate SBOM for CRA compliance
generate-sbom:
@echo "--> Generating SBOM"
make clean
rm -rf .venv
uv sync -q --no-dev
uv pip list --format=freeze > compliance/requirements-prod.txt
syft .venv \
-o spdx-json=compliance/sbom-spdx.json \
-o cyclonedx-json=compliance/sbom-cyclonedx.json \
-o syft-text=compliance/sbom-syft.txt
npx prettier -w compliance/sbom-spdx.json
npx prettier -w compliance/sbom-cyclonedx.json
uv sync -q
#
# Documentation
#
## Build documentation
doc:
@echo "--> Building documentation"
cd docs && $(MAKE) build
## Check the experience reports against the recipes they describe (NGI M4)
reports-check:
@echo "--> Validating experience reports"
uv run hop3-tools catalog reports
## Bundle the experience reports into one PDF (NGI M4 deliverable)
## Deliberately NOT gated on reports-check: the bundle is useful while the
## reports are being migrated, and a blocked build teaches nothing a warning
## does not. Run `make reports-check` for the verdict.
reports-pdf:
@echo "--> Bundling experience reports"
uv run hop3-tools catalog reports --bundle notes/experience-reports/_bundle.md
uv run md2pdf --class report -o experience-reports.pdf \
notes/experience-reports/_bundle.md
@rm -f notes/experience-reports/_bundle.md
@echo "--> Wrote experience-reports.pdf (run 'make reports-check' for the verdict)"
## Serve documentation locally
doc-serve:
@echo "--> Serving documentation"
cd docs && $(MAKE) serve
## Deploy documentation to hop3.cloud
doc-deploy:
@echo "--> Deploying documentation"
make doc
cd docs && make deploy
#
# Cleanup
#
## Clean build artifacts
clean:
bash -c "shopt -s globstar && rm -f **/*.pyc"
bash -c "shopt -s globstar && rm -rf **/.ruff_cache"
bash -c "shopt -s globstar && rm -rf **/.pytest_cache"
bash -c "shopt -s globstar && rm -rf **/.mypy_cache"
find . -type d -empty -delete
rm -rf *.egg-info *.egg .coverage .eggs .cache .mypy_cache .pyre \
.pytest_cache .pytest .DS_Store docs/_build docs/cache docs/tmp \
dist build pip-wheel-metadata junit-*.xml htmlcov coverage.xml \
tmp htmlcov-hop3-testing
rm -rf packages/*/dist packages/*/.pdm-build
rm -rf .nox
rm -rf docs/site
rm -rf docs/.cache
rm -rf test-logs/
# adt clean