Fixed error: "docker exporter does not currently support exporting manifest lists" The issue occurred because SBOM and provenance attestations create manifest lists, which cannot be loaded to the local Docker daemon (required for PRs). Changes: - Made sbom conditional: only enabled for push events (not PRs) - Made provenance conditional: only enabled for push events (not PRs) - PRs now build without attestations (faster, avoids manifest list error) - Production pushes still get full SBOM and provenance attestations This allows: - PR builds to complete successfully with load=true - Production builds to maintain supply chain security features
117 lines
4.1 KiB
YAML
117 lines
4.1 KiB
YAML
name: Build and Push Docker Images
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
- develop
|
|
tags:
|
|
- 'v*'
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
- develop
|
|
pull_request_target:
|
|
types: [labeled]
|
|
workflow_dispatch:
|
|
|
|
env:
|
|
REGISTRY: ghcr.io
|
|
IMAGE_NAME: ${{ github.repository }}
|
|
|
|
jobs:
|
|
# Security check for fork PRs
|
|
security-check:
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'pull_request'
|
|
permissions:
|
|
pull-requests: read
|
|
outputs:
|
|
is_fork: ${{ steps.check.outputs.is_fork }}
|
|
steps:
|
|
- name: Check if PR is from fork
|
|
id: check
|
|
run: |
|
|
if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then
|
|
echo "is_fork=true" >> $GITHUB_OUTPUT
|
|
echo "::warning::This PR is from a fork. Builds from forks require manual approval for security."
|
|
else
|
|
echo "is_fork=false" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
build-and-push:
|
|
needs: security-check
|
|
# Run on push/tag events (security-check is skipped but that's ok)
|
|
# For PRs, only run on non-fork PRs or manually approved fork PRs
|
|
if: |
|
|
always() && (
|
|
github.event_name == 'push' ||
|
|
github.event_name == 'workflow_dispatch' ||
|
|
(github.event_name == 'pull_request' && needs.security-check.result == 'success' && needs.security-check.outputs.is_fork == 'false') ||
|
|
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-build'))
|
|
)
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- service: web
|
|
dockerfile: docker/web/Dockerfile
|
|
context: .
|
|
- service: caddy
|
|
dockerfile: docker/caddy/Dockerfile
|
|
context: .
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
# For pull_request_target, checkout the PR head
|
|
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || '' }}
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Log in to GitHub Container Registry
|
|
if: github.event_name != 'pull_request' && github.event_name != 'pull_request_target'
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Extract metadata (tags, labels)
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-${{ matrix.service }}
|
|
tags: |
|
|
type=ref,event=branch
|
|
type=ref,event=pr
|
|
type=semver,pattern={{version}}
|
|
type=semver,pattern={{major}}.{{minor}}
|
|
type=semver,pattern={{major}}
|
|
type=sha
|
|
type=raw,value=latest,enable={{is_default_branch}}
|
|
|
|
- name: Build and push Docker image
|
|
id: build
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: ${{ matrix.context }}
|
|
file: ${{ matrix.dockerfile }}
|
|
push: ${{ github.event_name != 'pull_request' && github.event_name != 'pull_request_target' }}
|
|
load: ${{ github.event_name == 'pull_request' || github.event_name == 'pull_request_target' }}
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
# Only specify platforms for push (multi-platform), not for load (single-platform only)
|
|
platforms: ${{ (github.event_name != 'pull_request' && github.event_name != 'pull_request_target') && 'linux/amd64,linux/arm64' || '' }}
|
|
# SBOM and provenance create manifest lists, incompatible with load (PRs)
|
|
sbom: ${{ github.event_name != 'pull_request' && github.event_name != 'pull_request_target' }}
|
|
provenance: ${{ github.event_name != 'pull_request' && github.event_name != 'pull_request_target' }}
|