diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 13f81fb9..4007e17a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -72,8 +72,29 @@ jobs: username: ${{ github.actor }} 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 --no-tags docker://${IMAGE} --format '{{ .Digest }}')" >> $GITHUB_ENV + else + echo "MISSING_TAG=true" >> $GITHUB_ENV + fi + - name: Build and load uses: docker/build-push-action@v5 + if: ${{ env.MISSING_TAG == 'true' }} with: context: ${{ matrix.dir }} file: ${{ matrix.file }} @@ -83,6 +104,7 @@ jobs: - name: Dockle scan uses: erzz/dockle-action@v1 + if: ${{ env.MISSING_TAG == 'true' }} with: image: "${{ env.IMAGE_STAGING }}:${{ matrix.tags[0] }}" exit-code: '1' @@ -92,6 +114,7 @@ jobs: - name: Run Snyk to check Docker image for vulnerabilities uses: snyk/actions/docker@master + if: ${{ env.MISSING_TAG == 'true' }} continue-on-error: true env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} @@ -101,6 +124,7 @@ jobs: - name: Upload result to GitHub Code Scanning uses: github/codeql-action/upload-sarif@v3 + if: ${{ env.MISSING_TAG == 'true' }} continue-on-error: true with: sarif_file: snyk.sarif @@ -108,6 +132,7 @@ jobs: - name: Build and push id: build uses: docker/build-push-action@v5 + if: ${{ env.MISSING_TAG == 'true' }} with: context: ${{ matrix.dir }} file: ${{ matrix.file }} @@ -123,7 +148,12 @@ jobs: BASE_IMAGE=${IMAGE_RELEASE} fi - IMAGE=${BASE_IMAGE}:${{ matrix.fullTag }}@${{ steps.build.outputs.digest }} \ + DIGEST="${{ steps.build.outputs.digest }}" + if [[ "${{ env.MISSING_TAG}}" == "true" ]]; then + DIGEST=${{ env.OLD_DIGEST }} + fi + + IMAGE=${BASE_IMAGE}:${{ matrix.fullTag }}@${DIGEST} \ MAJOR=${{ matrix.version }} \ yq --null-input '{ "apiVersion": "postgresql.cnpg.io/v1", diff --git a/lib/repo_funcs.sh b/lib/repo_funcs.sh index a22e4434..22ac9420 100644 --- a/lib/repo_funcs.sh +++ b/lib/repo_funcs.sh @@ -90,6 +90,14 @@ generate_postgres() { pipOptions="--break-system-packages" 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 echo "$postgresImageVersion" @@ -111,9 +119,9 @@ generate_postgres() { newRelease="false" - # Detect if postgres image updated + # Detect an update of the postgres image if [ "$oldPostgresImageLastUpdate" != "$postgresImageLastUpdate" ]; then - echo "Debian Image changed from $oldPostgresImageLastUpdate to $postgresImageLastUpdate" + echo "Postgres image timestamp changed from $oldPostgresImageLastUpdate to $postgresImageLastUpdate" newRelease="true" record_version "${versionFile}" "POSTGRES_IMAGE_LAST_UPDATED" "${postgresImageLastUpdate}" fi @@ -125,6 +133,18 @@ generate_postgres() { record_version "${versionFile}" "BARMAN_VERSION" "${barmanVersion}" 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 echo "PostgreSQL base image changed from $oldPostgresImageVersion to $postgresImageVersion" record_version "${versionFile}" "IMAGE_RELEASE_VERSION" 1 @@ -135,12 +155,6 @@ generate_postgres() { record_version "${versionFile}" "IMAGE_RELEASE_VERSION" $imageReleaseVersion 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' \ -e 's/%%IMAGE_RELEASE_VERSION%%/'"$imageReleaseVersion"'/g' \ -e 's/%%PIP_OPTIONS%%/'"${pipOptions}"'/g' \