Watch dependencies #982
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is a GitHub workflow defining a set of jobs with a set of steps. | |
# ref: https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions | |
# | |
# - Watch multiple images tags referenced in values.yaml to match the latest | |
# image tag. | |
# | |
# - Watch the jupyterhub pinning in images/*/requirements.in to match the | |
# latest jupyterhub version available on PyPI, and if doing this, also | |
# refreeze images/*/requirements.txt. | |
# | |
# About environment: watch-dependencies | |
# | |
# To reduce the exposure of the secrets.jupyterhub_bot_pat token that was setup | |
# for the environment watch-dependencies, we have setup a dedicated environment | |
# according to steps in | |
# https://github.com/jupyterhub/team-compass/issues/516#issuecomment-1129961954. | |
# | |
name: Watch dependencies | |
on: | |
push: | |
paths: | |
- "images/*/requirements.in" | |
- ".github/workflows/watch-dependencies.yaml" | |
branches: ["main"] | |
schedule: | |
# Run at 05:00 every day, ref: https://crontab.guru/#0_5_*_*_* | |
- cron: "0 5 * * *" | |
workflow_dispatch: | |
jobs: | |
update-image-dependencies: | |
# Don't run this job on forks | |
if: github.repository == 'jupyterhub/zero-to-jupyterhub-k8s' | |
runs-on: ubuntu-22.04 | |
environment: watch-dependencies | |
strategy: | |
fail-fast: false | |
matrix: | |
include: | |
- name: chp | |
registry: registry.hub.docker.com | |
repository: jupyterhub/configurable-http-proxy | |
values_path: proxy.chp.image.tag | |
version_startswith: "" | |
version_patch_regexp_group_suffix: "" | |
# traefik made us need to introduce version_patch_regexp_group_suffix | |
# to control if we accept omitting the patch version. The traefik | |
# image provides tags like 2.7 even though 2.7.0 hasn't been released, | |
# which makes bumping to it something we don't want to do. We still | |
# need to accept major.minor formatted tags though as the pause image | |
# has them. | |
# | |
- name: traefik | |
registry: registry.hub.docker.com | |
repository: library/traefik | |
values_path: proxy.traefik.image.tag | |
version_startswith: "" | |
version_patch_regexp_group_suffix: "" | |
# kube-scheduler should be pinned to its minor version as bumping it | |
# will require manual interventions sometimes, see the notes in | |
# values.yaml about bumping its version. | |
# | |
- name: kube-scheduler | |
registry: registry.k8s.io | |
repository: kube-scheduler | |
values_path: scheduling.userScheduler.image.tag | |
version_startswith: "v1.28" | |
version_patch_regexp_group_suffix: "" | |
- name: pause | |
registry: registry.k8s.io | |
repository: pause | |
values_path: scheduling.userPlaceholder.image.tag | |
version_startswith: "" | |
version_patch_regexp_group_suffix: "?" | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Get values.yaml pinned tag of ${{ matrix.registry }}/${{ matrix.repository }} | |
id: local | |
run: | | |
local_tag=$(cat jupyterhub/values.yaml | yq e '.${{ matrix.values_path }}' -) | |
echo "tag=$local_tag" >> $GITHUB_OUTPUT | |
- name: Get latest tag of ${{ matrix.registry }}/${{ matrix.repository }} | |
id: latest | |
# The skopeo image helps us list tags consistently from different docker | |
# registries. We use jq to filter out tags of the x.y or x.y.z format | |
# with the optional v prefix or version_startswith filter, and then sort | |
# based on the numerical x, y, and z values. Finally, we pick the last | |
# value in the list. | |
# | |
run: | | |
latest_tag=$( | |
docker run --rm quay.io/skopeo/stable list-tags docker://${{ matrix.registry }}/${{ matrix.repository }} \ | |
| jq -r '[.Tags[] | select(. | match("^v?\\d+\\.\\d+(\\.\\d+)${{ matrix.version_patch_regexp_group_suffix }}$") | .string | startswith("${{ matrix.version_startswith }}"))] | sort_by(split(".") | map(tonumber? // (.[1:] | tonumber))) | last' | |
) | |
echo "tag=$latest_tag" >> $GITHUB_OUTPUT | |
- name: Update values.yaml pinned tag | |
if: steps.local.outputs.tag != steps.latest.outputs.tag | |
run: | | |
sed --in-place 's/tag: "${{ steps.local.outputs.tag }}"/tag: "${{ steps.latest.outputs.tag }}"/g' jupyterhub/values.yaml | |
- name: git diff | |
if: steps.local.outputs.tag != steps.latest.outputs.tag | |
run: git --no-pager diff --color=always | |
# ref: https://github.com/peter-evans/create-pull-request | |
- name: Create a PR | |
if: steps.local.outputs.tag != steps.latest.outputs.tag | |
uses: peter-evans/create-pull-request@v6 | |
with: | |
token: "${{ secrets.jupyterhub_bot_pat }}" | |
author: JupterHub Bot Account <[email protected]> | |
committer: JupterHub Bot Account <[email protected]> | |
branch: update-image-${{ matrix.name }} | |
labels: maintenance,dependencies | |
commit-message: Update ${{ matrix.repository }} version from ${{ steps.local.outputs.tag }} to ${{ steps.latest.outputs.tag }} | |
title: Update ${{ matrix.repository }} version from ${{ steps.local.outputs.tag }} to ${{ steps.latest.outputs.tag }} | |
body: >- | |
A new ${{ matrix.repository }} image version has been detected, version | |
`${{ steps.latest.outputs.tag }}`. | |
update-jupyterhub-dependencies: | |
# Don't run this job on forks | |
if: github.repository == 'jupyterhub/zero-to-jupyterhub-k8s' | |
runs-on: ubuntu-20.04 | |
environment: watch-dependencies | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: actions/setup-python@v5 | |
with: | |
python-version: "3.11" | |
- name: Install Python dependencies | |
run: pip install packaging requests | |
- name: Get images/hub/requirements.in pinned version of jupyterhub | |
id: local | |
run: | | |
local_version=$(cat images/hub/requirements.in | grep 'jupyterhub==' | sed 's/jupyterhub==//') | |
echo "version=$local_version" >> $GITHUB_OUTPUT | |
- name: Get latest version of jupyterhub | |
id: latest | |
shell: python | |
run: | | |
import os | |
import packaging.version | |
import requests | |
request = requests.get("https://pypi.org/pypi/jupyterhub/json") | |
data = request.json() | |
releases = data["releases"] | |
latest_version = sorted(releases.keys(), key=packaging.version.Version)[-1] | |
with open(os.environ["GITHUB_OUTPUT"], "a") as f: | |
f.write(f"version={latest_version}\n") | |
- name: Update pinned version of jupyterhub | |
if: steps.local.outputs.version != steps.latest.outputs.version | |
run: | | |
for img in hub singleuser-sample; do | |
sed --in-place 's/jupyterhub==${{ steps.local.outputs.version }}/jupyterhub==${{ steps.latest.outputs.version }}/g' images/$img/requirements.in | |
done | |
sed --in-place 's/appVersion: "${{ steps.local.outputs.version }}"/appVersion: "${{ steps.latest.outputs.version }}"/g' jupyterhub/Chart.yaml | |
- name: Refreeze images/*/requirements.txt based on images/*/requirements.in | |
if: steps.local.outputs.version != steps.latest.outputs.version | |
run: ci/refreeze | |
- name: git diff | |
if: steps.local.outputs.version != steps.latest.outputs.version | |
run: git --no-pager diff --color=always | |
# ref: https://github.com/peter-evans/create-pull-request | |
- name: Create a PR | |
if: steps.local.outputs.version != steps.latest.outputs.version | |
uses: peter-evans/create-pull-request@v6 | |
with: | |
token: "${{ secrets.jupyterhub_bot_pat }}" | |
author: JupterHub Bot Account <[email protected]> | |
committer: JupterHub Bot Account <[email protected]> | |
branch: update-jupyterhub | |
labels: maintenance,dependencies | |
commit-message: Update jupyterhub from ${{ steps.local.outputs.version }} to ${{ steps.latest.outputs.version }} | |
title: Update jupyterhub from ${{ steps.local.outputs.version }} to ${{ steps.latest.outputs.version }} | |
body: >- | |
A new jupyterhub version has been detected, version | |
`${{ steps.latest.outputs.version }}`. | |
refreeze-dockerfile-requirements-txt: | |
# Don't run this job on forks, but also not on the daily schedule to reduce | |
# noise. If we could run this weekly that would be reasonable, but updating | |
# these dependencies every day is too much noise. | |
# | |
if: github.repository == 'jupyterhub/zero-to-jupyterhub-k8s' && github.event_name != 'schedule' | |
runs-on: ubuntu-22.04 | |
environment: watch-dependencies | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Refreeze images/*/requirements.txt based on images/*/requirements.in | |
run: ci/refreeze | |
- name: git diff | |
run: git --no-pager diff --color=always | |
# ref: https://github.com/peter-evans/create-pull-request | |
- name: Create a PR | |
uses: peter-evans/create-pull-request@v6 | |
with: | |
token: "${{ secrets.jupyterhub_bot_pat }}" | |
author: JupyterHub Bot Account <[email protected]> | |
committer: JupyterHub Bot Account <[email protected]> | |
branch: update-image-requirements | |
labels: dependencies | |
commit-message: "hub image: refreeze requirements.txt" | |
title: "hub image: refreeze requirements.txt" | |
body: >- | |
The hub image's requirements.txt has been refrozen based on | |
requirements.in. |