-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#270 Adjust prune workflow #288
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#!/bin/bash | ||
|
||
# Initialize array to store digest SHAs and all release versions | ||
declare -a digests | ||
declare -a all_release_versions | ||
|
||
# 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 | ||
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"))') | ||
|
||
# Add release versions to all_release_versions array | ||
all_release_versions+=("$release_versions") | ||
|
||
# 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') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I: ideally we would use something more straightforward like
where the referenced SHA points to the attestation/provenance. The workaround here is to search the first 3 lines of the
Another potential workaround would be to use the GitHub API:
However, this would require There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have a Github issue we can link for this bug in the |
||
|
||
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 | ||
|
||
# Pass the latest_release_version to GITHUB_OUTPUT so snapshot_images.sh can use it | ||
latest_release_version=$(echo "$all_release_versions" | jq -r .[] | sort -uV -r | head -n 1) | ||
echo "latest-release-version=${latest_release_version}" >> "$GITHUB_OUTPUT" | ||
|
||
# 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" |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,79 @@ | ||||||
#!/bin/bash | ||||||
|
||||||
# Initialize array to store digest SHAs | ||||||
declare -a digests | ||||||
|
||||||
# Fetch all docker image names | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A: Since we already rely on the release version being passed from the |
||||||
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') | ||||||
chang-annie marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
# 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 base manifest SHA | ||||||
# Inspect command will output Name, MediaType, Digest in the first three lines | ||||||
# Use regex to pull out the SHA | ||||||
latest_snapshot_manifest_base_sha=$(docker buildx imagetools inspect "ghcr.io/boozallen/${name}:${latest_snapshot_version}" | head -n 3 | sed -n 's/^Digest: *//p') | ||||||
|
||||||
echo "Manifest index SHA: ${latest_snapshot_manifest_base_sha}" | ||||||
|
||||||
# Add to digests array | ||||||
digests+=("$latest_snapshot_manifest_base_sha") | ||||||
|
||||||
# Fetch the manifest list SHAs | ||||||
latest_snapshot_manifest_list_shas=$(docker buildx imagetools inspect --raw "ghcr.io/boozallen/${name}:${latest_snapshot_version}" | jq -r '.manifests[].digest' | paste -s -d ' ' -) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Q: Why do we not have to same logic as above when we were getting the release SHA's like this: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need to be pulling the manifest digest SHA for snapshot versions? I thought for snapshot versions we just need the manifest list SHAs but if that's not the case, I can update it to also pull in the manifest digest SHA. so if the manifest is something like this:
we'll be pulling out the following SHAs:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the difference in the manifest digest SHA vs manifest list SHA? I'm just confused why the logic for preserving released versions is different than preserving snapshot versions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @carter-cundiff I agree, I just added it into the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This makes me wonder if we should just pull this logic out into a common shared function that we source in each script. Something like an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for instance I think we'd also need this same logic down in the patch snapshot logic for the same reasons outlined here. |
||||||
|
||||||
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 the major, minor, and patch components of the latest release version using IFS (Internal Field Separator) | ||||||
IFS='.' read -r major minor patch <<< "${LATEST_RELEASE_VERSION}" | ||||||
|
||||||
# Patch pattern uses the latest release version's major and minor components | ||||||
patch_pattern="${major}\.${minor}\.[1-9]+[0-9]*-SNAPSHOT?" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A: I'd drop the plus as it's not doing much here. Also I don't think the
Suggested change
|
||||||
|
||||||
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 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I: the logic to find the latest patch version is as follows:
Since there are no actual patch versions currently, this logic was tested locally by creating dummy data. Some examples below:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there's a false assumption in this logic that the major.minor.patch number has to be 1-9 which is not always the case. Before we released aissemble The logic should still be fine for when the major remains the same, but probably won't work for when the major changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah you're right, I was assuming that our versioning would be 1-9 and sequential... I think it make more sense if I just use the latest release version's major and minor values for the patch pattern. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree. Honestly it's not the end of the world if we delete these patch release snapshots anyway. The one that really matters is the patch release itself. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @carter-cundiff updated to new logic of using the latest release version's major and minor versions for the patch pattern. The latest release version is passed from the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't think this works for when the latest release is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess it would match on both, but it this scenario we want it to match on only |
||||||
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" |
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 | ||
|
||
|
@@ -15,14 +16,37 @@ 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A: For consistency with the snapshot step, it might make sense to call this Fetch release version SHAs and set the id/output names to be |
||
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 }} | ||
LATEST_RELEASE_VERSION: ${{ steps.multi-arch-digests.outputs.latest-release-version }} | ||
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 }}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I: concats the output of the two scripts into a single string that's passed to the |
||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I: As I was reading this PR I again started to question the I think I prefer our current approach anyway, as it also cleans up RC tags without any extra effort. But I just thought I'd bring it up since I know we went back and forth a bit on what the options were doing. |
||
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" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I: we're skipping There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I: and some parameter name changes required for upgrading from |
||
cut-off: 2d | ||
account: boozallen | ||
token: ${{ secrets.GHCR_IO_TOKEN }} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So given this regex will only match to 3 digits (i.e.
1.7.0
), do we still need the check below for1.7.0-arm64
and1.7.0-amd64
? In theory this regex shouldn't match on that.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup, removed!