Skip to content

Commit

Permalink
Use homegrown solution to check for base image update (#98)
Browse files Browse the repository at this point in the history
This change replaces the actions I was using to check if the image was
up to date because none of the solutions were working properly.
  • Loading branch information
craigktreasure authored Oct 22, 2023
1 parent bd6f7ec commit 33bef72
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 12 deletions.
16 changes: 4 additions & 12 deletions .github/workflows/Rolling.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,10 @@ on:
jobs:
check:
name: Container Image Update Check
runs-on: ubuntu-latest
outputs:
needs-updating: ${{ steps.check.outputs.needs-updating }}
steps:
# https://github.com/giggio/docker-image-update-checker
- name: Check if container update available
id: check
uses: giggio/docker-image-update-checker@v2
with:
base-image: mcr.microsoft.com/dotnet/aspnet:7.0-cbl-mariner2.0-distroless
image: ${{ secrets.DOCKERHUB_USERNAME }}/synologyddnsupdater:latest
os: linux
uses: ./.github/workflows/workflow_image-update-check.yml
with:
base-image: mcr.microsoft.com/dotnet/aspnet:7.0-cbl-mariner2.0-distroless
image: craigktreasure/synologyddnsupdater:latest

build_rolling:
name: Build
Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/workflow_image-update-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Check for image updates

on:
workflow_call:
inputs:
image:
type: string
required: true
description: The container image to verify against the base image.
base-image:
type: string
required: true
description: The container base image.
outputs:
needs-updating:
description: Whether the image needs updating.
value: ${{ jobs.image-update-check.steps.update-check.outputs.needsBaseUpdate }}

jobs:
image-update-check:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Check base image
id: update-check
shell: pwsh
run: |
$imageNeedsUpdate = ./scripts/CheckImageNeedsBaseUpdate.ps1 -Image ${{ inputs.image }} -BaseImage ${{ inputs.base-image }} -CheckDateCreated
"needsBaseUpdate=$imageNeedsUpdate" >> $env:GITHUB_ENV
110 changes: 110 additions & 0 deletions scripts/CheckImageNeedsBaseUpdate.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#Requires -PSEdition Core

<#
.SYNOPSIS
Checks if the image needs to be updated due to changes in the specified base image.
Returns `true` if the image needs to be updated and `false` if the image is up to date.
.PARAMETER BaseImageName
The name of the base image to check against.
.PARAMETER ImageName
The name of the image to check.
.PARAMETER CheckDateCreated
If specified, the image creation date will be checked to ensure the image was created after the base image.
#>
[CmdletBinding()]
param (
[string] $BaseImageName = 'mcr.microsoft.com/dotnet/aspnet:7.0-cbl-mariner2.0-distroless',

[string] $ImageName = 'craigktreasure/synologyddnsupdater:latest',

[switch] $CheckDateCreated
)

Set-StrictMode -Version 2.0
$ErrorActionPreference = 'Stop'

function CheckLastExitCode($message) {
if ($LASTEXITCODE -ne 0) {
Write-Error "Command failed with $LASTEXITCODE. $message"
}
}

function PullImage($imageName) {
Write-Host "Pulling image $imageName..." -ForegroundColor Magenta
docker pull $imageName
CheckLastExitCode "Failed to pull image $imageName"
}

function GetDateCreated($imageName) {
Write-Host "Getting image creation date for $imageName..." -ForegroundColor Magenta
$imageCreated = docker image inspect $imageName --format='{{.Created}}'
CheckLastExitCode "Failed to get image creation date for $imageName"
return $imageCreated
}

function CompareImageCreationDates($baseImageName, $imageName) {
Write-Host 'Comparing image creation dates...' -ForegroundColor Magenta

$baseImageCreated = GetDateCreated $baseImageName
$imageCreated = GetDateCreated $imageName

$baseImageCreatedDate = [DateTime]::Parse($baseImageCreated)
$imageCreatedDate = [DateTime]::Parse($imageCreated)

if ($baseImageCreatedDate -gt $imageCreatedDate) {
Write-Verbose "Base image was created on $baseImageCreatedDate, but image was created on $imageCreatedDate."

return $false
}

return $true
}

function GetImageLayers($imageName) {
Write-Host "Getting image layers for $imageName..." -ForegroundColor Magenta
$imageLayers = docker image inspect $imageName --format='{{range .RootFS.Layers}}{{println .}}{{end}}'
CheckLastExitCode "Failed to get image layers for $imageName"
return $imageLayers | Where-Object { $_ -ne '' }
}

function CheckImageContainsBaseLayers($baseImageLayers, $imageLayers) {
Write-Host 'Comparing image layers...' -ForegroundColor Magenta

for ($i = 0; $i -lt $baseImageLayers.Length; $i++) {
if ($baseImageLayers[$i] -ne $imageLayers[$i]) {
Write-Verbose "Image layers do not match. Base image layer $i is $($baseImageLayers[$i]), but image layer $i is $($imageLayers[$i])."

return $false
}
}

return $true
}

PullImage $BaseImageName
PullImage $ImageName

if ($CheckDateCreated) {
if (CompareImageCreationDates $BaseImageName $ImageName) {
Write-Host 'Image was created after base image.' -ForegroundColor Green
}
else {
Write-Host 'Image was created before base image. Image needs an update.' -ForegroundColor Red

return $true
}
}

$baseImageLayers = GetImageLayers $BaseImageName
$imageLayers = GetImageLayers $ImageName

$imageIsUpToDate = CheckImageContainsBaseLayers $baseImageLayers $imageLayers

if ($imageIsUpToDate) {
Write-Host 'Image contains base layers. Image is up to date.' -ForegroundColor Green
}
else {
Write-Host 'Image does NOT contain all base layers. Image needs an update.' -ForegroundColor Red
}

return !$imageIsUpToDate

0 comments on commit 33bef72

Please sign in to comment.