Skip to content

Commit f4c360d

Browse files
committed
add basic pre-commit �config
1 parent b4ca353 commit f4c360d

File tree

9 files changed

+105
-88
lines changed

9 files changed

+105
-88
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,4 @@ coverage.xml
5353
docs/_build/
5454

5555
.ipynb_checkpoints
56-
.DS_Store
56+
.DS_Store

.pre-commit-config.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
exclude: "(.*/)?secrets/.*"
2+
3+
ci:
4+
# pre-commit.ci will open PRs updating our hooks once a month
5+
autoupdate_schedule: monthly
6+
7+
repos:
8+
# autoformat and lint Python code
9+
- repo: https://github.com/astral-sh/ruff-pre-commit
10+
rev: v0.13.1
11+
hooks:
12+
- id: ruff
13+
types_or:
14+
- python
15+
args: ["--fix", "--show-fixes"]
16+
- id: ruff-format
17+
types_or:
18+
- python
19+
20+
# Autoformat: markdown, yaml, javascript (see the file .prettierignore)
21+
- repo: https://github.com/rbubley/mirrors-prettier
22+
rev: v3.6.2
23+
hooks:
24+
- id: prettier
25+
26+
# Autoformat and linting, misc. details
27+
- repo: https://github.com/pre-commit/pre-commit-hooks
28+
rev: v6.0.0
29+
hooks:
30+
- id: end-of-file-fixer
31+
- id: check-executables-have-shebangs

LICENSE

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,3 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2121
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2222
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2323
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24-

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ Python dependencies:
2727

2828
pip install -r requirements.txt
2929

30-
3130
### Upgrading
3231

3332
To upgrade the deployment in-place:

config/nbviewer.yaml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ memcached:
1515

1616
nbviewer:
1717
extraArgs:
18-
- '--cache-expiry-min=3600'
19-
- '--cache-expiry-max=14400'
20-
- "--content-security-policy=connect-src *" # https://github.com/jupyter/nbviewer/issues/797
21-
- '--jupyter-js-widgets-version=2.1' # https://github.com/jupyter/nbviewer/issues/818
22-
- '--jupyter-widgets-html-manager-version=0.15' # https://github.com/jupyter/nbviewer/issues/818
23-
- >-
24-
--NBViewer.extra_head_html=
25-
<script defer data-domain="nbviewer.org" src="https://plausible.io/js/script.file-downloads.outbound-links.js"></script>
26-
<script>window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>
18+
- "--cache-expiry-min=3600"
19+
- "--cache-expiry-max=14400"
20+
- "--content-security-policy=connect-src *" # https://github.com/jupyter/nbviewer/issues/797
21+
- "--jupyter-js-widgets-version=2.1" # https://github.com/jupyter/nbviewer/issues/818
22+
- "--jupyter-widgets-html-manager-version=0.15" # https://github.com/jupyter/nbviewer/issues/818
23+
- >-
24+
--NBViewer.extra_head_html=
25+
<script defer data-domain="nbviewer.org" src="https://plausible.io/js/script.file-downloads.outbound-links.js"></script>
26+
<script>window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>
2727
2828
statuspage:
2929
enabled: true

pyproject.toml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,12 @@ name = "nbviewer.org-deploy"
66
addopts = "-v"
77
testpaths = [
88
"tests",
9-
]
9+
]
10+
11+
[tool.ruff.lint]
12+
select = [
13+
"E9", # syntax
14+
"I", # isort
15+
"UP", # pyupgrade
16+
"F", # flake8
17+
]

statuspage/statuspage.py

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,62 @@
11
#!/usr/bin/env python3
22

3-
from datetime import datetime
43
import json
54
import os
65
import sys
76
import time
7+
from datetime import datetime
88

99
import requests
10-
11-
api_key = os.environ['STATUSPAGE_API_KEY']
12-
page_id = os.environ['STATUSPAGE_PAGE_ID']
13-
metric_id = os.environ['STATUSPAGE_METRIC_ID']
14-
api_base = 'api.statuspage.io'
1510

16-
github_id = os.environ['GITHUB_OAUTH_KEY']
17-
github_secret = os.environ['GITHUB_OAUTH_SECRET']
11+
api_key = os.environ["STATUSPAGE_API_KEY"]
12+
page_id = os.environ["STATUSPAGE_PAGE_ID"]
13+
metric_id = os.environ["STATUSPAGE_METRIC_ID"]
14+
api_base = "api.statuspage.io"
15+
16+
github_id = os.environ["GITHUB_OAUTH_KEY"]
17+
github_secret = os.environ["GITHUB_OAUTH_SECRET"]
1818

1919

2020
def get_rate_limit():
2121
"""Retrieve the current GitHub rate limit for our auth tokens"""
2222
r = requests.get(
23-
'https://api.github.com/rate_limit',
24-
auth=(github_id, github_secret)
23+
"https://api.github.com/rate_limit", auth=(github_id, github_secret)
2524
)
2625
r.raise_for_status()
2726
resp = r.json()
28-
return resp['resources']['core']
27+
return resp["resources"]["core"]
2928

3029

3130
def post_data(limit, remaining, **ignore):
3231
"""Send the percent-remaining GitHub rate limit to statuspage"""
3332
percent = 100 * remaining / limit
3433
now = int(datetime.utcnow().timestamp())
35-
url = "https://api.statuspage.io/v1/pages/{page_id}/metrics/{metric_id}/data.json".format(
36-
page_id=page_id, metric_id=metric_id,
37-
)
38-
39-
r = requests.post(url,
34+
url = f"https://api.statuspage.io/v1/pages/{page_id}/metrics/{metric_id}/data.json"
35+
36+
r = requests.post(
37+
url,
4038
headers={
4139
"Content-Type": "application/x-www-form-urlencoded",
4240
"Authorization": "OAuth " + api_key,
4341
},
4442
data={
45-
'data[timestamp]': now,
46-
'data[value]': percent,
47-
}
43+
"data[timestamp]": now,
44+
"data[value]": percent,
45+
},
4846
)
4947
r.raise_for_status()
5048

5149

5250
def get_and_post():
5351
data = get_rate_limit()
5452
print(json.dumps(data))
55-
post_data(limit=data['limit'], remaining=data['remaining'])
53+
post_data(limit=data["limit"], remaining=data["remaining"])
5654

5755

5856
while True:
5957
try:
6058
get_and_post()
6159
except Exception as e:
62-
print("Error: %s" % e, file=sys.stderr)
60+
print(f"Error: {e}", file=sys.stderr)
6361
# post every two minutes
6462
time.sleep(120)

tasks.py

Lines changed: 36 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,21 @@
11
#!/usr/bin/env python3
2-
# -*- coding: utf-8 -*-
32
"""
43
Deploys nbviewer on helm
54
65
"""
76

8-
from __future__ import print_function
9-
10-
from functools import lru_cache
11-
import json
12-
import os
13-
import pipes
14-
import re
15-
import socket
16-
import sys
17-
import time
18-
19-
join = os.path.join
20-
21-
from invoke import run, task
227
import requests
23-
8+
from invoke import task
249

2510
creds = {}
26-
with open('creds') as f:
11+
with open("creds") as f:
2712
exec(f.read(), creds)
2813

2914

3015
@task
3116
def trigger_build(ctx):
3217
url_base = "https://hub.docker.com/api/build/v1/source/579ab043-912f-425b-8b3f-765ee6143b53/trigger/{}/call/"
33-
r = requests.post(url=url_base.format(creds['DOCKER_TRIGGER_TOKEN']))
18+
r = requests.post(url=url_base.format(creds["DOCKER_TRIGGER_TOKEN"]))
3419
r.raise_for_status()
3520
print(r.text)
3621

@@ -45,42 +30,40 @@ def doitall(ctx):
4530
2. upgrade on all machines
4631
"""
4732
# make sure current repo is up to date
48-
ctx.run('git pull', echo=True)
33+
ctx.run("git pull", echo=True)
4934
upgrade(ctx)
5035
fastly(ctx)
5136

5237

5338
@task
5439
def upgrade(ctx, yes=False):
55-
"""Update helm deployment
56-
57-
"""
40+
"""Update helm deployment"""
5841
raise NotImplementedError("Not implemented yet for helm")
5942

6043

6144
# ------- Fastly commands for updating the CDN --------
6245

63-
FASTLY_API = 'https://api.fastly.com'
46+
FASTLY_API = "https://api.fastly.com"
6447

6548

6649
class FastlyService:
6750
def __init__(self, api_key, service_id):
6851
self.session = requests.Session()
69-
self.session.headers['Fastly-Key'] = api_key
52+
self.session.headers["Fastly-Key"] = api_key
7053
self.service_id = service_id
7154
latest_version = self.versions()[-1]
72-
self.version = latest_version['number']
73-
if latest_version['active']:
55+
self.version = latest_version["number"]
56+
if latest_version["active"]:
7457
# don't have an inactive version yet
75-
self.api_request('/clone', method='PUT')
58+
self.api_request("/clone", method="PUT")
7659
latest_version = self.versions()[-1]
77-
self.version = latest_version['number']
60+
self.version = latest_version["number"]
7861

79-
def api_request(self, path, include_version=True, method='GET', **kwargs):
62+
def api_request(self, path, include_version=True, method="GET", **kwargs):
8063
url = "{api}/service/{service_id}{v}{path}".format(
8164
api=FASTLY_API,
8265
service_id=self.service_id,
83-
v='/version/%i' % self.version if include_version else '',
66+
v=f"/version/{self.version}" if include_version else "",
8467
path=path,
8568
)
8669
r = self.session.request(method, url, **kwargs)
@@ -92,78 +75,78 @@ def api_request(self, path, include_version=True, method='GET', **kwargs):
9275
return r.json()
9376

9477
def backends(self):
95-
return self.api_request('/backend')
78+
return self.api_request("/backend")
9679

9780
def versions(self):
98-
return self.api_request('/version', include_version=False)
81+
return self.api_request("/version", include_version=False)
9982

10083
def add_backend(self, name, hostname, port, copy_backend=None):
10184
if copy_backend is None:
10285
copy_backend = self.backends()[0]
10386
data = {
10487
key: copy_backend[key]
10588
for key in [
106-
'healthcheck',
107-
'max_conn',
108-
'weight',
109-
'error_threshold',
110-
'connect_timeout',
111-
'between_bytes_timeout',
112-
'first_byte_timeout',
113-
'auto_loadbalance',
89+
"healthcheck",
90+
"max_conn",
91+
"weight",
92+
"error_threshold",
93+
"connect_timeout",
94+
"between_bytes_timeout",
95+
"first_byte_timeout",
96+
"auto_loadbalance",
11497
]
11598
}
116-
data.update({'address': hostname, 'name': name, 'port': port})
117-
self.api_request('/backend', method='POST', data=data)
99+
data.update({"address": hostname, "name": name, "port": port})
100+
self.api_request("/backend", method="POST", data=data)
118101

119102
def remove_backend(self, name):
120-
self.api_request('/backend/%s' % name, method='DELETE')
103+
self.api_request(f"/backend/{name}", method="DELETE")
121104

122105
def deploy(self):
123106
# activate the current version
124-
self.api_request('/activate', method='PUT')
107+
self.api_request("/activate", method="PUT")
125108
# clone to a new version
126-
self.api_request('/clone', method='PUT')
127-
self.version = self.versions()[-1]['number']
109+
self.api_request("/clone", method="PUT")
110+
self.version = self.versions()[-1]["number"]
128111

129112

130113
def all_instances():
131114
"""Return {(ip, port) : name} for all running nbviewer containers on all machines"""
132115
all_nbviewers = {}
133116
# add ovh by hand
134117
# TODO: get service from kubernetes
135-
all_nbviewers[('135.125.83.237', 80)] = 'ovh'
118+
all_nbviewers[("135.125.83.237", 80)] = "ovh"
136119
return all_nbviewers
137120

138121

139122
@task
140123
def fastly(ctx):
141124
"""Update the fastly CDN"""
142125
print("Checking fastly backends")
143-
f = FastlyService(creds['FASTLY_KEY'], creds['FASTLY_SERVICE_ID'])
126+
f = FastlyService(creds["FASTLY_KEY"], creds["FASTLY_SERVICE_ID"])
144127
changed = False
145128
backends = f.backends()
146129
nbviewers = all_instances()
147130
existing_backends = set()
148131
# first, delete the backends we don't want
149132
copy_backend = backends[0]
150133
for backend in backends:
151-
host = (backend['address'], backend['port'])
134+
host = (backend["address"], backend["port"])
152135
if host not in nbviewers:
153-
print("Deleting backend %s" % backend['name'])
154-
f.remove_backend(backend['name'])
136+
print(f"Deleting backend {backend['name']}")
137+
f.remove_backend(backend["name"])
155138
changed = True
156139
else:
157140
existing_backends.add(host)
158141
for host, name in nbviewers.items():
159142
if host not in existing_backends:
160143
ip, port = host
161-
print("Adding backend %s %s:%i" % (name, ip, port))
144+
print(f"Adding backend {name} {ip}:{port}")
162145
f.add_backend(name, ip, port, copy_backend)
163146
changed = True
164147

165148
if changed:
166-
print("Activating fastly configuration %s" % f.version)
149+
print(f"Activating fastly configuration {f.version}")
167150
f.deploy()
168151
else:
169152
print("Fastly OK")

tests/test_nbviewer.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import requests
33
from bs4 import BeautifulSoup
44

5-
65
NBVIEWER = "https://nbviewer.org"
76

87
frontpage_request = requests.get(NBVIEWER)

0 commit comments

Comments
 (0)