mirror of
https://github.com/data-privacy-stack/presidio.git
synced 2026-09-21 13:38:05 -05:00
ci: publish distroless variants and rebuild images weekly
Extract the release build/push and manifest jobs into a reusable build-images.yml workflow, extend it with a distroless variant, and add a weekly rebuild-images.yml so digest-pinned bases pick up security updates without a manual re-pin. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
co-authored by
Copilot App
parent
a04e702875
commit
a3f351261a
@@ -0,0 +1,166 @@
|
||||
name: Build and Push Images
|
||||
|
||||
# Reusable image build. Called by release.yml when cutting a release and by
|
||||
# rebuild-images.yml on a schedule, so that published images pick up base image
|
||||
# security updates without waiting for the next release.
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
version:
|
||||
description: Tag applied to the analyzer, anonymizer and CLI-adjacent images.
|
||||
required: true
|
||||
type: string
|
||||
image-version:
|
||||
description: Tag applied to the image-redactor image.
|
||||
required: true
|
||||
type: string
|
||||
date-tag:
|
||||
description: >
|
||||
Optional immutable suffix, e.g. 20260909. When set, each image is also
|
||||
pushed as <version>-<date-tag> so a specific rebuild can be pinned or
|
||||
rolled back to.
|
||||
required: false
|
||||
default: ''
|
||||
type: string
|
||||
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
IMAGE_REGISTRY: ghcr.io
|
||||
IMAGE_NAMESPACE: data-privacy-stack
|
||||
|
||||
jobs:
|
||||
build-and-push-containers:
|
||||
name: Build and Push ${{ matrix.image }}${{ matrix.tag_suffix }} (${{ matrix.platform }})
|
||||
runs-on: ${{ matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [presidio-anonymizer, presidio-analyzer, presidio-image-redactor]
|
||||
platform: [linux/amd64, linux/arm64]
|
||||
variant: [default, distroless]
|
||||
exclude:
|
||||
# No distroless variant is published for the image-redactor: it
|
||||
# depends on the Tesseract OCR system packages, which are not
|
||||
# available in a distroless base image.
|
||||
- image: presidio-image-redactor
|
||||
variant: distroless
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
platform_tag: linux-amd64
|
||||
- platform: linux/arm64
|
||||
platform_tag: linux-arm64
|
||||
- variant: default
|
||||
dockerfile: Dockerfile
|
||||
tag_suffix: ''
|
||||
- variant: distroless
|
||||
dockerfile: Dockerfile.distroless
|
||||
tag_suffix: -distroless
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
env:
|
||||
GHCR_TOKEN: ${{ github.repository_owner == 'data-privacy-stack' && github.token || secrets.GHCR_TOKEN }}
|
||||
GHCR_USERNAME: ${{ github.repository_owner == 'data-privacy-stack' && github.actor || vars.GHCR_USERNAME || github.actor }}
|
||||
run: echo "${GHCR_TOKEN}" | docker login ${{ env.IMAGE_REGISTRY }} -u "${GHCR_USERNAME}" --password-stdin
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Build and Push ${{ matrix.image }}${{ matrix.tag_suffix }} for ${{ matrix.platform }}
|
||||
run: |
|
||||
set -eu
|
||||
repo="${IMAGE_REGISTRY}/${IMAGE_NAMESPACE}/${{ matrix.image }}"
|
||||
version_tag="${VERSION}"
|
||||
if [ "${{ matrix.image }}" = "presidio-image-redactor" ]; then
|
||||
version_tag="${IMAGE_VERSION}"
|
||||
fi
|
||||
suffix="${{ matrix.tag_suffix }}"
|
||||
platform_tag="${{ matrix.platform_tag }}"
|
||||
|
||||
tag_args="--tag ${repo}:latest${suffix}-${platform_tag}"
|
||||
tag_args="${tag_args} --tag ${repo}:${version_tag}${suffix}-${platform_tag}"
|
||||
if [ -n "${DATE_TAG}" ]; then
|
||||
tag_args="${tag_args} --tag ${repo}:${version_tag}-${DATE_TAG}${suffix}-${platform_tag}"
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
docker buildx build \
|
||||
--platform ${{ matrix.platform }} \
|
||||
--file ./${{ matrix.image }}/${{ matrix.dockerfile }} \
|
||||
--cache-from type=registry,ref=${repo}:latest${suffix} \
|
||||
--cache-to type=inline \
|
||||
${tag_args} \
|
||||
--attest type=sbom \
|
||||
--attest type=provenance,mode=max \
|
||||
--push \
|
||||
./${{ matrix.image }}
|
||||
env:
|
||||
VERSION: ${{ inputs.version }}
|
||||
IMAGE_VERSION: ${{ inputs.image-version }}
|
||||
DATE_TAG: ${{ inputs.date-tag }}
|
||||
|
||||
create-container-manifests:
|
||||
name: Create Multi-Platform Container Manifests
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-and-push-containers
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Log in to GitHub Container Registry
|
||||
env:
|
||||
GHCR_TOKEN: ${{ github.repository_owner == 'data-privacy-stack' && github.token || secrets.GHCR_TOKEN }}
|
||||
GHCR_USERNAME: ${{ github.repository_owner == 'data-privacy-stack' && github.actor || vars.GHCR_USERNAME || github.actor }}
|
||||
run: echo "${GHCR_TOKEN}" | docker login ${{ env.IMAGE_REGISTRY }} -u "${GHCR_USERNAME}" --password-stdin
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Create multi-platform manifests
|
||||
run: |
|
||||
set -eu
|
||||
images=(presidio-anonymizer presidio-analyzer presidio-image-redactor)
|
||||
platform_tags=(linux-amd64 linux-arm64)
|
||||
|
||||
for image in "${images[@]}"; do
|
||||
repo="${IMAGE_REGISTRY}/${IMAGE_NAMESPACE}/${image}"
|
||||
version_tag="${VERSION}"
|
||||
suffixes=("" "-distroless")
|
||||
if [ "${image}" = "presidio-image-redactor" ]; then
|
||||
version_tag="${IMAGE_VERSION}"
|
||||
suffixes=("")
|
||||
fi
|
||||
|
||||
for suffix in "${suffixes[@]}"; do
|
||||
tags=("latest${suffix}" "${version_tag}${suffix}")
|
||||
if [ -n "${DATE_TAG}" ]; then
|
||||
tags+=("${version_tag}-${DATE_TAG}${suffix}")
|
||||
fi
|
||||
|
||||
for tag in "${tags[@]}"; do
|
||||
platform_refs=()
|
||||
for platform_tag in "${platform_tags[@]}"; do
|
||||
platform_refs+=("${repo}:${tag}-${platform_tag}")
|
||||
done
|
||||
|
||||
docker buildx imagetools create \
|
||||
--tag "${repo}:${tag}" \
|
||||
"${platform_refs[@]}"
|
||||
done
|
||||
done
|
||||
done
|
||||
env:
|
||||
VERSION: ${{ inputs.version }}
|
||||
IMAGE_VERSION: ${{ inputs.image-version }}
|
||||
DATE_TAG: ${{ inputs.date-tag }}
|
||||
@@ -0,0 +1,71 @@
|
||||
name: Rebuild Images
|
||||
|
||||
# Published images pin their base image by digest, so they never pick up
|
||||
# operating system security updates on their own. Rebuilding on a schedule
|
||||
# republishes the same versions on top of a freshly patched base, which is what
|
||||
# container compliance scanners expect ("redeploy the image", "update the
|
||||
# vulnerable image reference").
|
||||
#
|
||||
# Rebuilds do not change any application code: the workflow builds the current
|
||||
# state of main and republishes the `latest` and current version tags, plus an
|
||||
# immutable `<version>-<date>` tag so a specific rebuild can be pinned.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Every Monday at 05:00 UTC.
|
||||
- cron: '0 5 * * 1'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
get-version:
|
||||
name: Get Version Numbers
|
||||
runs-on: ubuntu-slim
|
||||
outputs:
|
||||
version: ${{ steps.set-version.outputs.version }}
|
||||
image-version: ${{ steps.set-image-version.outputs.image-version }}
|
||||
date-tag: ${{ steps.set-date-tag.outputs.date-tag }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Extract main version
|
||||
id: set-version
|
||||
run: |
|
||||
set -eu
|
||||
ver=$(grep -m 1 version presidio-analyzer/pyproject.toml | tr -s ' ' | tr -d '"' | tr -d "'" | cut -d' ' -f3)
|
||||
echo "version=$ver" >> $GITHUB_OUTPUT
|
||||
echo "Main version: $ver"
|
||||
|
||||
- name: Extract image-redactor version
|
||||
id: set-image-version
|
||||
run: |
|
||||
set -eu
|
||||
imageVer=$(grep -m 1 version presidio-image-redactor/pyproject.toml | tr -s ' ' | tr -d '"' | tr -d "'" | cut -d' ' -f3)
|
||||
echo "image-version=$imageVer" >> $GITHUB_OUTPUT
|
||||
echo "Image-redactor version: $imageVer"
|
||||
|
||||
- name: Set date tag
|
||||
id: set-date-tag
|
||||
run: |
|
||||
set -eu
|
||||
dateTag=$(date -u +'%Y%m%d')
|
||||
echo "date-tag=$dateTag" >> $GITHUB_OUTPUT
|
||||
echo "Date tag: $dateTag"
|
||||
|
||||
rebuild-and-push-containers:
|
||||
name: Rebuild and Push Container Images
|
||||
needs: get-version
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
uses: ./.github/workflows/build-images.yml
|
||||
with:
|
||||
version: ${{ needs.get-version.outputs.version }}
|
||||
image-version: ${{ needs.get-version.outputs.image-version }}
|
||||
date-tag: ${{ needs.get-version.outputs.date-tag }}
|
||||
secrets: inherit
|
||||
@@ -5,10 +5,6 @@ on:
|
||||
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
IMAGE_REGISTRY: ghcr.io
|
||||
IMAGE_NAMESPACE: data-privacy-stack
|
||||
|
||||
jobs:
|
||||
get-version:
|
||||
name: Get Version Numbers
|
||||
@@ -114,101 +110,14 @@ jobs:
|
||||
skip-existing: true
|
||||
|
||||
build-and-push-containers:
|
||||
name: Build and Push ${{ matrix.image }} (${{ matrix.platform }})
|
||||
runs-on: ${{ matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
|
||||
name: Build and Push Container Images
|
||||
needs: get-version
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [presidio-anonymizer, presidio-analyzer, presidio-image-redactor]
|
||||
platform: [linux/amd64, linux/arm64]
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
platform_tag: linux-amd64
|
||||
- platform: linux/arm64
|
||||
platform_tag: linux-arm64
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
env:
|
||||
GHCR_TOKEN: ${{ github.repository_owner == 'data-privacy-stack' && github.token || secrets.GHCR_TOKEN }}
|
||||
GHCR_USERNAME: ${{ github.repository_owner == 'data-privacy-stack' && github.actor || vars.GHCR_USERNAME || github.actor }}
|
||||
run: echo "${GHCR_TOKEN}" | docker login ${{ env.IMAGE_REGISTRY }} -u "${GHCR_USERNAME}" --password-stdin
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Build and Push ${{ matrix.image }} for ${{ matrix.platform }}
|
||||
run: |
|
||||
repo="${IMAGE_REGISTRY}/${IMAGE_NAMESPACE}/${{ matrix.image }}"
|
||||
version_tag="${VERSION}"
|
||||
if [ "${{ matrix.image }}" = "presidio-image-redactor" ]; then
|
||||
version_tag="${IMAGE_VERSION}"
|
||||
fi
|
||||
|
||||
docker buildx build \
|
||||
--platform ${{ matrix.platform }} \
|
||||
--cache-from type=registry,ref=${repo}:latest \
|
||||
--cache-to type=inline \
|
||||
--tag "${repo}:latest-${{ matrix.platform_tag }}" \
|
||||
--tag "${repo}:${version_tag}-${{ matrix.platform_tag }}" \
|
||||
--attest type=sbom \
|
||||
--attest type=provenance,mode=max \
|
||||
--push \
|
||||
./${{ matrix.image }}
|
||||
env:
|
||||
VERSION: ${{ needs.get-version.outputs.version }}
|
||||
IMAGE_VERSION: ${{ needs.get-version.outputs.image-version }}
|
||||
|
||||
create-container-manifests:
|
||||
name: Create Multi-Platform Container Manifests
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-version, build-and-push-containers]
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Log in to GitHub Container Registry
|
||||
env:
|
||||
GHCR_TOKEN: ${{ github.repository_owner == 'data-privacy-stack' && github.token || secrets.GHCR_TOKEN }}
|
||||
GHCR_USERNAME: ${{ github.repository_owner == 'data-privacy-stack' && github.actor || vars.GHCR_USERNAME || github.actor }}
|
||||
run: echo "${GHCR_TOKEN}" | docker login ${{ env.IMAGE_REGISTRY }} -u "${GHCR_USERNAME}" --password-stdin
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Create multi-platform manifests
|
||||
run: |
|
||||
images=(presidio-anonymizer presidio-analyzer presidio-image-redactor)
|
||||
platform_tags=(linux-amd64 linux-arm64)
|
||||
|
||||
for image in "${images[@]}"; do
|
||||
repo="${IMAGE_REGISTRY}/${IMAGE_NAMESPACE}/${image}"
|
||||
version_tag="${VERSION}"
|
||||
if [ "${image}" = "presidio-image-redactor" ]; then
|
||||
version_tag="${IMAGE_VERSION}"
|
||||
fi
|
||||
|
||||
for tag in latest "${version_tag}"; do
|
||||
platform_refs=()
|
||||
for platform_tag in "${platform_tags[@]}"; do
|
||||
platform_refs+=("${repo}:${tag}-${platform_tag}")
|
||||
done
|
||||
|
||||
docker buildx imagetools create \
|
||||
--tag "${repo}:${tag}" \
|
||||
"${platform_refs[@]}"
|
||||
done
|
||||
done
|
||||
env:
|
||||
VERSION: ${{ needs.get-version.outputs.version }}
|
||||
IMAGE_VERSION: ${{ needs.get-version.outputs.image-version }}
|
||||
uses: ./.github/workflows/build-images.yml
|
||||
with:
|
||||
version: ${{ needs.get-version.outputs.version }}
|
||||
image-version: ${{ needs.get-version.outputs.image-version }}
|
||||
secrets: inherit
|
||||
|
||||
Reference in New Issue
Block a user