env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository_owner }}/caddy-l4 name: Build caddy-l4 on: workflow_dispatch: push: branches: - main paths: - docker/DockerfileCaddyL4 - docker/entrypoint-caddy.sh - docker/caddy-compat-normalize.awk - docker/caddy-l4.version - docker/test-caddy-compat.sh - Caddyfile # The version check below reads the pin out of docker-compose.yml, so a # compose-only bump has to trigger this workflow or the check never runs. - docker-compose.yml - .github/workflows/build-caddy-l4-image.yml permissions: write-all jobs: build_ee: runs-on: ubicloud steps: - uses: actions/checkout@v4 - uses: depot/setup-action@v1 # docker-compose.yml pins an exact tag, and the Caddyfile it must agree # with lives in the same checkout. Fail the build rather than publish a # version nothing references, which is how :latest drifted from the # Caddyfile in the first place. - name: Resolve and check image version id: version run: | set -euo pipefail version="$(tr -d '[:space:]' < docker/caddy-l4.version)" pinned="$(grep -oE 'caddy-l4:[^[:space:]"]+' docker-compose.yml | head -1 | cut -d: -f2-)" caddy="$(grep -m1 -oE '^FROM caddy:[0-9]+\.[0-9]+\.[0-9]+' docker/DockerfileCaddyL4 | cut -d: -f2)" if [ "$version" != "$pinned" ]; then echo "docker/caddy-l4.version is '$version' but docker-compose.yml pins '$pinned'" >&2 echo "Bump both together." >&2 exit 1 fi # Otherwise a caddy bump that forgets the version file publishes a tag # that names the wrong caddy. case "$version" in "$caddy"-*) ;; *) echo "docker/caddy-l4.version is '$version' but the Dockerfile pins caddy '$caddy'" >&2 echo "The version must be -." >&2 exit 1 ;; esac echo "version=$version" >> "$GITHUB_OUTPUT" - name: Docker meta id: meta-ee-public uses: docker/metadata-action@v5 with: images: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=sha type=ref,event=branch # Not gated on the default branch: docker-compose.yml pins this tag, # so it has to be publishable from a branch (workflow_dispatch) # before the pin merges, or main would reference a tag that does not # exist yet. The version is immutable, so republishing from main is # a no-op. Only branch pushes to main and manual dispatch run this # workflow, so a branch cannot claim the tag by accident. type=raw,value=${{ steps.version.outputs.version }} type=raw,value=latest,enable={{is_default_branch}} # The shim rewrites config a self-hoster never sees, so a silent # regression here strands them on a restart loop or a dead :80. - name: Test the legacy-Caddyfile compatibility shim run: | docker build -f docker/DockerfileCaddyL4 -t caddy-l4:ci ./docker docker/test-caddy-compat.sh caddy-l4:ci - name: Login to registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push publicly uses: depot/build-push-action@v1 with: context: ./docker file: ./docker/DockerfileCaddyL4 platforms: linux/amd64,linux/arm64 push: true tags: | ${{ steps.meta-ee-public.outputs.tags }} labels: | ${{ steps.meta-ee-public.outputs.labels }}