Skip to content

Commit 16e0e8f

Browse files
committed
move dependencies to update-nbviewer.py script so it can be run locally
1 parent 51ab64d commit 16e0e8f

File tree

4 files changed

+147
-41
lines changed

4 files changed

+147
-41
lines changed

.github/workflows/watch-dependencies.yaml

Lines changed: 15 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# automatically check for updates to nbviewer
2-
# adapted from mybinder.org-deploy, under BSD-3-Clause lience
2+
# adapted from mybinder.org-deploy, under BSD-3-Clause license
33
name: Watch dependencies
44

55
on:
@@ -25,39 +25,17 @@ jobs:
2525

2626
- uses: actions/setup-python@v5
2727
with:
28-
python-version: "3.10"
28+
python-version: "3.13"
29+
cache: pip
2930

30-
- name: Get current versions of jupyter/nbviewer
31-
id: current
32-
# get the version of the image and chart repo currently being deployed
31+
- name: install requirements
3332
run: |
34-
local_image=$(cat config/nbviewer.yaml | yq e '.image')
35-
echo "tag=$local_image" >> $GITHUB_OUTPUT
36-
local_chart=$(cat .github/workflows/cd.yml | yq e '.env.NBVIEWER_VERSION')
37-
echo "chart=$local_chart" >> $GITHUB_OUTPUT
38-
39-
- name: Get latest versions jupyter/nbviewer
40-
id: latest
41-
# docker tags api sorts by date
42-
# there is no version information in nbviewer image tags
33+
pip install -r requirements.txt
34+
35+
- name: Check for nbviewer updates
36+
id: update
4337
run: |
44-
latest_tag=$(
45-
curl https://hub.docker.com/v2/repositories/jupyter/nbviewer/tags | jq -r '.results[0].name'
46-
)
47-
echo "tag=jupyter/nbviewer:$latest_tag" >> $GITHUB_OUTPUT
48-
head=$(
49-
git ls-remote https://github.com/jupyter/nbviewer HEAD | cut -f1
50-
)
51-
echo "chart=$head" >> "$GITHUB_OUTPUT"
52-
echo "short=${head::7}" >> "$GITHUB_OUTPUT"
53-
54-
- name: Update nbviewer image
55-
if: steps.local.outputs.tag != steps.latest.outputs.tag
56-
run: sed --in-place 's@${{ steps.local.outputs.tag }}@${{ steps.latest.outputs.tag }}@g' config/nbviewer.yaml
57-
58-
- name: Update nbviewer chart
59-
if: steps.local.outputs.chart != steps.latest.outputs.chart
60-
run: sed --in-place 's@${{ steps.local.outputs.chart }}@${{ steps.latest.outputs.chart }}@g' .github/workflows/cd.yml
38+
python3 scripts/update-nbviewer.py
6139
6240
- name: git diff
6341
id: git-diff
@@ -72,11 +50,10 @@ jobs:
7250
id: prsummary
7351
if: steps.git-diff.changed
7452
run: |
75-
pip install PyGithub
7653
./scripts/get-prs.py \
7754
jupyter/nbviewer \
78-
${{ steps.local.outputs.chart }} \
79-
${{ steps.latest.outputs.chart }} \
55+
${{ steps.update.outputs.chart_before }} \
56+
${{ steps.update.outputs.chart_after }} \
8057
--write-github-actions-output=prs
8158
env:
8259
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -93,11 +70,11 @@ jobs:
9370
committer: JupterHub Bot Account <[email protected]>
9471
branch: update-nbviewer
9572
labels: dependencies
96-
commit-message: Update nbviewer version to ${{ steps.latest.outputs.short }}
97-
title: Update nbviewer version to ${{ steps.latest.outputs.short }}
73+
commit-message: Update nbviewer version to ${{ steps.update.outputs.chart_short }}
74+
title: Update nbviewer version to ${{ steps.update.outputs.chart_short }}
9875
body: |
99-
- Updates nbviewer chart to jupyter/nbviewer@${{ steps.latest.outputs.chart }}
100-
- Update nbviewer image to `${{ steps.latest.outputs.tag }}`
76+
- Updates nbviewer chart to jupyter/nbviewer@${{ steps.update.outputs.chart_after }}
77+
- Update nbviewer image to `${{ steps.update.outputs.image_tag }}`
10178
10279
${{ steps.prsummary.outputs.prs }}
10380

requirements.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
beautifulsoup4
2+
pygithub
23
pytest
4+
pyyaml
35
requests

requirements.txt

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@ beautifulsoup4==4.13.5
88
# via -r requirements.in
99
certifi==2025.8.3
1010
# via requests
11+
cffi==2.0.0
12+
# via
13+
# cryptography
14+
# pynacl
1115
charset-normalizer==3.4.3
1216
# via requests
17+
cryptography==46.0.1
18+
# via pyjwt
1319
idna==3.10
1420
# via requests
1521
iniconfig==2.1.0
@@ -18,15 +24,31 @@ packaging==25.0
1824
# via pytest
1925
pluggy==1.6.0
2026
# via pytest
27+
pycparser==2.23
28+
# via cffi
29+
pygithub==2.8.1
30+
# via -r requirements.in
2131
pygments==2.19.2
2232
# via pytest
33+
pyjwt[crypto]==2.10.1
34+
# via pygithub
35+
pynacl==1.6.0
36+
# via pygithub
2337
pytest==8.4.2
2438
# via -r requirements.in
25-
requests==2.32.5
39+
pyyaml==6.0.2
2640
# via -r requirements.in
41+
requests==2.32.5
42+
# via
43+
# -r requirements.in
44+
# pygithub
2745
soupsieve==2.8
2846
# via beautifulsoup4
2947
typing-extensions==4.15.0
30-
# via beautifulsoup4
48+
# via
49+
# beautifulsoup4
50+
# pygithub
3151
urllib3==2.5.0
32-
# via requests
52+
# via
53+
# pygithub
54+
# requests

scripts/update-nbviewer.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
"""
2+
script to update nbviewer
3+
4+
run via watch-dependencies.yaml workflow,
5+
but can be run locally.
6+
7+
"""
8+
9+
import os
10+
import shlex
11+
from pathlib import Path
12+
from subprocess import check_output
13+
14+
import requests
15+
import yaml
16+
17+
nbviewer_deploy = Path(__file__).absolute().parents[1]
18+
cd_yaml = nbviewer_deploy / ".github/workflows/cd.yml"
19+
nbviewer_config_yaml = nbviewer_deploy / "config/nbviewer.yaml"
20+
21+
22+
def _maybe_output(key, value):
23+
"""Make outputs available to github actions (if running in github actions)"""
24+
github_output = os.environ.get("GITHUB_OUTPUT")
25+
line = f"{key}={shlex.quote(value)}"
26+
if github_output:
27+
with Path(github_output).open("a") as f:
28+
f.write(f"{line}\n")
29+
else:
30+
print(line)
31+
32+
33+
def get_current_chart():
34+
"""Get the current version of the chart in cd.yaml"""
35+
with cd_yaml.open() as f:
36+
cd = yaml.safe_load(f)
37+
chart_rev = cd["env"]["NBVIEWER_VERSION"]
38+
return chart_rev
39+
40+
41+
def get_latest_chart():
42+
"""Get the latest version of the chart repo"""
43+
out = check_output(
44+
["git", "ls-remote", "https://github.com/jupyter/nbviewer", "HEAD"], text=True
45+
).strip()
46+
return out.split()[0]
47+
48+
49+
def get_current_image():
50+
"""Get the current version of the nbviewer image in config"""
51+
with nbviewer_config_yaml.open() as f:
52+
config = yaml.safe_load(f)
53+
current_image = config["image"]
54+
return current_image
55+
56+
57+
def get_latest_image():
58+
"""Get the latest version of the nbviewer image from docker hub"""
59+
r = requests.get("https://hub.docker.com/v2/repositories/jupyter/nbviewer/tags")
60+
r.raise_for_status()
61+
tags = r.json()
62+
tag = tags["results"][0]["name"]
63+
return f"jupyter/nbviewer:{tag}"
64+
65+
66+
def update_chart():
67+
"""Update the version of the nbviewer chart to be deployed"""
68+
current_chart = get_current_chart()
69+
latest_chart = get_latest_chart()
70+
_maybe_output("chart_before", current_chart)
71+
_maybe_output("chart_after", latest_chart)
72+
_maybe_output("chart_short", latest_chart[:7])
73+
if latest_chart != current_chart:
74+
print(f"Updating {current_chart} -> {latest_chart} in {cd_yaml}")
75+
with cd_yaml.open() as f:
76+
current_yaml = f.read()
77+
modified_yaml = current_yaml.replace(current_chart, latest_chart, 1)
78+
with cd_yaml.open("w") as f:
79+
f.write(modified_yaml)
80+
81+
82+
def update_image():
83+
"""Update the version of the nbviewer image to be deployed"""
84+
current_image = get_current_image()
85+
latest_image = get_latest_image()
86+
_maybe_output("image_before", current_image)
87+
_maybe_output("image_after", latest_image)
88+
_maybe_output("image_tag", latest_image.partition(":")[2])
89+
90+
if latest_image != current_image:
91+
print(f"Updating {current_image} -> {latest_image} in {nbviewer_config_yaml}")
92+
with nbviewer_config_yaml.open() as f:
93+
current_yaml = f.read()
94+
modified_yaml = current_yaml.replace(current_image, latest_image, 1)
95+
with nbviewer_config_yaml.open("w") as f:
96+
f.write(modified_yaml)
97+
98+
99+
def main():
100+
update_chart()
101+
update_image()
102+
103+
104+
if __name__ == "__main__":
105+
main()

0 commit comments

Comments
 (0)