Skip to content

Commit

Permalink
#270 Adjust prune workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
chang-annie committed Aug 22, 2024
1 parent 4d2516d commit 047f063
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 10 deletions.
51 changes: 51 additions & 0 deletions .github/scripts/release_images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/bash

# Initialize array to store digest SHAs
declare -a digests

# Fetch all docker image names
image_names=$(gh api \
-H "Accept: application/vnd.github+json" \
-H "-GitHub-Api-Version: 2022-11-28" \
-H "Authorization: Token ${GITHUB_TOKEN}" \
--paginate "/orgs/boozallen/packages?package_type=container" | jq -r '.[] | select((.name | startswith("aissemble")) and (.name | endswith("-chart") | not)) | .name')

# For each docker image, find all release versions, excluding 1.7.0(-arm64/amd64)
for name in $image_names; do
release_versions=$(gh api \
-H "Accept: application/vnd.github+json" \
-H "-GitHub-Api-Version: 2022-11-28" \
-H "Authorization: Token ${GITHUB_TOKEN}" \
--paginate "/orgs/boozallen/packages/container/${name}/versions" \
| jq -r '.[] | .metadata.container.tags[] | select(test("^\\d+\\.\\d+\\.\\d+?$"))' \
| jq -R -s 'split("\n") | map(select(length > 0)) | map(select(. != "1.7.0" and . != "1.7.0-arm64" and . != "1.7.0-amd64"))')

# Loop through all release versions
for version in $(echo "$release_versions" | jq -r '.[]'); do
echo "Processing release image ${name}:${version}"

# Fetch the base manifest SHA
# Inspect command will output Name, MediaType, Digest in the first three lines
# so we can use a regex to pull out the SHA
manifest_base_sha=$(docker buildx imagetools inspect "ghcr.io/boozallen/${name}:${version}" | head -n 3 | sed -n 's/^Digest: *//p')

echo "Manifest index SHA: ${manifest_base_sha}"

# Add to digests array
digests+=("$manifest_base_sha")

# Query the raw inpect output to get the nested manifest list SHAs
manifest_list_shas=$(docker buildx imagetools inspect --raw "ghcr.io/boozallen/${name}:${version}" | jq -r '.manifests[].digest' | paste -s -d ' ' -)

echo "Manifest List SHAs: $manifest_list_shas"

# Add to digests array
digests+=("$manifest_list_shas")
done
done

# Join digests into a single string separated by spaces
digests_string=$(echo "${digests[*]}")

# Save the output to $GITHUB_OUTPUT
echo "multi-arch-digests=${digests_string}" >> "$GITHUB_OUTPUT"
83 changes: 83 additions & 0 deletions .github/scripts/snapshot_images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/bin/bash

# Initialize array to store digest SHAs
declare -a digests

# Fetch all docker image names
image_names=$(gh api \
-H "Accept: application/vnd.github+json" \
-H "-GitHub-Api-Version: 2022-11-28" \
-H "Authorization: Token ${GITHUB_TOKEN}" \
--paginate "/orgs/boozallen/packages?package_type=container" | jq -r '.[] | select((.name | startswith("aissemble")) and (.name | endswith("-chart") | not)) | .name')

# For each docker image, find their snapshot versions by grabbing any tag that ends with "-SNAPSHOT"
for name in $image_names; do
all_snapshot_versions=$(gh api \
-H "Accept: application/vnd.github+json" \
-H "-GitHub-Api-Version: 2022-11-28" \
-H "Authorization: Token ${GITHUB_TOKEN}" \
--paginate "/orgs/boozallen/packages/container/${name}/versions" \
| jq -r '.[] | .metadata.container.tags[] | select(endswith("-SNAPSHOT"))'| jq -R -s 'split("\n")| map(select(length > 0))')

# Find the latest snapshot version by sorting all snapshot versions, then selecting the top
latest_snapshot_version=$(echo "$all_snapshot_versions" | jq -r '.[] | select(endswith("-SNAPSHOT"))' | sort -r | head -n 1)

echo "Processing snapshot image ${name}:${latest_snapshot_version}"

# Fetch the latest snapshot version SHA
latest_snapshot_manifest_list_shas=$(docker buildx imagetools inspect --raw "ghcr.io/boozallen/${name}:${latest_snapshot_version}" | jq -r '.manifests[].digest' | paste -s -d ' ' -)

echo "Manifest List: $latest_snapshot_manifest_list_shas"

# Add to digests array
digests+=("$latest_snapshot_manifest_list_shas")

# Find if there are any patch versions available
# Extract version from latest snapshot
version_part="${latest_snapshot_version%-SNAPSHOT}"

# Extract the major, minor, and patch components using IFS (Internal Field Separator)
IFS='.' read -r major minor patch <<< "$version_part"
previous_major=$((major - 1))
previous_minor=$((minor - 1))

# If previous_minor is >= 0, then patch pattern = [current_major].[previous_minor].[1-9]-SNAPSHOT
if [ $previous_minor -ge 0 ];then
patch_major=${major}
patch_minor=${previous_minor}
else
# Else previous_minor is < 0, then patch pattern = [previous_major].[10 + previous_minor].[1-9]-SNAPSHOT
patch_major=${previous_major}
patch_minor=$((10 + previous_minor))
fi

patch_pattern="${patch_major}\.${patch_minor}\.[1-9]-SNAPSHOT"

for version in $(echo "$all_snapshot_versions" | jq -r '.[]'); do
if [[ ${version} =~ ^${patch_pattern}$ ]]; then
echo "Patch version ${version} matches patch pattern ${patch_pattern}"

# Add to array containing all matching patch versions
matching_patch_versions+=("$version")
fi

# If matching patch versions array is not empty
if [ ${#matching_patch_versions[@]} -ne 0 ]; then
echo "Patch Versions array is not empty"
# Find the latest patch version
latest_patch_version=($(printf "%s\n" "${matching_patch_versions[@]}" | sort -V -r | head -n 1))

# Fetch the SHA
latest_patch_version_sha=$(docker buildx imagetools inspect --raw "ghcr.io/boozallen/${name}:${latest_patch_version}" | jq -r '.manifests[].digest' | paste -s -d ' ' -)

# Add to the digests array
digests+=("$latest_patch_version_sha")
fi
done
done

# Join digests into a single string separated by spaces
digests_string=$(echo "${digests[*]}")

# Save the output to $GITHUB_OUTPUT
echo "latest-snapshot-digests=${digests_string}" >> "$GITHUB_OUTPUT"
43 changes: 33 additions & 10 deletions .github/workflows/prune.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Prunes old aissemble-* untagged containers
# Prunes old aissemble-* containers, excluding those with the following tags:
# any release versions, the latest snapshot version, and the latest patch version

name: Prune ghcr.io

Expand All @@ -15,14 +16,36 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Prune
uses: snok/container-retention-policy@v2
# Required in order to access script files in this repository
- uses: actions/checkout@v4

# Prevents multi-platform release images from being pruned by identifying all manifest lists
- name: Fetch multi-platform package version SHAs
id: multi-arch-digests
env:
GITHUB_TOKEN: ${{ secrets.GHCR_IO_TOKEN }}
run: bash ${GITHUB_WORKSPACE}/.github/scripts/release_images.sh

# Prevents the latest snapshot images from being pruned
- name: Fetch latest snapshot version SHAs
id: latest-snapshot-digests
env:
GITHUB_TOKEN: ${{ secrets.GHCR_IO_TOKEN }}
run: bash ${GITHUB_WORKSPACE}/.github/scripts/snapshot_images.sh

- name: Concatenate digests
id: concat-digests
run: |
skip_shas="${{ steps.multi-arch-digests.outputs.multi-arch-digests }} ${{ steps.latest-snapshot-digests.outputs.latest-snapshot-digests }}"
echo "skip_shas=$skip_shas" >> $GITHUB_OUTPUT
- name: Prune old release versions
uses: snok/container-retention-policy@v3.0.0
with:
image-names: aissemble-*
cut-off: Two days ago UTC
account-type: org
org-name: boozallen
keep-at-least: 2
untagged-only: true
dry-run: false
skip-shas: ${{ steps.concat-digests.outputs.skip_shas }}
image-names: "aissemble-* !aissemble-*-chart"
image-tags: "!1.7.0 !1.7.0-arm64 !1.7.0-amd64"
cut-off: 2d
account: boozallen
token: ${{ secrets.GHCR_IO_TOKEN }}

0 comments on commit 047f063

Please sign in to comment.