Skip to content

Commit

Permalink
Add workflow to update base images
Browse files Browse the repository at this point in the history
  • Loading branch information
mkjpryor committed Aug 16, 2023
1 parent edad1f2 commit 8b8f837
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
48 changes: 48 additions & 0 deletions .github/workflows/base_image_update.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Update base images
on:
push:
branches: [feature/automate-base-images]
# Allow manual executions
workflow_dispatch:
# Run nightly
schedule:
- cron: '0 0 * * *'

jobs:
propose_base_image_update:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
distro: [focal, jammy]
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Install script dependencies
run: pip install -r ./requirements.txt

- name: Check for base image updates
id: base-image-update
run: ./bin/base-image-update ${{ matrix.distro }}

- name: Generate app token for PR
uses: stackhpc/github-actions/generate-app-token@master
id: generate-app-token
with:
repository: ${{ github.repository }}
app-id: ${{ secrets.APP_ID }}
app-private-key: ${{ secrets.APP_PRIVATE_KEY }}

- name: Propose changes via PR if required
uses: peter-evans/create-pull-request@v5
with:
token: ${{ steps.generate-app-token.outputs.token }}
commit-message: ${{ fromJson(steps.base-image-update.outputs.pr).title }}
branch: update/kubernetes-patch
delete-branch: true
title: ${{ fromJson(steps.base-image-update.outputs.pr).title }}
body: ${{ fromJson(steps.base-image-update.outputs.pr).body }}
labels: |
automation
dependency-update
72 changes: 72 additions & 0 deletions bin/base-image-update
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python3

import argparse
import fileinput
import json
import os
import pathlib

import requests


#####
# This script updates the base images to the latest release
#####

parser = argparse.ArgumentParser(
description = "Updates an Ubuntu base image to the latest release."
)
parser.add_argument(
"distro",
choices = ["focal", "jammy"],
help = "The name of the distro to update."
)
args = parser.parse_args()


SERVER_URL = "https://cloud-images.ubuntu.com"
RELEASES_URL = f"{SERVER_URL}/releases/streams/v1/com.ubuntu.cloud:released:download.json"
PRODUCT_KEYS = {
"focal": "com.ubuntu.cloud:server:20.04:amd64",
"jammy": "com.ubuntu.cloud:server:22.04:amd64",
}

# Get the repository root
repo_root = pathlib.Path(__file__).parent.parent.resolve()

# Download the product stream
response = requests.get(RELEASES_URL)
response.raise_for_status()
products = response.json()["products"]

# Find the latest version for the distro
# The versions are of the form YYYYMMDD, so default string sorting works fine
versions = products[PRODUCT_KEYS[args.distro]]["versions"]
latest = next(iter(sorted(versions, reverse = True)))
# Get the URL for the image
# The paths in the stream are of the form "server{bit that we want}"
latest_path = versions[latest]["items"]["disk1.img"]["path"]
latest_url = f"{SERVER_URL}{latest_path.removeprefix('server')}"

# Update the link in the env file
env_file = repo_root / "env" / "base" / f"ubuntu-{args.distro}.env"
with fileinput.input(env_file, inplace = True) as fh:
for line in fh:
if line.startswith("SOURCE_IMAGE_URL="):
print(f"SOURCE_IMAGE_URL=\"{latest_url}\"")
else:
print(line, end = "")

# Output the title and body for the PR as a JSON document
pr = {
"title": f"Update ubuntu-{args.distro} base image ({latest})",
"body": (
"This PR was created automatically to update the "
f"`ubuntu-{args.distro}` base image to release `{latest}`."
),
}

# Output the new versions so they can be included in the PR
output_path = os.environ.get("GITHUB_OUTPUT", "/dev/stdout")
with open(output_path, "a") as fh:
print(f"pr={json.dumps(pr)}", file = fh)

0 comments on commit 8b8f837

Please sign in to comment.