-
Notifications
You must be signed in to change notification settings - Fork 513
Expand file tree
/
Copy pathcommon.mk
More file actions
409 lines (351 loc) · 10.9 KB
/
common.mk
File metadata and controls
409 lines (351 loc) · 10.9 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
# Common items for all Starcraft Makefiles. Should only be edited in the `starbase` repository:
# https://github.com/canonical/starbase
SOURCES=$(wildcard *.py) $(PROJECT) tests
# Env vars for the docs Starter Pack. They must be exported so make can pass them to the
# docs Makefile.
export BUILDDIR ?= _build
export VENVDIR ?= ../.venv
export VALEDIR ?= $(VENVDIR)/lib/python*/site-packages/vale
ifneq ($(OS),Windows_NT)
OS := $(shell uname)
endif
ifdef CI
APT := apt-get --yes
else
APT := apt-get
endif
PRETTIER=npm exec --package=prettier@3.6.0 -- prettier --log-level warn # renovate: datasource=npm
PRETTIER_FILES="**/*.{yaml,yml,json,json5,css,md}"
# Cutoff (in seconds) before a test is considered slow by pytest
SLOW_CUTOFF_TIME ?= 1
# By default we should not update the uv lock file here.
export UV_FROZEN := true
.DEFAULT_GOAL := help
.ONESHELL:
.SHELLFLAGS = -ec
.PHONY: help
help: ## Show this help.
@printf "\e[1m%-30s\e[0m | \e[1m%s\e[0m\n" "Target" "Description"
printf "\e[2m%-30s + %-41s\e[0m\n" "------------------------------" "------------------------------------------------"
egrep '^[^:]+\: [^#]*##' $$(echo $(MAKEFILE_LIST) | tac --separator=' ') | sed -e 's/^[^:]*://' -e 's/:[^#]*/ /' | sort -V| awk -F '[: ]*' \
'{
if ($$2 == "##")
{
$$1=sprintf(" %-28s", $$1);
$$2=" | ";
print $$0;
}
else
{
$$1=sprintf(" └ %-25s", $$1);
$$2=" | ";
$$3=sprintf(" └ %s", $$3);
print $$0;
}
}' | uniq
.PHONY: setup
setup: install-uv _setup-docs _setup-lint _setup-tests setup-precommit install-build-deps ## Set up the development environment
uv sync $(UV_TEST_GROUPS) $(UV_LINT_GROUPS) $(UV_DOCS_GROUPS)
.PHONY: setup-docs
setup-docs: _setup-docs ##- Set up the documentation-only environment
uv sync --no-dev $(UV_DOCS_GROUPS)
.PHONY: _setup-docs
_setup-docs: install-uv
.PHONY: setup-lint
setup-lint: _setup-lint ##- Set up a linting-only environment
uv sync $(UV_LINT_GROUPS)
.PHONY: _setup-lint
_setup-lint: install-uv install-shellcheck install-pyright install-lint-build-deps
.PHONY: setup-tests
setup-tests: _setup-tests ##- Set up a testing environment without linters
uv sync $(UV_TEST_GROUPS)
.PHONY: _setup-tests
_setup-tests: install-uv install-build-deps
.PHONY: setup-tics
setup-tics: install-uv install-build-deps ##- Set up a testing environment for Tiobe TICS
uv venv
uv sync $(UV_TEST_GROUPS) $(UV_LINT_GROUPS) $(UV_TICS_GROUPS)
ifneq ($(CI),)
echo $(PWD)/.venv/bin >> $(GITHUB_PATH)
endif
.PHONY: setup-precommit
setup-precommit: install-uv ##- Set up pre-commit hooks in this repository.
ifeq ($(shell which pre-commit),)
uv tool run pre-commit install
else
pre-commit install
endif
.PHONY: clean
clean: ## Clean up the development environment
uv tool run pyclean .
rm -rf dist/ build/ docs/_build/ docs/_linkcheck *.snap .coverage*
.PHONY: autoformat
autoformat: format # Hidden alias for 'format'
.PHONY: format-ruff
format-ruff: install-ruff ##- Automatically format with ruff
success=true
ruff check --fix $(SOURCES) || success=false
ruff format $(SOURCES)
$$success || exit 1
.PHONY: format-codespell
format-codespell: ##- Fix spelling issues with codespell
uv run codespell --toml pyproject.toml --write-changes $(SOURCES)
.PHONY: format-pre-commit
format-pre-commit: ##- Format the entire repository using pre-commit
uv tool run pre-commit run
.PHONY: format-prettier
format-prettier: install-npm ##- Format files with prettier
$(PRETTIER) --write $(PRETTIER_FILES)
.PHONY: lint-ruff
lint-ruff: install-ruff ##- Lint with ruff
ifneq ($(CI),)
@echo ::group::$@
endif
ruff check $(SOURCES)
ruff format --diff $(SOURCES)
ifneq ($(CI),)
@echo ::endgroup::
endif
.PHONY: lint-codespell
lint-codespell: install-codespell ##- Check spelling with codespell
ifneq ($(CI),)
@echo ::group::$@
endif
uv run codespell --toml pyproject.toml $(SOURCES)
ifneq ($(CI),)
@echo ::endgroup::
endif
.PHONY: lint-mypy
lint-mypy: ##- Check types with mypy
ifneq ($(CI),)
@echo ::group::$@
endif
uv run mypy --show-traceback --show-error-codes $(PROJECT)
ifneq ($(CI),)
@echo ::endgroup::
endif
.PHONY: lint-pyright
lint-pyright: ##- Check types with pyright
ifneq ($(CI),)
@echo ::group::$@
endif
ifneq ($(shell which pyright),) # Prefer the system pyright
pyright --pythonpath .venv/bin/python
else
uv tool run pyright --pythonpath .venv/bin/python
endif
ifneq ($(CI),)
@echo ::endgroup::
endif
.PHONY: lint-ty
lint-ty: install-ty ##- Check types with Astral ty (disabled by default)
ifneq ($(CI),)
@echo ::group::$@
endif
ty check --python .venv/bin/python $(SOURCES)
ifneq ($(CI),)
@echo ::endgroup::
endif
.PHONY: lint-uv-lockfile
lint-uv-lockfile: install-uv ##- Check that uv.lock matches expectations from pyproject.toml
unset UV_FROZEN
uv lock --check
.PHONY: lint-shellcheck
lint-shellcheck: ##- Lint shell scripts
ifneq ($(CI),)
@echo ::group::$@
endif
@# jinja2 shell script templates are mistakenly counted as "true" shell scripts due to their shebang,
@# so explicitly filter them out
git ls-files | grep -vE "\.sh\.j2$$" | file --mime-type -Nnf- | grep shellscript | cut -f1 -d: | xargs -r shellcheck
ifneq ($(CI),)
@echo ::endgroup::
endif
.PHONY: lint-prettier
lint-prettier: install-npm ##- Lint files with prettier
ifneq ($(CI),)
@echo ::group::$@
endif
$(PRETTIER) --check $(PRETTIER_FILES)
ifneq ($(CI),)
@echo ::endgroup::
endif
# Legacy alias for linting docs
.PHONY: lint-docs
lint-docs: docs-lint ##- Lint the documentation
.PHONY: lint-twine
lint-twine: pack-pip ##- Lint Python packages with twine
ifneq ($(CI),)
@echo ::group::$@
endif
uv tool run twine check dist/*
ifneq ($(CI),)
@echo ::endgroup::
endif
.PHONY: test
test: ## Run all tests
uv run pytest
.PHONY: test-fast
test-fast: ##- Run fast tests
uv run pytest -m 'not slow'
.PHONY: test-slow
test-slow: ##- Run slow tests
uv run pytest -m 'slow'
.PHONY: test-coverage
test-coverage: ## Generate coverage report
ifeq ($(COVERAGE_SOURCE),)
uv run coverage run --source $(PROJECT),tests -m pytest
else
uv run coverage run --source $(COVERAGE_SOURCE),tests -m pytest
endif
uv run coverage xml -o results/coverage.xml
# for backwards compatibility
# https://github.com/canonical/starflow/blob/3447d302cb7883cbb966ce0ec7e5b3dfd4bb3019/.github/workflows/test-python.yaml#L109
cp results/coverage.xml coverage.xml
uv run coverage report -m
uv run coverage html
.PHONY: test-find-slow
test-find-slow: ##- Identify slow tests. Set cutoff time in seconds with SLOW_CUTOFF_TIME
uv run pytest --durations 0 --durations-min $(SLOW_CUTOFF_TIME)
# Alias for `html` target in docs project. We want to use our own `.venv`, so we
# replace it.
.PHONY: docs
docs: docs-install ## Render the documentation to disk
$(MAKE) -C docs html --no-print-directory
# Alias for `serve` target in docs project
.PHONY: docs-auto
docs-auto: docs-install ##- Render the documentation in a live session
$(MAKE) -C docs run --no-print-directory
# Override for `install` target in docs project. We still need the Vale setup, so we
# run that after the parent docs setup.
.PHONY: docs-install
docs-install: setup-docs ##- Set up documentation packages
$(MAKE) -C docs vale-install --no-print-directory
# Alias for `setup-docs`
.PHONY: docs-setup
docs-setup: setup-docs
# Override for `clean` target in docs project. We don't want to touch `.venv`, so
# we pass a null dir instead.
.PHONY: docs-clean
docs-clean: ##- Clean the temporary files used in documentation
VENVDIR=$(mktemp)
$(MAKE) -C docs clean --no-print-directory
# Override for `help` target in docs project
.PHONY: docs-help
docs-help: ##- List the individual commands in the documentation subproject.
@echo "Commands in the documentation subproject:"
$(MAKE) -C docs help --no-print-directory
@echo "Run these commands from inside the 'docs/' directory."
# Override for `pymarkdownlnt-install` target in docs project. Make it a noop.
.PHONY: docs-pymarkdownlnt-install
docs-pymarkdownlnt-install:
@echo "Cannot run 'docs-pymarkdownlnt'. This project doesn't use Markdown."
# Override for `lint-md` target in docs project. Make it a noop.
.PHONY: docs-lint-md
docs-lint-md:
@echo "Cannot run 'docs-lint-md'. This project doesn't use Markdown."
# Passthrough for the rest of the targets in docs project
.PHONY: docs-%
docs-%: docs-install
$(MAKE) -C docs $(@:docs-%=%) --no-print-directory
# Run our own docs linting, then pass to the docs
.PHONY: docs-lint
docs-lint: docs ##- Lint the documentation
ifneq ($(CI),)
@echo ::group::$@
endif
uv run $(UV_DOCS_GROUPS) sphinx-lint docs \
--ignore docs/.sphinx \
--ignore docs/_build \
--ignore docs/reference/commands \
--enable all \
-d line-too-long,missing-underscore-after-hyperlink,missing-space-in-hyperlink
$(MAKE) -C docs spelling --no-print-directory
$(MAKE) -C docs woke --no-print-directory
$(MAKE) -C docs linkcheck --no-print-directory
ifneq ($(CI),)
@echo ::endgroup::
endif
.PHONY: pack-pip
pack-pip: ##- Build packages for pip (sdist, wheel)
ifneq ($(CI),)
@echo ::group::$@
endif
uv build --quiet .
ifneq ($(CI),)
@echo ::endgroup::
endif
# Below are intermediate targets for setup. They are not included in help as they should
# not be used independently.
.PHONY: install-uv
install-uv:
ifneq ($(shell which uv),)
else ifneq ($(shell which snap),)
sudo snap install --classic astral-uv
else ifneq ($(shell which brew),)
brew install uv
else ifeq ($(OS),Windows_NT)
pwsh -c "irm https://astral.sh/uv/install.ps1 | iex"
else
curl -LsSf https://astral.sh/uv/install.sh | sh
endif
.PHONY: install-codespell
install-codespell:
ifneq ($(shell which codespell),)
else ifneq ($(shell which snap),)
sudo snap install codespell
else ifneq ($(shell which brew),)
make install-uv
uv tool install codespell
else
$(warning Codespell not installed. Please install it yourself.)
endif
.PHONY: install-pyright
install-pyright: install-uv
ifneq ($(shell which pyright),)
else ifneq ($(shell which snap),)
sudo snap install --classic pyright
else
# Workaround for a bug in npm
[ -d "$(HOME)/.npm/_cacache" ] && chown -R `id -u`:`id -g` "$(HOME)/.npm" || true
uv tool install pyright
endif
.PHONY: install-ruff
install-ruff:
ifneq ($(shell which ruff),)
else ifneq ($(shell which snap),)
sudo snap install ruff
else
make install-uv
uv tool install ruff
endif
.PHONY: install-shellcheck
install-shellcheck:
ifneq ($(shell which shellcheck),)
else ifneq ($(shell which snap),)
sudo snap install shellcheck
else ifneq ($(shell which brew),)
brew install shellcheck
else
$(warning Shellcheck not installed. Please install it yourself.)
endif
.PHONY: install-ty
install-ty:
ifneq ($(shell which ty),)
else ifneq ($(shell which snap),)
sudo snap install --classic --edge astral-ty
sudo snap alias astral-ty.ty ty
else
make install-uv
uv tool install ty
endif
.PHONY: install-npm
install-npm:
ifneq ($(shell which npm),)
else ifneq ($(shell which snap),)
sudo snap install --classic node
else ifneq ($(shell which brew),)
brew install node
else
$(error npm not installed. Please install it yourself.)
endif