|
a |
|
b/Makefile |
|
|
1 |
SHELL := /bin/bash |
|
|
2 |
|
|
|
3 |
# Detect how to open things depending on our OS |
|
|
4 |
OS = $(shell uname -s) |
|
|
5 |
ifeq ($(OS),Linux) |
|
|
6 |
OPEN=xdg-open |
|
|
7 |
else |
|
|
8 |
OPEN=open |
|
|
9 |
endif |
|
|
10 |
|
|
|
11 |
# Export all environment variables |
|
|
12 |
export |
|
|
13 |
|
|
|
14 |
# Import config variables |
|
|
15 |
include .cookiecutter/config |
|
|
16 |
|
|
|
17 |
# Ensure directory to track and log setup state exists |
|
|
18 |
$(shell mkdir -p .cookiecutter/state) |
|
|
19 |
|
|
|
20 |
.PHONY: test-setup |
|
|
21 |
## Test that everything has been setup |
|
|
22 |
test-setup: |
|
|
23 |
@echo Testing configuration |
|
|
24 |
|
|
|
25 |
@# Checking S3 |
|
|
26 |
@$(call execute_in_env, (test '${IN_PYTEST}' && echo 'In test-suite: Skipping S3 checks') ||\ |
|
|
27 |
aws s3 ls s3://${BUCKET} > /dev/null 2>&1 || echo "ERROR: No bucket") |
|
|
28 |
|
|
|
29 |
@# Github |
|
|
30 |
@(test '${IN_PYTEST}' && echo 'In test-suite: Skipping Github checks') ||\ |
|
|
31 |
git ls-remote > /dev/null 2>&1 || echo "ERROR: No Git remote" |
|
|
32 |
|
|
|
33 |
@# Pre-commit valid |
|
|
34 |
@$(call execute_in_env, pre-commit run -a) |
|
|
35 |
|
|
|
36 |
@# Metaflow |
|
|
37 |
@$(call execute_in_env, python .cookiecutter/scripts/check_metaflow_aws.py || echo "ERROR: Metaflow+AWS configuration") |
|
|
38 |
|
|
|
39 |
.PHONY: init |
|
|
40 |
## Fully initialise a project: install; setup github repo; setup S3 bucket |
|
|
41 |
init: install .cookiecutter/state/setup-bucket .cookiecutter/state/setup-github |
|
|
42 |
@echo SETUP COMPLETE |
|
|
43 |
|
|
|
44 |
.PHONY: install |
|
|
45 |
## Install a project: create conda env; install local package; setup git hooks; setup metaflow+AWS |
|
|
46 |
install: .cookiecutter/state/conda-create .cookiecutter/state/setup-git .cookiecutter/state/setup-metaflow |
|
|
47 |
@direnv reload # Now the conda env exists, reload to activate it |
|
|
48 |
|
|
|
49 |
.PHONY: inputs-pull |
|
|
50 |
## Pull `inputs/` from S3 |
|
|
51 |
inputs-pull: |
|
|
52 |
$(call execute_in_env, aws s3 sync s3://${BUCKET}/inputs inputs) |
|
|
53 |
|
|
|
54 |
.PHONY: inputs-push |
|
|
55 |
## Push `inputs/` to S3 (WARNING: this may overwrite existing files!) |
|
|
56 |
inputs-push: |
|
|
57 |
$(call execute_in_env, aws s3 sync inputs s3://${BUCKET}/inputs) |
|
|
58 |
|
|
|
59 |
.PHONY: docs |
|
|
60 |
## Build the API documentation |
|
|
61 |
docs: |
|
|
62 |
$(call execute_in_env, sphinx-apidoc -o docs/api ${REPO_NAME}) |
|
|
63 |
$(call execute_in_env, sphinx-build -b docs/ docs/_build) |
|
|
64 |
|
|
|
65 |
.PHONY: docs-clean |
|
|
66 |
## Clean the built API documentation |
|
|
67 |
docs-clean: |
|
|
68 |
rm -r docs/source/api |
|
|
69 |
rm -r docs/_build |
|
|
70 |
|
|
|
71 |
.PHONY: docs-open |
|
|
72 |
## Open the docs in the browser |
|
|
73 |
docs-open: |
|
|
74 |
$(OPEN) docs/_build/index.html |
|
|
75 |
|
|
|
76 |
.PHONY: conda-update |
|
|
77 |
## Update the conda-environment based on changes to `environment.yaml` |
|
|
78 |
conda-update: |
|
|
79 |
conda env update -n ${REPO_NAME} -f environment.yaml |
|
|
80 |
$(MAKE) -s pip-install |
|
|
81 |
@direnv reload |
|
|
82 |
|
|
|
83 |
.PHONY: clean |
|
|
84 |
## Delete all compiled Python files |
|
|
85 |
clean: |
|
|
86 |
find . -type f -name "*.py[co]" -delete |
|
|
87 |
find . -type d -name "__pycache__" -delete |
|
|
88 |
|
|
|
89 |
.PHONY: pre-commit |
|
|
90 |
## Perform pre-commit actions |
|
|
91 |
pre-commit: |
|
|
92 |
$(call execute_in_env, pre-commit) |
|
|
93 |
|
|
|
94 |
.PHONY: lint |
|
|
95 |
## Run flake8 linting on repository |
|
|
96 |
lint: |
|
|
97 |
$(call execute_in_env, flake8) |
|
|
98 |
|
|
|
99 |
.PHONY: pip-install |
|
|
100 |
## Install our package and requirements in editable mode (including development dependencies) |
|
|
101 |
pip-install: |
|
|
102 |
@$(call execute_in_env, pip install -e ".[dev]") |
|
|
103 |
|
|
|
104 |
################################################################################# |
|
|
105 |
# Helper Commands (no need to explicitly document) # |
|
|
106 |
################################################################################# |
|
|
107 |
|
|
|
108 |
define err |
|
|
109 |
(echo "$1, check $@ for more info" && exit 1) |
|
|
110 |
endef |
|
|
111 |
|
|
|
112 |
# Allow us to execute make commands from within our project's conda env |
|
|
113 |
# and with bash utilities available |
|
|
114 |
define execute_in_env |
|
|
115 |
source .cookiecutter/scripts/import.sh && conda_activate ${REPO_NAME} && $1 |
|
|
116 |
endef |
|
|
117 |
|
|
|
118 |
.cookiecutter/state/conda-create: |
|
|
119 |
@echo -n "Creating environment ${REPO_NAME} and installing all dependencies" |
|
|
120 |
@(conda env create -q -n ${REPO_NAME} -f environment.yaml\ |
|
|
121 |
&& $(call execute_in_env, pip install -e ".[dev]"))\ |
|
|
122 |
> $@.log 2>&1\ |
|
|
123 |
|| $(call err,Python environment setup failed) |
|
|
124 |
@touch $@ |
|
|
125 |
@echo " DONE" |
|
|
126 |
|
|
|
127 |
.cookiecutter/state/setup-git: |
|
|
128 |
@echo -n "Installing and configuring git pre-commit hooks" |
|
|
129 |
@$(call execute_in_env, \ |
|
|
130 |
pre-commit install --install-hooks\ |
|
|
131 |
> $@.log 2>&1\ |
|
|
132 |
|| $(call err,Git pre-commit setup failed)\ |
|
|
133 |
) |
|
|
134 |
@touch $@ |
|
|
135 |
@echo " DONE" |
|
|
136 |
|
|
|
137 |
.cookiecutter/state/setup-metaflow: |
|
|
138 |
@echo -n "Configuring Metaflow + AWS" |
|
|
139 |
@$(call execute_in_env, \ |
|
|
140 |
get_metaflow_config\ |
|
|
141 |
> $@.log 2>&1\ |
|
|
142 |
|| $(call err,AWS + Metaflow setup failed)\ |
|
|
143 |
) |
|
|
144 |
@touch $@ |
|
|
145 |
@echo " DONE" |
|
|
146 |
|
|
|
147 |
.cookiecutter/state/setup-github: |
|
|
148 |
@echo -n "Creating and configuring Github repo '${GITHUB_ACCOUNT}/${REPO_NAME}'" |
|
|
149 |
@$(call execute_in_env, \ |
|
|
150 |
create_gh_repo ${GITHUB_ACCOUNT} ${REPO_NAME} ${PROJECT_OPENNESS}\ |
|
|
151 |
> $@.log 2>&1\ |
|
|
152 |
|| $(call err,Github repo creation failed)\ |
|
|
153 |
) |
|
|
154 |
@touch $@ |
|
|
155 |
@echo " DONE" |
|
|
156 |
|
|
|
157 |
.cookiecutter/state/setup-bucket: |
|
|
158 |
@echo -n "Creating S3 bucket '${BUCKET}'" |
|
|
159 |
@$(call execute_in_env, \ |
|
|
160 |
(create_bucket ${BUCKET} && make_bucket_private ${BUCKET})\ |
|
|
161 |
> $@.log 2>&1\ |
|
|
162 |
|| $(call err,S3 Bucket creation failed)\ |
|
|
163 |
) |
|
|
164 |
@touch $@ |
|
|
165 |
@echo " DONE" |
|
|
166 |
|
|
|
167 |
|
|
|
168 |
################################################################################# |
|
|
169 |
# Self Documenting Commands # |
|
|
170 |
################################################################################# |
|
|
171 |
|
|
|
172 |
.DEFAULT_GOAL := help |
|
|
173 |
|
|
|
174 |
# Inspired by <http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html> |
|
|
175 |
# sed script explained: |
|
|
176 |
# /^##/: |
|
|
177 |
# * save line in hold space |
|
|
178 |
# * purge line |
|
|
179 |
# * Loop: |
|
|
180 |
# * append newline + line to hold space |
|
|
181 |
# * go to next line |
|
|
182 |
# * if line starts with doc comment, strip comment character off and loop |
|
|
183 |
# * remove target prerequisites |
|
|
184 |
# * append hold space (+ newline) to line |
|
|
185 |
# * replace newline plus comments by `---` |
|
|
186 |
# * print line |
|
|
187 |
# Separate expressions are necessary because labels cannot be delimited by |
|
|
188 |
# semicolon; see <http://stackoverflow.com/a/11799865/1968> |
|
|
189 |
.PHONY: help |
|
|
190 |
help: |
|
|
191 |
@echo "$$(tput bold)Available rules:$$(tput sgr0)" |
|
|
192 |
@echo |
|
|
193 |
@sed -n -e "/^## / { \ |
|
|
194 |
h; \ |
|
|
195 |
s/.*//; \ |
|
|
196 |
:doc" \ |
|
|
197 |
-e "H; \ |
|
|
198 |
n; \ |
|
|
199 |
s/^## //; \ |
|
|
200 |
t doc" \ |
|
|
201 |
-e "s/:.*//; \ |
|
|
202 |
G; \ |
|
|
203 |
s/\\n## /---/; \ |
|
|
204 |
s/\\n/ /g; \ |
|
|
205 |
p; \ |
|
|
206 |
}" ${MAKEFILE_LIST} \ |
|
|
207 |
| LC_ALL='C' sort --ignore-case \ |
|
|
208 |
| awk -F '---' \ |
|
|
209 |
-v ncol=$$(tput cols) \ |
|
|
210 |
-v indent=19 \ |
|
|
211 |
-v col_on="$$(tput setaf 6)" \ |
|
|
212 |
-v col_off="$$(tput sgr0)" \ |
|
|
213 |
'{ \ |
|
|
214 |
printf "%s%*s%s ", col_on, -indent, $$1, col_off; \ |
|
|
215 |
n = split($$2, words, " "); \ |
|
|
216 |
line_length = ncol - indent; \ |
|
|
217 |
for (i = 1; i <= n; i++) { \ |
|
|
218 |
line_length -= length(words[i]) + 1; \ |
|
|
219 |
if (line_length <= 0) { \ |
|
|
220 |
line_length = ncol - indent - length(words[i]) - 1; \ |
|
|
221 |
printf "\n%*s ", -indent, " "; \ |
|
|
222 |
} \ |
|
|
223 |
printf "%s ", words[i]; \ |
|
|
224 |
} \ |
|
|
225 |
printf "\n"; \ |
|
|
226 |
}' \ |
|
|
227 |
| more $(shell test $(shell uname) = Darwin && echo '--no-init --raw-control-chars') |