forked from repo-mirrors/cnpg-postgres-containers
231 lines
8.5 KiB
YAML
231 lines
8.5 KiB
YAML
name: Continuous Delivery
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
paths-ignore:
|
|
- Debian/ClusterImageCatalog*.yaml
|
|
workflow_dispatch:
|
|
|
|
permissions: read-all
|
|
|
|
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-24.04
|
|
outputs:
|
|
strategy: ${{ steps.generate-jobs.outputs.strategy }}
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
|
- 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-24.04
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
security-events: write
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
|
|
|
- name: Set up QEMU
|
|
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # 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@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3
|
|
|
|
- name: Log in to the GitHub Container registry
|
|
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3
|
|
with:
|
|
registry: ghcr.io
|
|
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 docker://${IMAGE} --format '{{ .Digest }}')" >> $GITHUB_ENV
|
|
else
|
|
echo "MISSING_TAG=true" >> $GITHUB_ENV
|
|
fi
|
|
|
|
- name: Build and load
|
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6
|
|
if: ${{ env.MISSING_TAG == 'true' }}
|
|
with:
|
|
context: ${{ matrix.dir }}
|
|
file: ${{ matrix.file }}
|
|
push: false
|
|
load: true
|
|
tags: ${{ env.TAGS }}
|
|
|
|
- name: Dockle scan
|
|
uses: erzz/dockle-action@69369bc745ee29813f730231a821bcd4f71cd290 # v1
|
|
if: ${{ env.MISSING_TAG == 'true' }}
|
|
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
|
|
if: ${{ env.MISSING_TAG == 'true' }}
|
|
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@96f518a34f7a870018057716cc4d7a5c014bd61c # v3
|
|
if: ${{ env.MISSING_TAG == 'true' }}
|
|
continue-on-error: true
|
|
with:
|
|
sarif_file: snyk.sarif
|
|
|
|
- name: Build and push
|
|
id: build
|
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6
|
|
if: ${{ env.MISSING_TAG == 'true' }}
|
|
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
|
|
|
|
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 }} \
|
|
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@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
with:
|
|
name: ${{ matrix.version }}-${{ matrix.distro }}-clusterimagecatalog
|
|
path: ${{ matrix.version }}-${{ matrix.distro }}.yaml
|
|
|
|
image-catalog:
|
|
name: Generate ClusterImageCatalog
|
|
runs-on: ubuntu-24.04
|
|
needs: build
|
|
permissions:
|
|
contents: write
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
|
with:
|
|
token: ${{ secrets.REPO_GHA_PAT }}
|
|
|
|
- name: Download artifacts
|
|
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
|
|
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@af281f37de86139d1c7a27b91176b5dc1c2c827c # v1.1.2
|
|
with:
|
|
access_token: ${{ secrets.REPO_GHA_PAT }}
|
|
branch: main
|
|
enforce_admins: false
|
|
|
|
- name: Push ClusterImageCatalog updates
|
|
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # 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@af281f37de86139d1c7a27b91176b5dc1c2c827c # 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 }}
|