-
Notifications
You must be signed in to change notification settings - Fork 7
/
fabfile.py
279 lines (228 loc) · 7.84 KB
/
fabfile.py
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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
import re
import sys
import os
from collections import namedtuple
from datetime import datetime
from fileinput import input as finput
from netrc import netrc
from os import listdir
from os.path import join
from typing import List
from fabric import task
from fabric.connection import Connection
Credentials = namedtuple('Credentials', 'username, password')
def get_package_name(conn):
"""Return package name"""
result = conn.run("env/bin/python setup.py --name")
return result.stdout.strip("\n")
def get_package_description(conn):
"""Return package description"""
result = conn.run("env/bin/python setup.py --description")
return result.stdout.strip("\n")
def get_version(conn):
"""Returns version of the package"""
version_output = conn.run("./env/bin/python setup.py --version")
return version_output.stdout.strip("\n")
def get_surrounding_years():
"""
Gets the surrounding years -1 from current year and +1 from current year
"""
year = datetime.now().year
return [year - 1, year, year + 1]
def get_credentials(sitename: str) -> Credentials:
"""Retrieves username and password from .netrc file"""
netrc_instance = netrc()
result = netrc_instance.authenticators(sitename)
if not result:
raise Exception("Please add your credentials to "
"your ~/.netrc file for site %s" % sitename)
return Credentials(result[0], result[2])
def get_docker_tags(package_name: str, version: str) -> List[str]:
"""
Prepare docker tags to put on images
"""
targets = [
"flazzarini/%s:latest" % package_name,
"flazzarini/%s:%s" % (package_name, version),
]
targets.extend(
[
"registry.gefoo.org/%s" % (_) for _ in targets
]
)
return targets
def verify_pip_config(conn, executed_in_ci=False):
"""
Verifies if your pip configuration contains `pypi.gefoo.org` and sets
credentials if executed in CI
"""
# Skip this check when executed in CI, we are probably relying on
# Environment Variables
if executed_in_ci:
twine_env_vars = [
'TWINE_USERNAME',
'TWINE_PASSWORD',
'TWINE_REPOSITORY',
]
for twine_env_var in twine_env_vars:
if not os.environ.get(twine_env_var):
print("Make sure you have %r set" % (twine_env_var))
return
result = conn.run("cat ~/.pypirc | grep -e \"^\[pypi.gefoo.org\]$\"")
if result.exited != 0:
raise Exception(
"pypi.gefoo.org repository is not configured in your ~/.pypirc")
return
@task
def build(conn):
"""Builds python package"""
conn.run("./env/bin/python setup.py clean")
conn.run("./env/bin/python setup.py bdist bdist_wheel")
@task
def develop(conn):
"""Creates development environment"""
conn.run("[ -d env ] || python3 -m venv env", replace_env=False)
conn.run("env/bin/pip install -U pip setuptools", replace_env=False)
conn.run("env/bin/pip install wheel", replace_env=False)
conn.run("env/bin/pip install -e .[test,dev]", replace_env=False)
@task
def publish(conn):
"""Publish to pyrepo"""
verify_pip_config(conn)
conn.run("./env/bin/python setup.py clean")
conn.run("./env/bin/python setup.py bdist bdist_wheel")
filename = conn.run(
"./env/bin/python setup.py --fullname").stdout.strip("\n")
dist_file = "dist/%s-py3-none-any.whl" % (filename)
conn.run("./env/bin/twine upload -r pypi.gefoo.org %s" % dist_file)
@task
def doc(conn):
"""Builds doc"""
conn.run("rm -Rf doc/_build/*")
conn.run("rm -Rf doc/api-doc/*.rst")
conn.run("find doc/ -name '*.rst' -exec touch {} \;")
conn.run(
"./env/bin/python ci/scripts/gen_api_doc.py --dest doc/api-doc",
pty=True)
for year in get_surrounding_years():
conn.run(
"""\
./env/bin/python ci/scripts/gen_weeknr_map_doc.py \
--dest doc/weektables-doc/weektable_{year}.rst \
--year {year}
""".format(year=year))
conn.run("./env/bin/sphinx-build --color -aE doc doc/_build", pty=True)
@task
def publish_doc(conn, username=None, password=None, branch='develop'):
"""Publishes doc to https://docs.gefoo.org"""
if not username or not password:
credentials = get_credentials("docs.gefoo.org")
else:
credentials = Credentials(username, password)
doc(conn)
conn.run("cd doc/_build && zip -r doc.zip *")
package = get_package_name(conn)
description = get_package_description(conn)
print("Got branch %s" % branch)
if branch and branch != "master":
version = 'develop'
else:
version = get_version(conn)
conn.run(
"""\
cd doc/_build && \
curl -X POST \
--user {username}:{password} \
-F [email protected] \
-F name="{package}" \
-F version="{version}" \
-F description="{description}" \
https://docs.gefoo.org/hmfd
""".format(username=credentials.username,
password=credentials.password,
package=package,
version=version,
description=description))
@task
def test(conn):
"""Run tests"""
conn.run("[ -d .pytest_cache ] && rm -Rf .pytest_cache")
conn.run(
"env/bin/pytest-watch %s/ tests/ -- --lf -vv --color yes" % (
get_package_name(conn)
)
)
@task
def test_cov(conn):
"""Run tests with coverage checks"""
conn.run(
"env/bin/py.test --cov=%s --cov-report=term" % get_package_name(conn))
@task
def test_covhtml(conn):
"""Run tests with coverage checks as html report"""
conn.run(
"env/bin/py.test --cov=%s --cov-report=html" % get_package_name(conn))
@task
def build_docker(conn, do_python_build=True):
"""Builds docker image"""
if do_python_build:
build(conn)
package_name = get_package_name(conn)
version = get_version(conn)
targets = get_docker_tags(package_name, version)
for target in targets:
conn.run(
"docker build "
"--build-arg VERSION=%s "
"-t %s -f Dockerfile-Blocklister ." % (
version,
target,
)
)
# Separate build process for blocklister-updater
package_name = "blocklister-updater"
version = get_version(conn)
targets = get_docker_tags(package_name, version)
for target in targets:
conn.run(
"docker build "
"--build-arg VERSION=%s "
"-t %s -f Dockerfile-Updater ." % (
version,
target,
)
)
@task
def build_and_upload_docker(conn):
"""Builds all docker test images and uploads them"""
build_docker(conn)
package_name = get_package_name(conn)
version = get_version(conn)
targets = get_docker_tags(package_name, version)
for target in targets:
if "registry.gefoo.org" in target:
conn.run("docker push %s" % target)
# Separate build process for blocklister-updater
package_name = "blocklister-updater"
version = get_version(conn)
targets = get_docker_tags(package_name, version)
for target in targets:
if "registry.gefoo.org" in target:
conn.run("docker push %s" % target)
@task
def build_changelog(conn, filename="CHANGELOG.md"):
"""Parses the CHANGELOG.md and adds a link for each issue id"""
issue_links = get_changelog_links(filename=filename)
clean_changelog_links(filename=filename)
append_changelog_links(filename=filename, links_entries=issue_links)
@task
def run(conn):
"""Run application with gunicorn"""
package_name = get_package_name(conn)
conn.run(
"""
./env/bin/gunicorn -b 0.0.0.0 %s.main:app --reload
""" % package_name,
pty=True,
replace_env=False
)