From 5b603f42838bcaddb74ba15097cb2cc523c23824 Mon Sep 17 00:00:00 2001 From: oseoin Date: Thu, 16 May 2024 23:35:21 +0100 Subject: [PATCH] Forced SHA update workflow (#5560) --- .github/scripts/docker-updater.sh | 75 +++++++++++++++++++++++++ .github/workflows/update-docker-sha.yml | 69 +++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100755 .github/scripts/docker-updater.sh create mode 100644 .github/workflows/update-docker-sha.yml diff --git a/.github/scripts/docker-updater.sh b/.github/scripts/docker-updater.sh new file mode 100755 index 0000000000..6827e70cd1 --- /dev/null +++ b/.github/scripts/docker-updater.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +set -o pipefail + +SCRIPT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" +DOCKER_FILE=${SCRIPT_ROOT}/build/Dockerfile +exclude_strings="" + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + key="$1" + case $key in + --exclude) + exclude_strings="$2" + shift + shift + ;; + *) + DOCKER_FILE="$1" + shift + ;; + esac +done + +# Check if the file exists +if [ ! -f "$DOCKER_FILE" ]; then + echo "File $DOCKER_FILE does not exist." + exit 1 +fi + +function contains_excluded() { + local line="$1" + local exclude="$2" + local IFS=',' + local excluded=($exclude) + for word in "${excluded[@]}"; do + if [[ "$line" == *"$word"* ]]; then + return 0 + fi + done + return 1 +} + +function check_sha() { + image_sha="$1" + image=$(echo "$image_sha" | cut -d '@' -f1) + tag_sha=$(echo "$image_sha" | cut -d '@' -f2) + + docker pull -q "$image" > /dev/null + latest_digest=$(docker inspect --format='{{index .RepoDigests 0}}' "$image") + latest_sha=$(echo "$latest_digest" | cut -d '@' -f2) + + if [ "$tag_sha" = "$latest_sha" ]; then + echo "The provided SHA256 hash is the latest for $image" + else + echo "> A newer version of $image is available:" + echo "> - $image@$tag_sha" + echo "> + $image@$latest_sha" + echo "> updating $DOCKER_FILE" + sed -i -e "s/$tag_sha/$latest_sha/g" "$DOCKER_FILE" + fi +} +if [ -n "$exclude_strings" ]; then + echo "excluding images containing one of: '$exclude_strings'" +fi +while IFS= read -r line; do + if [[ $line =~ ^FROM\ (.+@.+) ]]; then + image=$(echo "${BASH_REMATCH[1]}" | awk '{print $1}') + if [ -n "$exclude_strings" ] && contains_excluded "$line" "$exclude_strings"; then + echo "Skipping $image" + continue + fi + check_sha "$image" + fi +done < "$DOCKER_FILE" diff --git a/.github/workflows/update-docker-sha.yml b/.github/workflows/update-docker-sha.yml new file mode 100644 index 0000000000..5d34136442 --- /dev/null +++ b/.github/workflows/update-docker-sha.yml @@ -0,0 +1,69 @@ +name: "Update pinned container SHAs" + +on: + workflow_dispatch: + inputs: + source_branch: + required: true + type: string + default: 'main' + excludes: + description: Comma separated list of strings to exclude images from the update + required: false + type: string + default: '' + dry_run: + type: boolean + default: false + +defaults: + run: + shell: bash + +permissions: + contents: read + +jobs: + update-docker-sha: + permissions: + contents: write + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + with: + ref: ${{ inputs.source_branch }} + + - name: Update images + id: update_images + run: | + docker_md5=$(find . -type f \( -wholename "build/Dockerfile" -o -wholename "tests/Dockerfile" \) -exec md5sum {} + | LC_ALL=C sort | md5sum | awk '{ print $1 }') + echo "docker_md5=${docker_md5:0:8}" >> $GITHUB_OUTPUT + ARGS="" + if [ -n ${{ github.event.inputs.excludes }} ]; then + ARGS="--exclude ${{ github.event.inputs.excludes }}" + fi + .github/scripts/docker-updater.sh ./build/Dockerfile $ARGS + .github/scripts/docker-updater.sh ./tests/Dockerfile $ARGS + files=$(git diff --name-only) + if [[ $files == *"Dockerfile"* ]]; then + echo "change_detected=true" >> $GITHUB_OUTPUT + else + echo "change_detected=false" >> $GITHUB_OUTPUT + fi + echo $GITHUB_OUTPUT + + - name: Create Pull Request + uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5 + with: + token: ${{ secrets.NGINX_PAT }} + commit-message: Update docker images ${{ steps.update_images.outputs.docker_md5 }} + title: Docker image update ${{ steps.update_images.outputs.docker_md5 }} + branch: chore/image-update-${{ inputs.source_branch }}-${{ steps.update_images.outputs.docker_md5 }} + author: nginx-bot + labels: | + chore + dependency + body: | + This automated PR updates pinned container image SHAs to latest. + if: ${{ !inputs.dry_run && steps.update_images.outputs.change_detected == 'true' }}