Skip to content

Commit

Permalink
Add support to compare platform variants (#29)
Browse files Browse the repository at this point in the history
Add support to optionally compare image platform variants. Eg. linux/arm64 is equal to linux/arm64/v8 and both are heavily used on docker images.
  • Loading branch information
clowa authored Oct 10, 2024
1 parent 31074cf commit 07f0faf
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 11 deletions.
62 changes: 56 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ env:
DEBUG: ${{ secrets.ACTIONS_STEP_DEBUG }}

jobs:
#####################################
# Singe platform tests

test1:
name: Test Update Needed
runs-on: ubuntu-22.04
Expand Down Expand Up @@ -52,6 +55,26 @@ jobs:
fi
test3:
name: Test single platform
runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Test Action
id: test
uses: ./
with:
base-image: alpine:3.17.1
image: lucacome/alpine-amd64
- name: Get Test Output
run: echo "Workflow Docker Image ${{ steps.test.outputs.needs-updating }}"
- name: Check value
run: |
if [[ "${{ steps.test.outputs.needs-updating }}" != "false" ]]; then
exit 1
fi
test4:
name: Test Update Needed on ARM64
runs-on: ubuntu-22.04
steps:
Expand All @@ -72,7 +95,10 @@ jobs:
exit 1
fi
test4:
#####################################
# Test with multiple platforms

test5:
name: Test Update Needed on multiple platforms
runs-on: ubuntu-22.04
steps:
Expand All @@ -93,7 +119,7 @@ jobs:
exit 1
fi
test5:
test6:
name: Test Update Not Needed on multiple platforms
runs-on: ubuntu-22.04
steps:
Expand All @@ -113,9 +139,11 @@ jobs:
if [[ "${{ steps.test.outputs.needs-updating }}" != "false" ]]; then
exit 1
fi
#####################################
# Test with platform variants

test6:
name: Test single platform
test7:
name: Test Update Needed on multiple platforms with variants
runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
Expand All @@ -124,8 +152,30 @@ jobs:
id: test
uses: ./
with:
base-image: alpine:3.17.1
image: lucacome/alpine-amd64
base-image: alpine:latest
image: golang:1.14.15-alpine3.13
platforms: linux/arm64/v8,linux/arm/v7,linux/amd64
- name: Get Test Output
run: echo "Workflow Docker Image ${{ steps.test.outputs.needs-updating }}"
- name: Check value
run: |
if [[ "${{ steps.test.outputs.needs-updating }}" != "true" ]]; then
exit 1
fi
test8:
name: Test Update Not Needed on multiple platforms with variants
runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Test Action
id: test
uses: ./
with:
base-image: alpine:3.17.2
image: alpine:3.17.2
platforms: linux/arm64/v8,linux/arm/v7,linux/amd64
- name: Get Test Output
run: echo "Workflow Docker Image ${{ steps.test.outputs.needs-updating }}"
- name: Check value
Expand Down
12 changes: 7 additions & 5 deletions docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ get_manifests() {
fi

headers=$(cat headers | awk -F ': ' '{sub(/\r/,"\n",$2); print $1","$2}' | grep 'docker-content-digest\|content-type' | jq -R 'split(",") | {(if .[0] == "content-type" then "type" else "digest" end): .[1]}' | jq -s 'reduce .[] as $item ({}; . * $item)')
manifest_v2=$(jq -r '. | select(.type == "application/vnd.docker.distribution.manifest.v2+json" or .type == "application/vnd.oci.image.manifest.v1+json") | [{digest: .digest, platform: "linux/amd64"}]' <<<"$headers")
manifest_v2=$(jq -r '. | select(.type == "application/vnd.docker.distribution.manifest.v2+json" or .type == "application/vnd.oci.image.manifest.v1+json") | [{digest: .digest, platforms: ["linux/amd64"]}]' <<<"$headers")
if [ ! -z "$manifest_v2" ]; then
echo "$manifest_v2"
return
fi

jq -r '[.manifests[] | select(.platform.architecture | contains ("unknown") | not) | {digest: .digest, platform: (.platform.os +"/"+ .platform.architecture)}]' <<<"$manifest_list"

manifests_with_variant=$(jq -r '[.manifests[] | select(.platform.architecture | contains ("unknown") | not) | select(.platform.variant != null) | {digest: .digest, platforms: [(.platform.os +"/"+ .platform.architecture +"/"+ .platform.variant), (.platform.os +"/"+ .platform.architecture)] }]' <<<"$manifest_list")
manifests_without_variant=$(jq -r '[.manifests[] | select(.platform.architecture | contains ("unknown") | not) | select(.platform.variant == null) | {digest: .digest, platforms: [(.platform.os +"/"+ .platform.architecture)]}]' <<<"$manifest_list")
# Concat both lists
echo "${manifests_with_variant}${manifests_without_variant}" | jq -s 'flatten(1)'
}

get_layers() {
Expand Down Expand Up @@ -111,15 +113,15 @@ diff=false
# loop through plafforms split by comma
for platform in $(echo $platforms | tr -s ',' ' '); do
# get the digest for the platform
digest_base=$(jq -r ".[] | select(.platform == \"$platform\") | .digest" <<<"$manifests_base")
digest_base=$(jq -r ".[] | select(.platforms[] == \"$platform\") | .digest" <<<"$manifests_base")

# if the digest is empty, then the platform is not present in the base image
if [ -z "$digest_base" ]; then
error "Platform $platform not found in the base image $base"
fi

# get the digest for the platform
digest_image=$(jq -r ".[] | select(.platform == \"$platform\") | .digest" <<<"$manifests_image")
digest_image=$(jq -r ".[] | select(.platforms[] == \"$platform\") | .digest" <<<"$manifests_image")

# if the digest is empty, then the platform is not present in the image
if [ -z "$digest_image" ]; then
Expand Down

0 comments on commit 07f0faf

Please sign in to comment.