name: Continuous Delivery on: push: branches: - main paths-ignore: - Debian/ClusterImageCatalog*.yaml workflow_dispatch: env: IMAGE_STAGING: "ghcr.io/${{ github.repository_owner }}/postgresql-testing" IMAGE_RELEASE: "ghcr.io/${{ github.repository_owner }}/postgresql" DEFAULT_DISTRO: "bullseye" jobs: generate-jobs: name: Generate Jobs runs-on: ubuntu-22.04 outputs: strategy: ${{ steps.generate-jobs.outputs.strategy }} steps: - name: Checkout Code uses: actions/checkout@v4 - name: Generate Jobs id: generate-jobs shell: bash run: | bash .github/generate-strategy.sh build: needs: generate-jobs strategy: ${{ fromJson(needs.generate-jobs.outputs.strategy) }} name: ${{ matrix.name }} runs-on: ubuntu-22.04 permissions: contents: read packages: write security-events: write steps: - name: Checkout Code uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v3 with: platforms: ${{ matrix.platforms }} - name: Docker meta env: TAGS: ${{ toJson(matrix.tags) }} run: | RESULT="" for tag in $(jq -r '.[]' <<< "${TAGS}") do RESULT="${RESULT},${IMAGE_STAGING}:${tag}" # If we are running the pipeline in the main branch images are pushed in both -testing and PROD repo if [ "${GITHUB_REF#refs/heads/}" == main ] then RESULT="${RESULT},${IMAGE_RELEASE}:${tag}" fi done echo "TAGS=${RESULT%,}" >> $GITHUB_ENV - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to the GitHub Container registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and load uses: docker/build-push-action@v6 with: context: ${{ matrix.dir }} file: ${{ matrix.file }} push: false load: true tags: ${{ env.TAGS }} - name: Dockle scan uses: erzz/dockle-action@v1 with: image: "${{ env.IMAGE_STAGING }}:${{ matrix.tags[0] }}" exit-code: '1' failure-threshold: WARN accept-keywords: key accept-filenames: usr/share/cmake/Templates/Windows/Windows_TemporaryKey.pfx,etc/trusted-key.key,usr/share/doc/perl-IO-Socket-SSL/certs/server_enc.p12,usr/share/doc/perl-IO-Socket-SSL/certs/server.p12,usr/local/lib/python3.9/dist-packages/azure/core/settings.py,usr/local/lib/python3.8/site-packages/azure/core/settings.py,usr/share/postgresql-common/pgdg/apt.postgresql.org.asc,usr/local/lib/python3.7/dist-packages/azure/core/settings.py,etc/ssl/private/ssl-cert-snakeoil.key,usr/lib/python3.9/site-packages/azure/core/settings.py,usr/local/lib/python3.11/dist-packages/azure/core/settings.py - name: Run Snyk to check Docker image for vulnerabilities uses: snyk/actions/docker@master continue-on-error: true env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: image: "${{ env.IMAGE_STAGING }}:${{ matrix.tags[0] }}" args: --severity-threshold=high --file=${{ matrix.file }} - name: Upload result to GitHub Code Scanning uses: github/codeql-action/upload-sarif@v3 continue-on-error: true with: sarif_file: snyk.sarif - name: Build and push id: build uses: docker/build-push-action@v6 with: context: ${{ matrix.dir }} file: ${{ matrix.file }} platforms: ${{ matrix.platforms }} push: true tags: ${{ env.TAGS }} - name: Create artifact run: | # Set a default image BASE_IMAGE=${IMAGE_STAGING} if [ "${GITHUB_REF#refs/heads/}" == main ]; then BASE_IMAGE=${IMAGE_RELEASE} fi IMAGE=${BASE_IMAGE}:${{ matrix.fullTag }}@${{ steps.build.outputs.digest }} \ MAJOR=${{ matrix.version }} \ yq --null-input '{ "apiVersion": "postgresql.cnpg.io/v1", "kind": "ClusterImageCatalog", "metadata": {"name":"postgresql"}, "spec": { "images": [ { "major": env(MAJOR), "image": env(IMAGE) } ] } }' > ${{ matrix.version }}-${{ matrix.distro }}.yaml - name: Upload artifact uses: actions/upload-artifact@v4 with: name: ${{ matrix.version }}-${{ matrix.distro }}-clusterimagecatalog path: ${{ matrix.version }}-${{ matrix.distro }}.yaml image-catalog: name: Generate ClusterImageCatalog runs-on: ubuntu-22.04 needs: build steps: - name: Checkout Code uses: actions/checkout@v4 with: token: ${{ secrets.REPO_GHA_PAT }} - name: Download artifacts uses: actions/download-artifact@v4 with: pattern: '*-clusterimagecatalog' path: clusterimagecatalog merge-multiple: true - name: Update ClusterImageCatalog run: | yq eval-all '. as $item ireduce ({}; . *+ $item )' clusterimagecatalog/*-bullseye.yaml > Debian/ClusterImageCatalog-bullseye.yaml yq eval-all '. as $item ireduce ({}; . *+ $item )' clusterimagecatalog/*-bookworm.yaml > Debian/ClusterImageCatalog-bookworm.yaml ln -f -s ClusterImageCatalog-${DEFAULT_DISTRO}.yaml Debian/ClusterImageCatalog.yaml cat Debian/ClusterImageCatalog.yaml Debian/ClusterImageCatalog-bullseye.yaml Debian/ClusterImageCatalog-bookworm.yaml - name: Temporarily disable "include administrators" branch protection if: ${{ always() && github.ref == 'refs/heads/main' }} id: disable_include_admins uses: benjefferies/branch-protection-bot@v1.1.2 with: access_token: ${{ secrets.REPO_GHA_PAT }} branch: main enforce_admins: false - name: Push ClusterImageCatalog updates uses: EndBug/add-and-commit@v9 if: ${{ github.ref == 'refs/heads/main' }} with: author_name: CloudNativePG Automated Updates author_email: noreply@cnpg.com message: 'Automatic ClusterImageCatalog update' add: 'Debian/ClusterImageCatalog*.yaml' - name: Enable "include administrators" branch protection uses: benjefferies/branch-protection-bot@v1.1.2 if: ${{ always() && github.ref == 'refs/heads/main' }} with: access_token: ${{ secrets.REPO_GHA_PAT }} branch: main enforce_admins: ${{ steps.disable_include_admins.outputs.initial_status }}