Skip to content

Commit d1125d3

Browse files
committed
try auto-update PRs from nbviewer
1 parent bbef5af commit d1125d3

File tree

2 files changed

+192
-0
lines changed

2 files changed

+192
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# automatically check for updates to nbviewer
2+
# adapted from mybinder.org-deploy, under BSD-3-Clause lience
3+
name: Watch dependencies
4+
5+
on:
6+
push:
7+
paths:
8+
- ".github/workflows/watch-dependencies.yaml"
9+
schedule:
10+
# Run daily at 5am (somewhere), ref: https://crontab.guru/#0_5_*_*_*
11+
- cron: "0 5 * * *"
12+
workflow_dispatch:
13+
14+
jobs:
15+
update-nbviewer:
16+
# Don't schedule runs on forks, but allow the job to execute on push and
17+
# workflow_dispatch for CI development purposes.
18+
if: github.repository == 'jupyter/nbviewer.org-deploy' || github.event_name != 'schedule'
19+
20+
runs-on: ubuntu-24.04
21+
environment: watch-dependencies
22+
23+
steps:
24+
- uses: actions/checkout@v4
25+
26+
- uses: actions/setup-python@v5
27+
with:
28+
python-version: "3.10"
29+
30+
- name: Get current versions of jupyter/nbviewer
31+
id: current
32+
# get the version of the image and chart repo currently being deployed
33+
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
43+
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
61+
62+
- name: git diff
63+
id: git-diff
64+
run: |
65+
if git --no-pager diff --color=always --exit-code; then
66+
echo "changed=true" >> "$GITHUB_OUTPUT"
67+
else
68+
echo "changed=false" >> "$GITHUB_OUTPUT"
69+
fi
70+
71+
- name: Fetch PR summary
72+
id: prsummary
73+
if: steps.git-diff.changed
74+
run: |
75+
pip install PyGithub
76+
./scripts/get-prs.py \
77+
jupyter/nbviewer \
78+
${{ steps.local.outputs.chart }} \
79+
${{ steps.latest.outputs.chart }} \
80+
--write-github-actions-output=prs
81+
env:
82+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
83+
84+
# ref: https://github.com/peter-evans/create-pull-request
85+
- name: Create a PR
86+
uses: peter-evans/create-pull-request@v7
87+
# Don't try open PRs in forks or when the job is triggered by a push to
88+
# a branch other than the default branch.
89+
if: github.repository == 'jupyter/nbviewer.org-deploy' && (github.event_name != 'push' || github.ref == 'refs/heads/main')
90+
with:
91+
token: "${{ secrets.BOT_PAT }}"
92+
author: Jupter Bot Account <[email protected]>
93+
committer: JupterHub Bot Account <[email protected]>
94+
branch: update-nbviewer
95+
labels: dependencies
96+
commit-message: Update nbviewer version to ${{ steps.latest.outputs.short }}
97+
title: Update nbviewer version to ${{ steps.latest.outputs.short }}
98+
body: |
99+
- Updates nbviewer chart to jupyter/nbviewer@${{ steps.latest.outputs.chart }}
100+
- Update nbviewer image to `${{ steps.latest.outputs.tag }}`
101+
102+
${{ steps.prsummary.outputs.prs }}
103+
104+
## Related
105+
106+
- Source code: https://github.com/jupyter/nbviewer

scripts/get-prs.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/usr/bin/env python
2+
3+
# Copied from jupyterhub/mybinder.org-deploy
4+
# used under BSD-3-Clause license
5+
6+
import os
7+
import re
8+
import uuid
9+
from argparse import ArgumentParser
10+
11+
import github
12+
13+
14+
def extract_gitref(s):
15+
"""
16+
Extract git ref from a container registry tag or Helm chart version
17+
18+
Examples:
19+
- 2022.02.0 -> 2022.02.0
20+
- 2022.02.0-90.g0345a86 -> 0345a86
21+
- 0.2.0 -> 0.2.0
22+
- 0.2.0-n1011.hb49edf6 -> b49edf6
23+
- 0.2.0-0.dev.git.2752.h3450e52 -> 3450e52
24+
"""
25+
m = re.match(r"[\d\.]+-[\w\.]+[gh]([0-9a-f]+)", s)
26+
if m:
27+
return m.group(1)
28+
return s
29+
30+
31+
token = os.getenv("GITHUB_TOKEN")
32+
33+
parser = ArgumentParser(description="Summarise PRs from a repo")
34+
parser.add_argument("repo", help="The repository in format user/repo")
35+
parser.add_argument("start", help="commit or image/chart version from which to start")
36+
parser.add_argument("end", help="commit or image/chart version to which to end")
37+
parser.add_argument(
38+
"--write-github-actions-output",
39+
help="Name of a GitHub Action's output variable to write to",
40+
)
41+
parser.add_argument(
42+
"--max-commits",
43+
type=int,
44+
default=100,
45+
help="Maximum number of commits to check",
46+
)
47+
48+
args = parser.parse_args()
49+
50+
gh = github.Github(token)
51+
r = gh.get_repo(args.repo)
52+
53+
start = extract_gitref(args.start)
54+
end = extract_gitref(args.end)
55+
56+
prs = set()
57+
git_compare = r.compare(start, end)
58+
commits = list(git_compare.commits)
59+
if len(commits) > args.max_commits:
60+
pr_summaries = [
61+
f"{len(commits)} commits between {start} and {end}, not searching for PRs"
62+
]
63+
else:
64+
for c in commits:
65+
if len(c.parents) == 1:
66+
# Chartpress ignores merge commits when generating the Helm chart SHA
67+
prs.update(c.get_pulls())
68+
pr_summaries = [
69+
f"- [#{pr.number}]({pr.html_url}) {pr.title} ({', '.join(label.name for label in pr.labels)})"
70+
for pr in sorted(prs, key=lambda pr: pr.number)
71+
]
72+
73+
md = ["# PRs"] + pr_summaries + ["", f"{r.html_url}/compare/{start}...{end}"]
74+
md = "\n".join(md)
75+
76+
if args.write_github_actions_output:
77+
# GitHub Actions docs on setting a output variable with a multiline string:
78+
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
79+
#
80+
eof_marker = str(uuid.uuid4()).replace("-", "_")
81+
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
82+
print(f"{args.write_github_actions_output}<<{eof_marker}", file=f)
83+
print(md, file=f)
84+
print(eof_marker, file=f)
85+
else:
86+
print(md)

0 commit comments

Comments
 (0)