-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathMakefile
More file actions
196 lines (162 loc) · 7.13 KB
/
Makefile
File metadata and controls
196 lines (162 loc) · 7.13 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
################################################################################################
# Project's Makefile
#
# This Makefile is split into the following sections:
# - Requirements: prerequisites for running the environment.
# - Application: for building, testing, and publishing the project.
# - Development: for formatting, linting, and other development tasks.
# - Docker: for building, running, and publishing Docker images.
#
# We write our rule names in the following format: [verb]-[noun]-[noun], e.g. "build-app".
#
# Variables ####################################################################################
PROJECT_ROOT:=$(CURDIR)
PYTHON_VERSION:=`cat .python-version`
APP_VERSION?=DEV-SNAPSHOT
APP_NAME?=logging-http-client
SRC_DIR?=logging_http_client
IMAGE_ID?=$(APP_NAME):$(APP_VERSION)
IMAGE_SAVE_LOCATION?=$(PROJECT_ROOT)/build/images
# Requirements ##################################################################################
.PHONY: require-pyenv
require-pyenv:
@command -v pyenv >/dev/null 2>&1 || (echo "Pyenv is required. Please install via 'make install-pyenv'." && exit 1)
.PHONY: require-poetry
require-poetry:
@command -v poetry >/dev/null 2>&1 || (echo "Poetry is required. Please install via 'make install-poetry'." && exit 1)
.PHONY: require-docker
require-docker:
@command -v docker >/dev/null 2>&1 || (echo "Docker is required. Please install via https://docs.docker.com/engine/install/." && exit 1)
.PHONY: install-pyenv
install-pyenv:
@echo "Installing Pyenv..."
@curl https://pyenv.run | bash
.PHONY: install-poetry
install-poetry:
@echo "Installing Poetry..."
@curl -sSL https://install.python-poetry.org | python3 -
# Application ##################################################################################
.PHONY: setup
setup: require-poetry require-pyenv configure-ide-settings enable-code-quality-pre-commit-hook
@echo "Setting up the project..."
@echo "Setting local shell Python version to $(PYTHON_VERSION)..."
@deactivate 2>/dev/null || true
@pyenv install -s $(PYTHON_VERSION)
@pyenv local $(PYTHON_VERSION)
@poetry env remove --all 2>/dev/null || true
@poetry config virtualenvs.prefer-active-python true
@echo "Installing Poetry dependencies..."
@poetry install
@echo "Setup complete."
@echo "Your virtual environment python path is:"
@echo "$$(poetry env info --path)/bin/python"
.PHONY: test
test:
@echo "Running tests..."
@poetry run pytest -s -v $(PROJECT_ROOT)/tests
# Development ##################################################################################
.PHONY: clean
clean:
@echo "Cleaning application (e.g. cache, build files, virtual environment)..."
@poetry run pyclean -v ./$(SRC_DIR) ./tests
@poetry env remove $$(basename $$(poetry env info --path))
@echo "Cleaning complete."
@echo "Running 'make setup' to setup the project again."
@echo "NOTE: For PyCharm users, you might need to attach the new Poetry interpreter to the project."
@$(MAKE) setup
.PHONY: update-dependencies
update-dependencies:
@echo "Updating dependencies..."
@poetry update
.PHONY: lock-dependencies
lock-dependencies:
@echo "Locking dependencies..."
@poetry lock
.PHONY: format-code
format-code:
@echo "Formatting application..."
@poetry run black $(PROJECT_ROOT)/$(SRC_DIR) $(PROJECT_ROOT)/tests
.PHONY: lint-code
lint-code:
@echo "Linting application..."
@poetry run flake8 $(PROJECT_ROOT)/$(SRC_DIR) $(PROJECT_ROOT)/tests
.PHONY: check-format
check-format:
@echo "Checking application formatting..."
@poetry run black --check $(PROJECT_ROOT)/$(SRC_DIR) $(PROJECT_ROOT)/tests
.PHONY: check-lint
check-lint:
@echo "Checking application linting..."
@poetry run flake8 --show-source --statistics --count $(PROJECT_ROOT)/$(SRC_DIR) $(PROJECT_ROOT)/tests
.PHONY: enable-code-quality-pre-commit-hook
enable-code-quality-pre-commit-hook:
@echo "Enabling pre-commit hook..."
@ln -sf $(PROJECT_ROOT)/.hooks/pre-commit $(PROJECT_ROOT)/.git/hooks/pre-commit
@echo "Pre-commit hook enabled."
.PHONE: disable-code-quality-pre-commit-hook
disable-code-quality-pre-commit-hook:
@echo "Disabling pre-commit hook..."
@rm -f $(PROJECT_ROOT)/.git/hooks/pre-commit
@echo "Pre-commit hook disabled."
.PHONY: configure-ide-settings
configure-ide-settings:
@echo "Configuring IDE settings..."
@mkdir -p $(PROJECT_ROOT)/.idea
@cp $(PROJECT_ROOT)/.ide/logging-http-client.iml $(PROJECT_ROOT)/.idea/logging-http-client.iml
@mkdir -p $(PROJECT_ROOT)/.vscode
@cp $(PROJECT_ROOT)/.ide/settings.json $(PROJECT_ROOT)/.vscode/settings.json
# Docker #######################################################################################
.PHONY: check-test-docker
check-test-docker: require-docker
@echo "Testing application... (Containerised)"
@$(call build_docker_image,development)
@$(call run_docker_dev_mount,poetry run pytest -v /app/tests)
.PHONY: check-format-docker
check-format-docker: require-docker
@echo "Checking application formatting... (Containerised)"
@$(call build_docker_image,development)
@$(call run_docker_dev_mount,poetry run black --check /app/$(SRC_DIR) /app/tests)
.PHONY: check-lint-docker
check-lint-docker: require-docker
@echo "Checking application linting... (Containerised)"
@$(call build_docker_image,development)
@$(call run_docker_dev_mount,poetry run flake8 --show-source --statistics --count /app/$(SRC_DIR) /app/tests)
.PHONY: check-code-quality-docker
check-code-quality-docker: require-docker
@echo "Checking application code quality... (Containerised)"
@$(MAKE) check-format-docker
@$(MAKE) check-lint-docker
@$(MAKE) check-test-docker
.PHONY: build-python-package-docker
build-python-package-docker: require-docker
@echo "Building Python package... (Containerised)"
@$(call build_docker_image,development)
@$(call run_docker_dev_mount,poetry build)
.PHONY: publish-to-pypi-docker
publish-to-pypi-docker: require-docker
@echo "Publishing Python package to $(TARGET)... (Containerised)"
@test -n "$(TARGET)" || (echo "TARGET is not set. Please set the target repository." && exit 1)
@test -n "$(PYPI_API_TOKEN)" || (echo "PYPI_API_TOKEN is not set. Please set the PyPI API token." && exit 1)
@$(call build_docker_image,development)
@$(call run_docker_dev_mount, /bin/bash -c "\
poetry config repositories.prod-pypi https://upload.pypi.org/legacy/ && \
poetry config repositories.test-pypi https://test.pypi.org/legacy/ && \
poetry publish -r $(TARGET) --username __token__ --password $(PYPI_API_TOKEN)")
# Functions ####################################################################################
define build_docker_image
@echo "Building Docker image for target: $(1)"
@docker build --target $(1) --build-arg APP_VERSION=$(APP_VERSION) --build-arg APP_NAME=$(APP_NAME) -t $(IMAGE_ID) .
endef
define run_docker_dev_mount
@docker run $(2) \
--network=host \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(PROJECT_ROOT)/$(SRC_DIR):/app/$(SRC_DIR) \
-v $(PROJECT_ROOT)/tests:/app/tests \
-v $(PROJECT_ROOT)/pyproject.toml:/app/pyproject.toml \
-v $(PROJECT_ROOT)/poetry.lock:/app/poetry.lock \
-v $(PROJECT_ROOT)/README.md:/app/README.md \
-v $(PROJECT_ROOT)/LICENSE:/app/LICENSE \
-v $(PROJECT_ROOT)/dist:/app/dist \
--rm --name $(APP_NAME)-toolchain-dev $(IMAGE_ID) $(1)
endef