feat: immutable digest for the most specific tags (#113)

Detect updates of the Dockerfile template and Barman python
dependencies, and increase the imageReleaseVersion accordingly.
Avoid pushing an image if its most specific tag (fullTag)
already exists, thus preventing the override of the
existing digest.

Signed-off-by: Niccolò Fei <niccolo.fei@enterprisedb.com>
This commit is contained in:
Niccolò Fei
2024-09-05 16:48:18 +02:00
committed by GitHub
parent d0c032f6c1
commit 57be4d409f
2 changed files with 53 additions and 9 deletions

View File

@@ -72,8 +72,29 @@ jobs:
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
# When publishing new images from main, we should not overwrite an existing
# tag in order to guarantee the tag's SHA digest consistency.
- name: Verify primary tag is not overwritten
run: |
echo "MISSING_TAG=false" >> $GITHUB_ENV
# if we are not on the main branch, always push
if [ "${GITHUB_REF#refs/heads/}" != main ]; then
echo "MISSING_TAG=true" >> $GITHUB_ENV
exit 0
fi
IMAGE="${IMAGE_RELEASE}:${{ matrix.fullTag }}"
# If the primary tag already exists, skip the building phase
if skopeo inspect docker://${IMAGE} >/dev/null 2>/dev/null; then
echo "Image ${IMAGE} already exists"
# We still need to grab the digest to build the imageCatalog
echo "OLD_DIGEST=$(skopeo inspect docker://${IMAGE} --format '{{ .Digest }}')" >> $GITHUB_ENV
else
echo "MISSING_TAG=true" >> $GITHUB_ENV
fi
- name: Build and load - name: Build and load
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
if: ${{ env.MISSING_TAG == 'true' }}
with: with:
context: ${{ matrix.dir }} context: ${{ matrix.dir }}
file: ${{ matrix.file }} file: ${{ matrix.file }}
@@ -83,6 +104,7 @@ jobs:
- name: Dockle scan - name: Dockle scan
uses: erzz/dockle-action@v1 uses: erzz/dockle-action@v1
if: ${{ env.MISSING_TAG == 'true' }}
with: with:
image: "${{ env.IMAGE_STAGING }}:${{ matrix.tags[0] }}" image: "${{ env.IMAGE_STAGING }}:${{ matrix.tags[0] }}"
exit-code: '1' exit-code: '1'
@@ -92,6 +114,7 @@ jobs:
- name: Run Snyk to check Docker image for vulnerabilities - name: Run Snyk to check Docker image for vulnerabilities
uses: snyk/actions/docker@master uses: snyk/actions/docker@master
if: ${{ env.MISSING_TAG == 'true' }}
continue-on-error: true continue-on-error: true
env: env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
@@ -101,6 +124,7 @@ jobs:
- name: Upload result to GitHub Code Scanning - name: Upload result to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v3 uses: github/codeql-action/upload-sarif@v3
if: ${{ env.MISSING_TAG == 'true' }}
continue-on-error: true continue-on-error: true
with: with:
sarif_file: snyk.sarif sarif_file: snyk.sarif
@@ -108,6 +132,7 @@ jobs:
- name: Build and push - name: Build and push
id: build id: build
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
if: ${{ env.MISSING_TAG == 'true' }}
with: with:
context: ${{ matrix.dir }} context: ${{ matrix.dir }}
file: ${{ matrix.file }} file: ${{ matrix.file }}
@@ -123,7 +148,12 @@ jobs:
BASE_IMAGE=${IMAGE_RELEASE} BASE_IMAGE=${IMAGE_RELEASE}
fi fi
IMAGE=${BASE_IMAGE}:${{ matrix.fullTag }}@${{ steps.build.outputs.digest }} \ DIGEST="${{ steps.build.outputs.digest }}"
if [[ "${{ env.MISSING_TAG }}" == "false" ]]; then
DIGEST="${{ env.OLD_DIGEST }}"
fi
IMAGE=${BASE_IMAGE}:${{ matrix.fullTag }}@${DIGEST} \
MAJOR=${{ matrix.version }} \ MAJOR=${{ matrix.version }} \
yq --null-input '{ yq --null-input '{
"apiVersion": "postgresql.cnpg.io/v1", "apiVersion": "postgresql.cnpg.io/v1",

View File

@@ -90,6 +90,14 @@ generate_postgres() {
pipOptions="--break-system-packages" pipOptions="--break-system-packages"
fi fi
dockerTemplate="Dockerfile.template"
if [[ ${version} -gt "${POSTGRESQL_LATEST_MAJOR_RELEASE}" ]]; then
dockerTemplate="Dockerfile-beta.template"
fi
# Update requirements.txt
echo "$requirements" > "$versionDir/requirements.txt"
# Output the image being updated # Output the image being updated
echo "$postgresImageVersion" echo "$postgresImageVersion"
@@ -111,9 +119,9 @@ generate_postgres() {
newRelease="false" newRelease="false"
# Detect if postgres image updated # Detect an update of the postgres image
if [ "$oldPostgresImageLastUpdate" != "$postgresImageLastUpdate" ]; then if [ "$oldPostgresImageLastUpdate" != "$postgresImageLastUpdate" ]; then
echo "Debian Image changed from $oldPostgresImageLastUpdate to $postgresImageLastUpdate" echo "Postgres image timestamp changed from $oldPostgresImageLastUpdate to $postgresImageLastUpdate"
newRelease="true" newRelease="true"
record_version "${versionFile}" "POSTGRES_IMAGE_LAST_UPDATED" "${postgresImageLastUpdate}" record_version "${versionFile}" "POSTGRES_IMAGE_LAST_UPDATED" "${postgresImageLastUpdate}"
fi fi
@@ -125,6 +133,18 @@ generate_postgres() {
record_version "${versionFile}" "BARMAN_VERSION" "${barmanVersion}" record_version "${versionFile}" "BARMAN_VERSION" "${barmanVersion}"
fi fi
# Detect an update of Dockerfile template
if [[ -n $(git diff --name-status "$dockerTemplate") ]]; then
echo "Detected update of $dockerTemplate"
newRelease="true"
fi
# Detect an update of requirements.txt
if [[ -n $(git diff --name-status "$versionDir/requirements.txt") ]]; then
echo "Detected update of requirements.txt dependencies"
newRelease="true"
fi
if [ "$oldPostgresImageVersion" != "$postgresImageVersion" ]; then if [ "$oldPostgresImageVersion" != "$postgresImageVersion" ]; then
echo "PostgreSQL base image changed from $oldPostgresImageVersion to $postgresImageVersion" echo "PostgreSQL base image changed from $oldPostgresImageVersion to $postgresImageVersion"
record_version "${versionFile}" "IMAGE_RELEASE_VERSION" 1 record_version "${versionFile}" "IMAGE_RELEASE_VERSION" 1
@@ -135,12 +155,6 @@ generate_postgres() {
record_version "${versionFile}" "IMAGE_RELEASE_VERSION" $imageReleaseVersion record_version "${versionFile}" "IMAGE_RELEASE_VERSION" $imageReleaseVersion
fi fi
dockerTemplate="Dockerfile.template"
if [[ ${version} -gt "${POSTGRESQL_LATEST_MAJOR_RELEASE}" ]]; then
dockerTemplate="Dockerfile-beta.template"
fi
echo "$requirements" > "$versionDir/requirements.txt"
sed -e 's/%%POSTGRES_IMAGE_VERSION%%/'"$postgresImageVersion"'/g' \ sed -e 's/%%POSTGRES_IMAGE_VERSION%%/'"$postgresImageVersion"'/g' \
-e 's/%%IMAGE_RELEASE_VERSION%%/'"$imageReleaseVersion"'/g' \ -e 's/%%IMAGE_RELEASE_VERSION%%/'"$imageReleaseVersion"'/g' \
-e 's/%%PIP_OPTIONS%%/'"${pipOptions}"'/g' \ -e 's/%%PIP_OPTIONS%%/'"${pipOptions}"'/g' \