Skip to content

Watch dependencies #980

Watch dependencies

Watch dependencies #980

# 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.