Skip to content

chore(deps): update all digest updates (#665) #402

chore(deps): update all digest updates (#665)

chore(deps): update all digest updates (#665) #402

Workflow file for this run

name: Build and test application
on:
push:
branches:
- main
- next
tags: [v*]
pull_request:
paths:
- ".env.dist"
- ".github/workflows/build.yml"
- "bin/**"
- "deploy/**"
- "docker-compose*.yml"
- "kustomization.yaml"
- "Makefile"
- "target/**"
- "test/**"
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
env:
ADDITIONAL_DOCKER_IMAGES: "mysql:lts axllent/mailpit:v1.27 redis:8-alpine"
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
include:
- context: target/mda
image: mailserver-mda
- context: target/mta
image: mailserver-mta
- context: target/filter
image: mailserver-filter
- context: target/web
image: mailserver-web
- context: target/ssl
image: mailserver-ssl
- context: target/unbound
image: mailserver-unbound
- context: test/bats
image: mailserver-test
permissions:
contents: read
packages: write
id-token: write
attestations: write
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
- name: Set up QEMU
if: ${{ github.event_name != 'pull_request' }}
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Log in to Container Registry (ghcr.io)
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to Container Registry (docker.io)
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3
with:
username: ${{ vars.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Cache Docker layers
uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5
with:
path: ${{ runner.temp }}/.buildx-cache
key: ${{ runner.os }}-buildx-${{ matrix.image }}-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-${{ matrix.image }}-${{ github.ref }}-
${{ runner.os }}-buildx-${{ matrix.image }}-
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: |
ghcr.io/jeboehm/${{ matrix.image }}
jeboehm/${{ matrix.image }}
tags: |
type=schedule
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
- name: Create banner
run: .github/bin/create_banner.sh ${{ github.sha }} ${{ github.ref_name }}
- name: Build and push Docker image
if: ${{ github.event_name != 'pull_request' }}
id: build-and-push
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: ${{ matrix.context }}
platforms: linux/amd64,linux/arm64
push: ${{ matrix.image != 'mailserver-test' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=local,src=${{ runner.temp }}/.buildx-cache
cache-to: type=local,dest=${{ runner.temp }}/.buildx-cache-new,mode=max
- name: Build Docker image
if: ${{ github.event_name == 'pull_request' }}
id: build-and-save
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: ${{ matrix.context }}
push: false
tags: jeboehm/${{ matrix.image }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=local,src=${{ runner.temp }}/.buildx-cache
cache-to: type=local,dest=${{ runner.temp }}/.buildx-cache-new,mode=max
outputs: type=docker,dest=${{ runner.temp }}/${{ matrix.image }}.tar
- # Temp fix
# https://github.com/docker/build-push-action/issues/252
# https://github.com/moby/buildkit/issues/1896
name: Move cache
run: |
rm -rf ${{ runner.temp }}/.buildx-cache
mv ${{ runner.temp }}/.buildx-cache-new ${{ runner.temp }}/.buildx-cache
- name: Generate artifact attestation (ghcr.io)
if: ${{ github.event_name != 'pull_request' && matrix.image != 'mailserver-test' }}
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3
with:
subject-name: ghcr.io/jeboehm/${{ matrix.image }}
subject-digest: ${{ steps.build-and-push.outputs.digest }}
push-to-registry: true
- name: Generate artifact attestation (docker.io)
if: ${{ github.event_name != 'pull_request' && matrix.image != 'mailserver-test' }}
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3
with:
subject-name: index.docker.io/jeboehm/${{ matrix.image }}
subject-digest: ${{ steps.build-and-push.outputs.digest }}
push-to-registry: true
- name: Upload Docker image to artifacts
if: ${{ github.event_name == 'pull_request' }}
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: docker-image-${{ matrix.image }}
path: ${{ runner.temp }}/${{ matrix.image }}.tar
retention-days: 1
test_container_image_efficiency:
needs: build
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-latest
env:
CI: "true"
DIVE_VERSION: 0.13.1 # renovate: depName=wagoodman/dive
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
- name: Download Docker image artifacts
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
with:
path: images
pattern: docker-image-*
merge-multiple: true
- name: Install Dive
run: |
curl -sfOL "https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}/dive_${DIVE_VERSION}_linux_amd64.deb"
sudo dpkg -i ./dive_${DIVE_VERSION}_linux_amd64.deb
- name: Check container image efficiency
run: |
for image in $(ls images/); do
echo "::group::Checking image ${image}"
dive --ci-config .github/linters/.dive-ci.yml docker-archive://images/${image}
echo "::endgroup::"
done
test_docker_matrix:
needs: build
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-latest
strategy:
matrix:
TEST_CASE:
- default
- relayhost
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
- name: Download Docker image artifacts
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
with:
path: images
pattern: docker-image-*
merge-multiple: true
- name: Docker load downloaded image artifacts
run: |
for image in $(ls images/); do
docker load --input images/${image}
done
- name: Cache Docker images
uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5
id: docker-images-cache
with:
path: /tmp/docker-images
key: ${{ runner.os }}-images-additional-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-images-additional-${{ github.ref }}-
${{ runner.os }}-images-additional-
- name: Load or pull Docker images
run: |
mkdir -p /tmp/docker-images
read -a IMAGES <<< "${{ env.ADDITIONAL_DOCKER_IMAGES }}"
for IMAGE in "${IMAGES[@]}"; do
# Convert image name to filename-safe format
FILENAME=$(echo "$IMAGE" | tr '/:' '-').tar
CACHE_PATH="/tmp/docker-images/$FILENAME"
if [ -f "$CACHE_PATH" ]; then
echo "::group::Loading $IMAGE from cache"
docker load --input "$CACHE_PATH"
echo "::endgroup::"
else
echo "::group::Pulling $IMAGE from registry"
docker pull "$IMAGE"
docker save "$IMAGE" -o "$CACHE_PATH"
echo "::endgroup::"
fi
done
- name: Prepare environment
run: |
make .env
cat .env .github/test-matrix/${{ matrix.TEST_CASE }}.env > .env.tmp
awk -F= '{seen[$1]=$0} END {for (key in seen) print seen[key]}' .env.tmp > .env
rm .env.tmp
- name: Output environment
run: cat .env
- name: Start components
run: make up
- name: Load database fixtures
run: make fixtures
- name: Run tests
run: bin/test.sh run --rm test
- name: Collect logs
if: failure()
run: |
make logs
docker ps -a
test_kubernetes_matrix:
needs: build
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-latest
env:
CLUSTER_NAME: kind
POPEYE_VERSION: v0.22.1 # renovate: depName=derailed/popeye
strategy:
matrix:
TEST_CASE:
- default
- relayhost
- proxy
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
- name: Setup Kind
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1
with:
cluster_name: ${{ env.CLUSTER_NAME }}
- name: Install Popeye
run: |
curl -sfOL https://github.com/derailed/popeye/releases/download/${{ env.POPEYE_VERSION }}/popeye_linux_amd64.deb
sudo dpkg -i popeye_linux_amd64.deb
- name: Use kubectl context
run: |
kind get clusters
kubectl config use-context kind-${{ env.CLUSTER_NAME }}
- name: Restore cached Docker images
uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5
id: docker-images-cache
with:
path: /tmp/docker-images
key: ${{ runner.os }}-images-additional-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-images-additional-${{ github.ref }}-
${{ runner.os }}-images-additional-
- name: Load cached Docker images
if: steps.docker-images-cache.outputs.cache-hit == 'true'
run: |
read -a IMAGES <<< "${{ env.ADDITIONAL_DOCKER_IMAGES }}"
for IMAGE in "${IMAGES[@]}"; do
FILENAME=$(echo "$IMAGE" | tr '/:' '-').tar
CACHE_PATH="/tmp/docker-images/$FILENAME"
if [ -f "$CACHE_PATH" ]; then
echo "::group::Loading $IMAGE from cache into kind cluster"
kind load image-archive "$CACHE_PATH"
echo "::endgroup::"
fi
done
- name: Download docker image artifacts
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
with:
path: images
pattern: docker-image-*
merge-multiple: true
- name: Load downloaded docker images
run: |
for image in $(ls images/); do
echo "::group::Loading $image from downloaded artifacts into kind cluster"
kind load image-archive images/${image}
echo "::endgroup::"
done
- name: Prepare environment
run: |
make .env
cat .env .github/test-matrix/${{ matrix.TEST_CASE }}.env > .env.tmp
awk -F= '{seen[$1]=$0} END {for (key in seen) print seen[key]}' .env.tmp > .env
rm .env.tmp
- name: Prepare tls certs
run: make kubernetes-tls
- name: Deploy Kubernetes resources
run: make kubernetes-deploy-helper kubernetes-up
- name: Wait for all pods to be ready
run: make kubernetes-wait
- name: Run tests
run: make kubernetes-test
- name: Run Popeye
run: make popeye-score
- name: Get pod status on failure
if: failure()
run: |
make kubernetes-logs
kubectl get pods -o wide
test_trivy_vulnerabilities:
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
include:
- image: mailserver-mda
- image: mailserver-mta
- image: mailserver-filter
- image: mailserver-web
- image: mailserver-ssl
- image: mailserver-unbound
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
- name: Download Docker image artifacts
if: ${{ github.event_name == 'pull_request' }}
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
with:
path: images
pattern: docker-image-${{ matrix.image }}
merge-multiple: true
- name: Run Trivy vulnerability scanner
if: ${{ github.event_name == 'pull_request' }}
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1
with:
input: "images/${{ matrix.image }}.tar"
format: "sarif"
output: "trivy-results.sarif"
severity: "CRITICAL,HIGH"
- name: Log in to Container Registry (ghcr.io)
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Run Trivy vulnerability scanner
if: ${{ github.event_name != 'pull_request' }}
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1
with:
image-ref: "ghcr.io/jeboehm/${{ matrix.image }}:latest"
format: "sarif"
output: "trivy-results.sarif"
severity: "CRITICAL,HIGH"
- name: Upload Trivy scan results to GitHub Security tab
if: always()
uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4
with:
sarif_file: "trivy-results.sarif"
category: "${{ matrix.image }}"