Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
229 lines (199 loc) · 12 KB
/
Copy pathMakefile
File metadata and controls
229 lines (199 loc) · 12 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
SHELL := /bin/bash
PYTHON ?= python3
VENV := venv
BIN := $(VENV)/bin
# .env holds SMARTER_API_KEY and SMARTER_BASE_URL for make test-live, and GH_TOKEN for gh.
# A new checkout starts from doc/example-dot-env.
ifeq ("$(wildcard .env)","")
$(shell cp ./doc/example-dot-env .env)
endif
-include .env
export
# PYTHONPATH is the repository root, never ./smarter, which would shadow the standard library.
export PYTHONPATH := $(CURDIR)
# The documentation site's Terraform stack (terraform/docs). The account id is read from the
# caller's AWS credentials when a target needs it, never written into this public repository.
TF := terraform -chdir=terraform/docs
AWS_ACCOUNT_ID = $(shell aws sts get-caller-identity --query Account --output text)
TF_STATE_BUCKET = $(AWS_ACCOUNT_ID)-terraform-tfstate-smarter
.PHONY: all help init check-python test test-live coverage build clean \
python-requirements sam-models contracts lint analyze pre-commit-init pre-commit-run \
sphinx-build sphinx-linkcheck sphinx-publish terraform-init terraform-plan terraform-apply \
release-dry-run release
# Default target executed when no arguments are given to make.
all: help
# ---------------------------------------------------------
# Development
# ---------------------------------------------------------
# this repository's own virtual environment, from its own pinned requirements: never another project's venv.
init:
@echo "==============================================================================="
@echo "Creating $(VENV) from requirements/local.txt, installing the package, and the git hooks ..."
@echo "==============================================================================="
make check-python
rm -rf $(VENV)
$(PYTHON) -m venv $(VENV)
$(BIN)/pip install --upgrade pip
$(BIN)/pip install -r requirements/local.txt
$(BIN)/pip install -e . --no-deps
make pre-commit-init
# requirements/in/*.in, each constrained by constraints.in, compile into the pinned requirements/*.txt.
# --no-strip-extras keeps extras such as coverage[toml], which pip-tools 8 would drop.
python-requirements:
@echo "==============================================================================="
@echo "Compiling and updating Python dependency files using pip-compile ..."
@echo "==============================================================================="
$(BIN)/pip install --upgrade "pip-tools>=7.6.1"
$(BIN)/pip-compile --upgrade --no-strip-extras requirements/in/base.in -o requirements/base.txt
$(BIN)/pip-compile --upgrade --no-strip-extras requirements/in/local.in -o requirements/local.txt
$(BIN)/pip install -r requirements/local.txt
$(BIN)/pip install -e . --no-deps
check-python:
@command -v $(PYTHON) >/dev/null 2>&1 || { echo >&2 "$(PYTHON) is not installed. Aborting."; exit 1; }
@$(PYTHON) -c "import sys; sys.exit(sys.version_info < (3, 10))" || { \
echo >&2 "smarter-python needs Python 3.10 or newer. $(PYTHON) is $$($(PYTHON) --version)."; exit 1; }
# the unit tests never reach a platform: an httpx MockTransport answers every request.
test:
@echo "==============================================================================="
@echo "Running the unit tests ..."
@echo "==============================================================================="
$(BIN)/python -m unittest discover -s tests -t .
# the SDK against a running Smarter platform, e.g. the local one:
# SMARTER_BASE_URL=http://localhost:9357 SMARTER_API_KEY=... make test-live
# These prompt an LLMClient, which makes billable LLM requests.
test-live:
@echo "==============================================================================="
@echo "Running the live tests against $(SMARTER_BASE_URL) ..."
@echo "==============================================================================="
SMARTER_TEST_LIVE=true $(BIN)/python -m unittest discover -s tests/live -t . -v
coverage:
@echo "==============================================================================="
@echo "Running the unit tests with a coverage report ..."
@echo "==============================================================================="
$(BIN)/coverage run -m unittest discover -s tests -t .
$(BIN)/coverage report
$(BIN)/coverage xml
build:
@echo "==============================================================================="
@echo "Building the sdist and wheel into dist/, and checking them with twine ..."
@echo "==============================================================================="
rm -rf dist
$(BIN)/python -m build
$(BIN)/twine check --strict dist/*
clean:
@echo "==============================================================================="
@echo "Removing build, test and coverage artifacts ..."
@echo "==============================================================================="
rm -rf build dist docs/build .pytest_cache .coverage coverage.xml htmlcov node_modules *.egg-info
find . -name __pycache__ -type d -prune -not -path "./$(VENV)/*" -exec rm -rf {} +
# ---------------------------------------------------------
# The platform's contracts
# ---------------------------------------------------------
# Copy the platform's api contracts from ../smarter: the chat and journal contracts, the SAM
# schemas and examples, and the api's OpenAPI document. A ref reads them at a commit or tag,
# e.g. make contracts SMARTER_REF=v0.20.0
contracts:
scripts/sync-contracts.sh ../smarter $(SMARTER_REF)
# Regenerate smarter/models/sam/ from the platform's committed JSON Schemas.
sam-models: contracts
$(BIN)/python scripts/generate_sam_models.py
ls smarter/models/sam/*.py | xargs $(BIN)/pre-commit run --files > /dev/null || true
# ---------------------------------------------------------
# Code Management
# ---------------------------------------------------------
lint:
make pre-commit-run
analyze:
@echo "==============================================================================="
@echo "Generating code analysis report using cloc ..."
@echo "==============================================================================="
cloc . --exclude-ext=svg,json,zip --fullpath --vcs=git
pre-commit-init:
@echo "==============================================================================="
@echo "Installing and configuring pre-commit ..."
@echo "==============================================================================="
$(BIN)/pre-commit install
$(BIN)/pre-commit autoupdate
pre-commit-run:
@echo "==============================================================================="
@echo "Running pre-commit hooks on all files ..."
@echo "==============================================================================="
$(BIN)/pre-commit run --all-files
# ---------------------------------------------------------
# Sphinx documentation: docs.smarter-python.smarter.sh
# ---------------------------------------------------------
sphinx-build:
@echo "==============================================================================="
@echo "Building the Sphinx documentation into docs/build/html, warnings as errors ..."
@echo "==============================================================================="
rm -rf docs/build
$(BIN)/sphinx-build -W --keep-going -b html -d docs/build/doctrees docs/source docs/build/html
sphinx-linkcheck:
$(BIN)/sphinx-build -b linkcheck -d docs/build/doctrees docs/source docs/build/linkcheck
# the bucket and distribution come from the Terraform stack's outputs (make terraform-apply).
sphinx-publish: sphinx-build
@echo "==============================================================================="
@echo "Publishing docs/build/html to https://docs.smarter-python.smarter.sh/ ..."
@echo "==============================================================================="
BUCKET=$$($(TF) output -raw bucket_name) && \
DISTRIBUTION=$$($(TF) output -raw distribution_id) && \
aws s3 sync docs/build/html "s3://$$BUCKET/" --delete --exclude ".doctrees/*" --exclude ".buildinfo" && \
aws cloudfront create-invalidation --distribution-id "$$DISTRIBUTION" --paths "/*" --query Invalidation.Id --output text
# ---------------------------------------------------------
# Terraform: the documentation site's AWS resources (terraform/docs)
# ---------------------------------------------------------
terraform-init:
$(TF) init -backend-config="bucket=$(TF_STATE_BUCKET)"
# writes the plan to terraform/docs/tfplan, which terraform-apply applies exactly.
terraform-plan:
TF_VAR_aws_account_id=$(AWS_ACCOUNT_ID) $(TF) plan -out=tfplan
terraform-apply:
TF_VAR_aws_account_id=$(AWS_ACCOUNT_ID) $(TF) apply tfplan
rm -f terraform/docs/tfplan
# ---------------------------------------------------------
# Release
# ---------------------------------------------------------
# main makes a release, published to TestPyPI then PyPI. RELEASE_BRANCH=alpha or beta makes a
# prerelease, published to TestPyPI only. See .github/workflows/release.yml.
RELEASE_BRANCH ?= main
release-dry-run:
@echo "==============================================================================="
@echo "Starting the Release workflow on $(RELEASE_BRANCH) as a dry run: CI, then the next version ..."
@echo "==============================================================================="
gh workflow run release.yml --ref $(RELEASE_BRANCH) -f dry_run=true
@echo "Follow it with: gh run watch"
release:
@echo "==============================================================================="
@echo "Starting the Release workflow on $(RELEASE_BRANCH): CI, release, TestPyPI and PyPI ..."
@echo "==============================================================================="
gh workflow run release.yml --ref $(RELEASE_BRANCH) -f dry_run=false
@echo "Follow it with: gh run watch"
help:
@echo '===================================================================='
@echo 'init - Create venv from requirements/local.txt, install the package and the git hooks'
@echo 'python-requirements - Compile requirements/in/*.in into the pinned requirements/*.txt, and install them'
@echo 'check-python - Verify that Python 3.10 or newer is installed'
@echo 'test - Run the unit tests, which never reach a platform'
@echo 'test-live - Test against a running Smarter platform (SMARTER_BASE_URL, SMARTER_API_KEY)'
@echo 'coverage - Run the unit tests with a coverage report, and write coverage.xml'
@echo 'build - Build the sdist and wheel into dist/, and check them'
@echo 'clean - Remove build, test and coverage artifacts'
@echo '<************************** Contracts **************************>'
@echo 'contracts - Copy the api contracts, SAM schemas and OpenAPI document from ../smarter'
@echo 'sam-models - Copy the contracts, and regenerate the SAM models from their schemas'
@echo '<************************** Code Management **************************>'
@echo 'lint - Run all code linters and formatters'
@echo 'analyze - Generate code analysis report using cloc'
@echo 'pre-commit-init - Install and configure pre-commit'
@echo 'pre-commit-run - Run all pre-commit hooks on all files'
@echo '<************************** Documentation **************************>'
@echo 'sphinx-build - Build the Sphinx docs into docs/build/html, warnings as errors'
@echo 'sphinx-linkcheck - Check every external link in the docs'
@echo 'sphinx-publish - Build the docs, upload them to S3 and invalidate CloudFront'
@echo 'terraform-init - Initialize the docs site stack (terraform/docs) and its state'
@echo 'terraform-plan - Plan changes to the docs site AWS resources, into terraform/docs/tfplan'
@echo 'terraform-apply - Apply terraform/docs/tfplan'
@echo '<************************** Release **************************>'
@echo 'release-dry-run - Run the Release workflow as a dry run: CI, then the next version'
@echo 'release - Release and publish: CI, tag, GitHub release, TestPyPI, PyPI (RELEASE_BRANCH)'
@echo '===================================================================='