-
-
Notifications
You must be signed in to change notification settings - Fork 162
133 lines (123 loc) · 4.95 KB
/
Copy pathdocker-build-release.yml
File metadata and controls
133 lines (123 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
name: Docker Build and Publish (Tagged Release)
on:
release:
types:
- published
env:
REGISTRY: ghcr.io
IMAGE_PREFIX: ${{ github.repository_owner }}/opencontractserver
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
strategy:
matrix:
include:
- image: django
context: .
dockerfile: ./compose/production/django/Dockerfile
- image: frontend
context: ./frontend
dockerfile: ./frontend/Dockerfile
- image: postgres
context: .
dockerfile: ./compose/production/postgres/Dockerfile
- image: traefik
context: .
dockerfile: ./compose/production/traefik/Dockerfile
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to GitHub Container Registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}_${{ matrix.image }}
tags: |
type=ref,event=tag
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,prefix={{tag}}-
# Django gets a two-step build: first build+load locally so the image
# is on the daemon for the size-budget gate, then `docker push` each
# tag separately. This is split intentionally — combining `load: true`
# with `push: true` in a single `docker/build-push-action` step works
# only on single-platform builds, is not well-documented across Buildx
# versions, and some runner/daemon configurations reject it. Splitting
# makes the contract explicit and resilient to future runner changes.
- name: Build Django image (load locally for size budget gate)
if: matrix.image == 'django'
uses: docker/build-push-action@v7
with:
context: ${{ matrix.context }}
file: ${{ matrix.dockerfile }}
push: false
load: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64
build-args: |
BUILD_ENVIRONMENT=production
# Image-size budget for the Django/Celery image (issue #1494). The
# uncompressed image must fit under DJANGO_IMAGE_BUDGET_BYTES; we fail
# the release build otherwise so regressions surface immediately rather
# than at the next cold pod pull.
- name: Enforce Django image size budget
if: matrix.image == 'django'
env:
# 1.5 GiB budget per acceptance criteria on issue #1494.
DJANGO_IMAGE_BUDGET_BYTES: "1610612736"
run: |
set -euo pipefail
first_tag="$(echo '${{ steps.meta.outputs.tags }}' | head -n1)"
size_bytes="$(docker image inspect --format='{{.Size}}' "$first_tag")"
budget="$DJANGO_IMAGE_BUDGET_BYTES"
human_size="$(numfmt --to=iec-i --suffix=B "$size_bytes")"
human_budget="$(numfmt --to=iec-i --suffix=B "$budget")"
echo "Django image size: $human_size ($size_bytes bytes)"
echo "Budget: $human_budget ($budget bytes)"
if [ "$size_bytes" -gt "$budget" ]; then
echo "::error::Django image $human_size exceeds the $human_budget budget. See issue #1494."
exit 1
fi
# Push only after the size gate passes. Each tag in steps.meta.outputs.tags
# already points at the image loaded above (same reference Buildx tagged
# locally), so `docker push <tag>` re-uses the local layers — no rebuild.
- name: Push Django image to registry
if: matrix.image == 'django'
run: |
set -euo pipefail
while IFS= read -r tag; do
[ -z "$tag" ] && continue
echo "Pushing $tag"
docker push "$tag"
done <<< "${{ steps.meta.outputs.tags }}"
# Non-Django images do not have a size budget today, so the original
# combined build-and-push path stays — no `load` involved.
- name: Build and push non-Django image
if: matrix.image != 'django'
uses: docker/build-push-action@v7
with:
context: ${{ matrix.context }}
file: ${{ matrix.dockerfile }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64
build-args: |
BUILD_ENVIRONMENT=production