-
Notifications
You must be signed in to change notification settings - Fork 0
/
Makefile
157 lines (120 loc) · 4.81 KB
/
Makefile
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
# Ensure the .make folder exists when starting make
# We need this for build targets that have multiple or no file output.
# We 'touch' files in here to mark the last time the specific job completed.
_ := $(shell mkdir -p .make)
SHELL := bash
.ONESHELL:
.SHELLFLAGS := -eu -o pipefail -c
MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules
# Derive the app name from the git remote repo name and not trust what the local folder name is.
# https://stackoverflow.com/a/42543006/622276
GIT_REMOTE_URL=$(shell git config --get remote.origin.url)
APP_NAME=$(shell basename -s .git ${GIT_REMOTE_URL})
APP_NAME_KEBAB=$(APP_NAME)
APP_NAME_SNAKE=$(subst -,_,$(APP_NAME))
AWS_ACCOUNT_ID=
AWS_PROFILE=
include .env
AWS_ECR_REGION=ap-southeast-2
ECR_REGISTRY=$(AWS_ACCOUNT_ID).dkr.ecr.$(AWS_ECR_REGION).amazonaws.com
ECR_REPOSITORY=$(ECR_REGISTRY)/$(APP_NAME_KEBAB)
DOCKER_PYTHON_BASE=3.12-slim
all: directory_setup init lock dev fix docs typecheck test
# Named targets are ".PHONY" and get built always. Do not depend on them in the Makefile build chain.
.PHONY: all init lock prod dev clean directory_setup docker-build docker-run docker-push docker-login debug_env
debug_env:
@echo $(DOT_ENV_FILE)
@echo $(AWS_PROFILE)
@echo $(ECR_REGISTRY)
# ==================== SETUP ====================
directory_setup: .make/directory_setup
.make/directory_setup: $(REQUIRED_DIRS)
@touch $@
$(REQUIRED_DIRS):
mkdir -p $(REQUIRED_DIRS)
# Ensure the virtualenvironment is created
init: .venv/bin/python3 requirements%.txt
# Ensure the virtual environment has the correct basic tooling before we get to the pyproject.toml
.venv/bin/python3:
[ ! -d ".venv" ] && python3 -m venv .venv || echo ".venv already setup"
.venv/bin/python3 -m pip install -qq --upgrade pip uv build wheel pre-commit
.venv/bin/pre-commit install
# Ensure the lock files get generated based on changes to pyproject.toml
lock: requirements%.txt
requirements%.txt: pyproject.toml .venv/bin/python3
# Prod only deps
.venv/bin/python3 -m uv pip compile --no-cache --refresh --generate-hashes --upgrade -o requirements-macos.txt pyproject.toml
# Prod conatiner only deps
.venv/bin/python3 -m uv pip compile \
--python-platform linux \
--no-cache --refresh --generate-hashes --upgrade \
-o requirements-linux.txt pyproject.toml
# Dev dependencies
.venv/bin/python3 -m uv pip compile --no-cache --refresh --extra dev --upgrade -o requirements-dev-macos.txt pyproject.toml
# Install the necessary dependencies depending if it is prod or dev build
# The .make/*-deps-installed is a sentinel file we 'touch' to mark the job complete with '@touch $@'
prod: .make/prod-deps-installed
.make/prod-deps-installed: requirements-macos.txt
.venv/bin/python3 -m uv pip install \
--require-hashes --no-deps \
-r requirements-macos.txt
.venv/bin/python3 -m uv pip install . # <- the app/pkg itself
@touch $@
dev: .make/dev-deps-installed
.make/dev-deps-installed: requirements-dev-macos.txt
.venv/bin/python3 -m uv pip install \
-r requirements-dev-macos.txt \
--editable . # <- the app/pkg itself
@touch $@
# ==================== QUALITY ASSURANCE (CI) ====================
fix: .make/dev-deps-installed
# Formatting
.venv/bin/ruff format .
.venv/bin/isort src/ tests/ scripts
# Lint Fix
.venv/bin/ruff check . --fix
# Precommit validations checks
.venv/bin/pre-commit run
# Final isort to enforce import headings not yet supported in ruff
.venv/bin/isort src/ test/ scripts
typecheck: .make/dev-deps-installed
.venv/bin/mypy src
docs: .make/dev-deps-installed
.venv/bin/md_toc --in-place github --header-levels 4 README.md guides/*.md
test: .make/dev-deps-installed
.venv/bin/python3 -m pytest
wheel:
.venv/bin/python3 -m build --wheel --installer uv
run: .make/dev-deps-installed
.venv/bin/python3 -m ${APP_NAME_SNAKE}
# ==================== PACKAGING / DEPLOYMENT (CD) ====================
docker-login:
aws --profile $(AWS_PROFILE) ecr get-login-password --region $(AWS_ECR_REGION) | docker login --username AWS --password-stdin $(AWS_ACCOUNT_ID).dkr.ecr.$(AWS_ECR_REGION).amazonaws.com
docker-clean:
docker buildx prune -a -f
docker image prune -f
docker-build:
docker buildx build \
--build-arg TARGET_PYTHON_VERSION=$(DOCKER_PYTHON_BASE) \
--build-arg PROJECT_NAME=$(APP_NAME_SNAKE) \
--progress plain \
-t $(APP_NAME_KEBAB):latest \
-t $(ECR_REPOSITORY):latest \
-f containers/docker/Dockerfile \
.
docker tag $(APP_NAME_KEBAB):latest $(ECR_REPOSITORY):latest
docker-run:
docker run -i -t --env-file .env $(APP_NAME_KEBAB)
docker-push: docker-build docker-login
docker push $(ECR_REPOSITORY):latest
# ==================== TEARDOWN ====================
clean:
rm -rfv .make/
rm -rfv $(REQUIRED_DIRS)
rm -rfv .venv
rm -rfv requirements*.txt
rm -rfv src/${APP_NAME_SNAKE}.egg-info
rm -rfv dist/
docker image prune -f
docker buildx prune -f