builds/release/detect-image-updates.yaml (91 lines of code) (raw):
trigger: none
pr: none
schedules:
# Twice daily (7AM/PM PST)
- cron: "0 3,15 * * *"
displayName: Twice daily check (8AM/PM PDT)
branches:
include:
- main
- release/*
always: true
resources:
repositories:
- repository: product
type: github
endpoint: Azure/azure-iotedge
name: Azure/azure-iotedge
variables:
Codeql.Enabled: false
DisableDockerDetector: true
NugetSecurityAnalysisWarningLevel: warn
pool:
name: $(pool.linux.name)
demands:
- ImageOverride -equals agent-aziotedge-ubuntu-22.04-msmoby
steps:
- checkout: product
fetchDepth: 0
- script: |
#!/bin/bash
set -euo pipefail
branch="${BUILD_SOURCEBRANCH#refs/heads/}"
echo "Filtering product-versions.json for images on branch '$branch'"
# transform product-versions.json into a list of images for each product in this branch
images_json=$(cat product-versions.json | jq --arg registry "$REGISTRY" --arg branch "$branch" '
[
.channels[] | .products[] | {
product: .id, version, images: [
.components[]
| select(has("type") and .type == "dockerImage" and .repo == "Azure/iotedge" and .branch == $branch)
| "\($registry)/\(.name):\(.version)"
]
}
] | unique | map(select(.images | length != 0))
')
# $images_json contains something like:
# [
# {
# "product": "aziot-edge",
# "version": "1.4.9",
# "images": [
# "mcr.microsoft.com/azureiotedge-agent:1.4.9",
# "mcr.microsoft.com/azureiotedge-hub:1.4.9",
# "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.4.9",
# "mcr.microsoft.com/azureiotedge-diagnostics:1.4.9"
# ]
# },
# {
# "product": "api-proxy",
# "version": "1.1.3",
# "images": [
# "mcr.microsoft.com/azureiotedge-api-proxy:1.1.3"
# ]
# }
# ]
images=( $(echo "$images_json" | jq -r '[ .[].images ] | flatten | join("\n")') )
echo "Found ${#images[@]} images"
# $images contains something like:
# mcr.microsoft.com/azureiotedge-agent:1.4.9
# mcr.microsoft.com/azureiotedge-hub:1.4.9
# mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.4.9
# mcr.microsoft.com/azureiotedge-diagnostics:1.4.9
# mcr.microsoft.com/azureiotedge-api-proxy:1.1.3
# use build metadata present in each published image to determine if it is out of date
remove=( )
for image in ${images[@]}
do
echo "image: $image"
# This command assumes that $image is a manifest list, i.e., a mutli-platform image.
base_images=( $(
docker buildx imagetools inspect --format "{{json .Provenance}}" $image | jq -r '
. as $doc | [
keys[] | $doc[.] | [
.SLSA // halt | .materials[] | select(.uri | startswith("pkg:docker/docker/dockerfile") | not)
] | if length == 1 then first else (
"Error: inspect command found more than one base image in provenance materials\n\(.)" | halt_error
) end | "\(.uri | sub("pkg:docker/(?<i>.+)@(?<t>.+)\\?.+"; "\(.i):\(.t)")),sha256:\(.digest.sha256)"
] | unique | .[]
'
) )
# $base_images contains entries in the form of:
# mcr.microsoft.com/dotnet/runtime@6.0-alpine,sha256:b7a9b8fbdb096327a1e05cda40d40afbec54b96e1a6a1bb7577e67344f9d99e4
for base_info in ${base_images[@]}; do
IFS=',' read base_image current_digest <<< "$base_info"
latest_digest="$(docker buildx imagetools inspect $base_image --format '{{json .Manifest}}' | jq -r '.digest')"
echo -e " base:\t\t$base_image\n current:\t$current_digest\n latest:\t$latest_digest"
if [ -n "$current_digest" ] && [ "$current_digest" != "$latest_digest" ]
then
echo " ## NEEDS UPDATE ##"
else
remove+=( "$image" )
fi
done
done
# filter up-to-date images out of the list
remove_json=$(printf '%s\n' "${remove[@]}" | jq -R '.' | jq -s '. | unique')
images_json=$(echo "$images_json" | jq --argjson remove "$remove_json" '
[ .[] | { product, version, images: (.images - $remove) } | select(.images | length != 0) ]
')
if [ $(echo "$images_json" | jq '. | length != 0') == 'true' ]
then
echo 'Found images that need to be updated:'
echo "$images_json" | jq '.'
else
echo 'All images are up to date. Nothing to do...'
fi
echo "$images_json" > $(Build.ArtifactStagingDirectory)/updates.json
displayName: Detect base image updates
env:
REGISTRY: mcr.microsoft.com
- task: PublishBuildArtifacts@1
displayName: Save list of images to update
inputs:
pathtoPublish: '$(Build.ArtifactStagingDirectory)/updates.json'
artifactName: image-updates