Skip to content

Commit

Permalink
Make rebuilding the app images smarter
Browse files Browse the repository at this point in the history
  • Loading branch information
gerrod3 committed Nov 20, 2024
1 parent 03ce792 commit 4062938
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 3 deletions.
74 changes: 74 additions & 0 deletions .ci/scripts/check_for_updates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import argparse
import requests
from urllib.parse import urljoin
from packaging.version import parse
from packaging.requirements import Requirement

PACKAGES = [
"pulp-ansible",
"pulp-container",
"pulp-deb",
"pulp-gem",
"pulp-maven",
"pulp-python",
"pulp-rpm",
"pulp-ostree"
]

INDEX = "https://pypi.org"

def check_update(branch, current_versions):
"""
Go through each of the image's main Pulp components and see if there is a new version available.
"""
new_versions = {}
# Get the latest Z (or Y) pulpcore release for this branch
core_pypi_response = requests.get(urljoin(INDEX, "pypi/pulpcore/json"))
assert core_pypi_response.status_code == 200
core_version = parse(current_versions["pulpcore"])
for version, release in core_pypi_response.json()["releases"].items():
cur_version = parse(version)
if cur_version > core_version:
if branch != "latest":
if cur_version.major != core_version.major or cur_version.minor != core_version.minor:
continue
core_version = cur_version
new_versions["pulpcore"] = core_version

# Now check each plugin to see if they need updates
for plugin in PACKAGES:
if plugin not in current_versions:
continue
plugin_version = parse(current_versions[plugin])
plugin_pypi_response = requests.get(urljoin(INDEX, f"pypi/{plugin}/json"))
assert plugin_pypi_response.status_code == 200
plugin_versions = sorted((parse(v) for v in plugin_pypi_response.json()["releases"].keys()), reverse=True)
for version in plugin_versions:
if version <= plugin_version:
break
version_pypi_response = requests.get(urljoin(INDEX, f"pypi/{plugin}/{version}/json"))
assert version_pypi_response.status_code == 200
deps = version_pypi_response.json()["info"]["requires_dist"]
core_dep = next(filter(lambda dep: dep.startswith("pulpcore"), deps))
if core_version in Requirement(core_dep).specifier:
new_versions[plugin] = version
break

if new_versions:
print("Updates needed for:")
for plugin, version in new_versions.items():
print(f"{plugin}: {current_versions[plugin]} -> {version!s}")
exit(100)

print("No updates needed :)")

if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("branch")
parser.add_argument("versions", type=argparse.FileType("r"))
opts = parser.parse_args()
versions = {}
for line in opts.versions:
plugin, _, version = line.rstrip("\n").partition("==")
versions[plugin] = version
check_update(opts.branch, versions)
3 changes: 3 additions & 0 deletions .github/actions/base_images/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ outputs:
base_cache_key:
value: ${{ steps.hash_key.outputs.base_cache_key }}
description: "The cache key the built images were uploaded to."
rebuilt_images:
value: ${{ env.BUILD_IMAGES }}
description: "The images that were rebuilt or empty"

runs:
using: "composite"
Expand Down
59 changes: 57 additions & 2 deletions .github/actions/build_image/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ inputs:
description: 'Use the latest pulp-ui when building the image'
default: 'false'
required: false
built_base_images:
description: 'A JSON list of the base-images that were freshly rebuilt prior'
required: true
outputs:
app_version:
value: ${{ steps.image_version_branch.outputs.app_version }}
description: 'The full version of the app in the built image'
app_branch:
value: ${{ steps.image_version_branch.outputs.app_branch }}
description: 'The pulpcore version branch that the built image matches'
rebuilt_images:
value: ${{ env.BUILD }}
description: 'true/false if the app image was rebuilt'

runs:
using: "composite"
Expand All @@ -39,7 +45,7 @@ runs:
shell: bash

- name: Restore podman images from cache
uses: actions/cache/restore@v3
uses: actions/cache/restore@v4
with:
key: base-images=${{ inputs.image_cache_key }}
path: base-images.tar.gz
Expand All @@ -62,7 +68,41 @@ runs:
fi
shell: bash

- name: Set hash key
run: echo "VERSIONKEY=versions-${{ github.ref_name }}=${{ hashFiles(format('images/{}/stable/**', inputs.image_name)) }}" >> $GITHUB_ENV
shell: bash

- name: Restore last builds versions from cache
id: cache
uses: actions/cache/restore@v4
with:
key: ${{ env.VERSIONKEY }}
path: versions.freeze

- name: Check if rebuild is needed
run: |
# Rebuilds are needed for
# 1. CI is being ran in a PR or is a nightly run
# 2. Base images were rebuilt
# 3. New pulp versions was released
if [[ "${{ github.event_name }}" == "pull_request" || "${{ inputs.image_variant }}" == "nightly" || -n "${{ inputs.build_base_images }}" ]]; then
echo "BUILD=true" >> $GITHUB_ENV
else
if [[ "${{ steps.cache.outputs.cache-hit }}" == "false" ]]; then
echo "BUILD=true" >> $GITHUB_ENV
else
if python .ci/scripts/check_for_updates.py ${{ github.ref_name }} versions.freeze; then
echo "BUILD=false" >> $GITHUB_ENV
else
echo "BUILD=true" >> $GITHUB_ENV
fi
fi
fi
echo "Going to rebuild: ${BUILD}"
shell: bash

- name: Build images
if: env.BUILD == 'true'
run: |
podman version
buildah version
Expand All @@ -84,11 +124,26 @@ runs:
id: image_version_branch
run: |
base_image=$(echo ${{ inputs.image_name }} | cut -d '-' -f1)
app_version=$(podman run --pull=never pulp/${{ inputs.image_name }}:ci-amd64 bash -c "pip3 show pulpcore | sed -n -e 's/Version: //p'")
podman run --pull=never pulp/${{ inputs.image_name }}:ci-amd64 bash -c "pip3 freeze | grep pulp" >> versions.freeze
app_version=$(grep pulpcore versions.freeze | sed -n -e 's/pulpcore==//p')
app_branch=$(echo ${app_version} | grep -oP '\d+\.\d+')
echo "APP_VERSION: ${app_version}"
echo "APP_BRANCH: ${app_branch}"
echo "app_version=${app_version}" >> "$GITHUB_OUTPUT"
echo "app_branch=${app_branch}" >> "$GITHUB_OUTPUT"
shell: bash

- name: Clear cache for next upload
if: env.BUILD == 'true' && steps.cache.outputs.cache-hit == 'true' && github.event_name != 'pull_request'
run: |
echo "Deleting existing cache for ${{ env.VERSIONKEY }}"
gh cache delete "base-images=${{ env.VERSIONKEY }}" -R ${{ github.repository }}
shell: bash

- name: Cache versions
if: env.BUILD == 'true' && github.event_name != 'pull_request'
uses: actions/cache/save@v4
with:
key: ${{ env.VERSIONKEY }}
path: versions.freeze
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ jobs:
image_variant: "stable"
image_cache_key: ${{ needs.base-images.outputs.base_cache_key }}
latest_ui: ${{ github.base_ref == 'latest' }}
built_base_images: ${{ needs.base-images.outputs.rebuilt_images }}

- name: Test App Image
uses: "./.github/actions/test_image"
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,18 @@ jobs:
image_variant: ${{ matrix.image_variant }}
image_cache_key: ${{ needs.base-images.outputs.base_cache_key }}
latest_ui: ${{ github.ref_name == 'latest' }}
built_base_images: ${{ needs.base-images.outputs.rebuilt_images }}


- name: Test App Image
if: matrix.image_variant != 'nightly'
if: ${{ matrix.image_variant != 'nightly' && steps.build_image.outputs.rebuilt_images == 'true' }}
uses: "./.github/actions/test_image"
with:
image_name: ${{ matrix.image_name }}
app_branch: ${{ steps.build_image.outputs.app_branch }}

- name: Set tags
if: ${{ steps.build_image.outputs.rebuilt_images == 'true' }}
run: |
base_image=$(echo ${{ matrix.image_name }} | cut -d '-' -f1)
if [[ "${{ matrix.image_name }}" == "pulp" ]]; then
Expand Down Expand Up @@ -211,6 +214,7 @@ jobs:
echo "TAGS=${tags}" >> $GITHUB_ENV
- name: Publish App Image
if: ${{ steps.build_image.outputs.rebuilt_images == 'true' }}
uses: "./.github/actions/publish_images"
with:
image_names: ${{ env.IMAGES }}
Expand Down

0 comments on commit 4062938

Please sign in to comment.