-
Notifications
You must be signed in to change notification settings - Fork 2
/
Justfile
223 lines (187 loc) · 9.47 KB
/
Justfile
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
# This is a "Justfile". "just" is a task-runner similar to "make", but much less frustrating.
# There is a VS Code extension for just that provides syntax highlighting.
#
# Execute any commands in this file by running "just <command name>", e.g. "just install".
set dotenv-load := true
AWS_PROFILE := "mlops-club"
AWS_REGION := "us-west-2"
AWS_CDK_DIR := "./infrastructure"
FAST_API_DIR := "./rest-api"
# install the project's python packages and other useful
install: require-venv
# install useful VS Code extensions
which code && code --install-extension njpwerner.autodocstring || echo "skipping install of autodocstring"
which code && code --install-extension kokakiwi.vscode-just || echo "skipping install of vscode-just"
cp .vscode/example-settings.json settings.json || echo ".vscode/settings.json already present"
# install python packages not belonging to any particular package in this repo,
# but important for development
python -m pip install \
pre-commit \
phitoduck-projen \
black \
pylint \
flake8 \
mypy
# install the minecraft-deployment package as an "editable" package
python -m pip install -e {{AWS_CDK_DIR}}[all] -e {{FAST_API_DIR}}[all]
# install pre-commit hooks to protect the quality of code committed by contributors
pre-commit install
# # install git lfs for downloading rootski CSVs and other large files in the repo
# git lfs install
cdk-deploy: #require-venv
cd {{AWS_CDK_DIR}} \
&& \
AWS_PROFILE={{AWS_PROFILE}} \
AWS_ACCOUNT_ID=$(just get-aws-account-id) \
CDK_DEFAULT_REGION={{AWS_REGION}} \
AWS_REGION={{AWS_REGION}} \
cdk deploy \
--all \
--diff \
--require-approval never \
--profile {{AWS_PROFILE}} \
--region {{AWS_REGION}} \
--app "python app.py" --hotswap
# --require-approval any-change
cdk-diff: #require-venv
cd {{AWS_CDK_DIR}} \
&& \
AWS_PROFILE={{AWS_PROFILE}} \
AWS_ACCOUNT_ID=$(just get-aws-account-id) \
CDK_DEFAULT_REGION={{AWS_REGION}} \
AWS_REGION={{AWS_REGION}} \
cdk diff \
--profile {{AWS_PROFILE}} \
--region {{AWS_REGION}} \
--app "python3 app.py"
cdk-destroy: #require-venv
cd {{AWS_CDK_DIR}} \
&& \
AWS_PROFILE={{AWS_PROFILE}} \
AWS_ACCOUNT_ID=`just get-aws-account-id` \
CDK_DEFAULT_REGION={{AWS_REGION}} \
cdk destroy --all --diff --profile {{AWS_PROFILE}} --region {{AWS_REGION}} --app "python3 app.py"
# generate CloudFormation from the code in "{{AWS_CDK_DIR}}"
cdk-synth: require-venv #login-to-aws
cd {{AWS_CDK_DIR}} && \
AWS_PROFILE={{AWS_PROFILE}} \
AWS_ACCOUNT_ID=$(just get-aws-account-id) \
CDK_DEFAULT_REGION={{AWS_REGION}} \
AWS_REGION={{AWS_REGION}} \
cdk synth --all --profile mlops-club --app "python3 app.py"
open-aws:
#!/bin/bash
MLOPS_CLUB_SSO_START_URL="https://d-926768adcc.awsapps.com/start"
open $MLOPS_CLUB_SSO_START_URL
# Ensure that an "mlops-club" AWS CLI profile is configured. Then go through an AWS SSO
# sign in flow to get temporary credentials for that profile. If this command finishes successfully,
# you will be able to run AWS CLI commands against the MLOps club account using '--profile mlops-club'
# WARNING: this login only lasts for 8 hours
login-to-aws:
#!/bin/bash
MLOPS_CLUB_AWS_PROFILE_NAME="mlops-club"
MLOPS_CLUB_AWS_ACCOUNT_ID="630013828440"
MLOPS_CLUB_SSO_START_URL="https://d-926768adcc.awsapps.com/start"
MLOPS_CLUB_SSO_REGION="us-west-2"
# TODO: make this check work so we can uncomment it. It will make it so we only have to
# open our browser if our log in has expired or we have not logged in before.
# skip if already logged in
# aws sts get-caller-identity --profile ${MLOPS_CLUB_AWS_PROFILE_NAME} | cat | grep 'UserId' > /dev/null \
# && echo "[mlops-club] ✅ Logged in with aws cli" \
# && exit 0
# configure an "[mlops-club]" profile in aws-config
echo "[mlops-club] Configuring an AWS profile called '${MLOPS_CLUB_AWS_PROFILE_NAME}'"
aws configure set sso_start_url ${MLOPS_CLUB_SSO_START_URL} --profile ${MLOPS_CLUB_AWS_PROFILE_NAME}
aws configure set sso_region ${MLOPS_CLUB_SSO_REGION} --profile ${MLOPS_CLUB_AWS_PROFILE_NAME}
aws configure set sso_account_id ${MLOPS_CLUB_AWS_ACCOUNT_ID} --profile ${MLOPS_CLUB_AWS_PROFILE_NAME}
aws configure set sso_role_name AdministratorAccess --profile ${MLOPS_CLUB_AWS_PROFILE_NAME}
aws configure set region ${MLOPS_CLUB_SSO_REGION} --profile ${MLOPS_CLUB_AWS_PROFILE_NAME}
# login to AWS using single-sign-on
aws sso login --profile ${MLOPS_CLUB_AWS_PROFILE_NAME} \
&& echo '' \
&& echo "[mlops-club] ✅ Login successful. AWS CLI commands will now work by adding the '--profile ${MLOPS_CLUB_AWS_PROFILE_NAME}' 😃" \
&& echo " Your '${MLOPS_CLUB_AWS_PROFILE_NAME}' profile has temporary credentials using this identity:" \
&& echo '' \
&& aws sts get-caller-identity --profile ${MLOPS_CLUB_AWS_PROFILE_NAME} | cat
# certain boilerplate files like setup.cfg, setup.py, and .gitignore are "locked";
# you can modify their contents by editing the .projenrc.py file in the root of the repo.
update-boilerplate-files: require-venv
python .projenrc.py
# throw an error if a virtual environment isn't activated;
# add this as a requirement to other targets that you want to ensure always run in
# some kind of activated virtual environment
require-venv:
#!/usr/bin/env python
import sys
from textwrap import dedent
def get_base_prefix_compat():
"""Get base/real prefix, or sys.prefix if there is none."""
return getattr(sys, "base_prefix", None) or getattr(sys, "real_prefix", None) or sys.prefix
def in_virtualenv():
return get_base_prefix_compat() != sys.prefix
if not in_virtualenv():
print(dedent("""\
⛔️ ERROR: 'just' detected that you have not activated a python virtual environment.
Science has shown that installing python packages (e.g. 'pip install pandas')
without a virtual environment increases likelihood of getting ulcers and COVID. 🧪👩🔬
To resolve this error, please activate a virtual environment by running
whichever of the following commands apply to you:
```bash
# create a (virtual) copy of the python just for this project
python -m venv ./venv/
# activate that copy of python (now 'which python' points to your new virtual copy)
source ./venv/bin/activate
# re-run whatever 'just' command you just tried to run, for example
just install
```
-- Sincerely, The venv police 👮 🐍
"""))
sys.exit(1)
print("[mlops-club] ✅ Virtual environment is active")
# print the AWS account ID of the current AWS_PROFILE to stdout
get-aws-account-id:
#!/usr/bin/env python3
import json
import subprocess
args = ["aws", "sts", "get-caller-identity", "--profile", "{{AWS_PROFILE}}"]
proc = subprocess.run(args, capture_output=True)
aws_cli_response = json.loads(proc.stdout)
print(aws_cli_response["Account"])
# run quality checks and autoformatters against your code
lint: require-venv
pre-commit run --all-files
publish-python-package-test:
twine upload \
--repository-url "https://test.pypi.org/legacy/" \
--username "${TEST_PYPI__TWINE_USERNAME}" \
--password "${TEST_PYPI__TWINE_PASSWORD}" \
--verbose \
dist/*
publish-python-package-prod:
twine upload \
--repository-url "https://upload.pypi.org/legacy/" \
--username "${TWINE_USERNAME}" \
--password "${TWINE_PASSWORD}" \
--verbose \
dist/*
clean:
rm -rf ./dist/ **/dist/ || echo "no matches found for **/dist/"
rm -rf .projen/ **/.projen/ || echo "no matches found for **/.projen/"
rm -rf ./build/ **/build/ || echo "no matches found for **/build/"
rm -rf ./build_/ **/build_/ || echo "no matches found for **/build/"
rm -rf ./cdk.out/ **/cdk.out/ || echo "no matches found for **/cdk.out/"
rm -rf ./.DS_Store/ **/.DS_Store || echo "no matches found for **/.DS_Store"
rm -rf ./.mypy_cache/ **/.mypy_cache || echo "no matches found for **/.mypy_cache"
rm -rf ./.pytest_cache/ **/.pytest_cache || echo "no matches found for **/*.pytest_cache"
rm -rf ./test/ **/test || echo "no matches found for **/test"
rm -rf ./.coverage/ **/.coverage || echo "no matches found for **/.coverage"
rm -rf ./.ipynb_checkpoints/ **/.ipynb_checkpoints || echo "no matches found for **/.ipynb_checkpoints"
rm -rf ./.pyc/ **/*.pyc || echo "no matches found for **/*.pyc"
rm -rf ./__pycache__/ **__pycache__ || echo "no matches found for **/__pycache__"
rm -rf ./*.egg-info/ *.egg-info || echo "no matches found for **/*.egg-info"
rm cdk.context.json **/*cdk.context.json || echo "no matches found for cdk.context.json"
find . -type d -name "*.egg-info" -exec rm -rf {} +
find . -type d -name "__pycache__" -exec rm -rf {} +
find . -type d -name "htmlcov" -exec rm -rf {} +
find . -type d -name "test-reports" -exec rm -rf {} +
find . -type f -name "coverage.xml" -exec rm -rf {} +