-
Notifications
You must be signed in to change notification settings - Fork 2
197 lines (177 loc) · 6.93 KB
/
docker-build.yml
File metadata and controls
197 lines (177 loc) · 6.93 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
name: Build and Push Docker Image
on:
push:
branches:
- main
release:
types: [published, created]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
permissions:
contents: read
packages: write
jobs:
# Classify push so release-please-only merges can retag the last code image instead of rebuilding.
changes:
runs-on: ubuntu-latest
outputs:
build_code: ${{ steps.result.outputs.build_code }}
release_bump: ${{ steps.result.outputs.release_bump }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Paths filter (push to main only)
if: github.event_name == 'push'
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d
id: filter
with:
filters: |
build_code:
- 'src/**'
- 'scripts/**'
- 'Dockerfile'
release_bump:
- 'package.json'
- 'CHANGELOG.md'
- name: Emit change flags
id: result
run: |
if [ "${{ github.event_name }}" = "release" ]; then
echo "build_code=true" >> "$GITHUB_OUTPUT"
echo "release_bump=false" >> "$GITHUB_OUTPUT"
else
echo "build_code=${{ steps.filter.outputs.build_code }}" >> "$GITHUB_OUTPUT"
echo "release_bump=${{ steps.filter.outputs.release_bump }}" >> "$GITHUB_OUTPUT"
fi
build-and-push:
needs: changes
if: >-
github.event_name == 'release'
|| (
github.event_name == 'push'
&& needs.changes.outputs.build_code == 'true'
)
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
- name: Log in to Container Registry
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,prefix=sha-
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=main,enable={{is_default_branch}}
flavor: |
latest=auto
labels: |
org.opencontainers.image.title={{repo}}
org.opencontainers.image.description={{description}}
org.opencontainers.image.vendor={{vendor}}
org.opencontainers.image.version={{version}}
org.opencontainers.image.revision={{sha}}
org.opencontainers.image.created={{created}}
- name: Build and push Docker image
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# After release-please merges (version/changelog only), point semver + merge SHA tags at the
# same image as the last commit that actually got a build (github.event.before may be a
# release-only merge with no sha-* tag in GHCR — walk first-parent chain until crane finds one).
retag-release-image:
needs: changes
if: >-
github.event_name == 'push'
&& needs.changes.outputs.build_code != 'true'
&& needs.changes.outputs.release_bump == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
- name: Log in to Container Registry
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Install crane
env:
CRANE_VERSION: v0.20.3
run: |
set -euo pipefail
curl -sSL "https://github.com/google/go-containerregistry/releases/download/${CRANE_VERSION}/go-containerregistry_Linux_x86_64.tar.gz" \
| sudo tar -xz -C /usr/local/bin crane
crane version
- name: Retag existing image with release version and merge SHA
env:
BEFORE_SHA: ${{ github.event.before }}
MERGE_SHA: ${{ github.sha }}
run: |
set -euo pipefail
if [ "$BEFORE_SHA" = "0000000000000000000000000000000000000000" ]; then
echo "::error::github.event.before is empty; cannot locate the pre-merge image to retag."
exit 1
fi
MERGE_TAG="sha-${MERGE_SHA:0:7}"
VERSION="$(node -p "require('./package.json').version")"
# Strip prerelease/build for x.y rolling tags (same idea as docker/metadata semver flavor)
BASE="${VERSION%%-*}"
MAJOR="${BASE%%.*}"
REST="${BASE#*.}"
MINOR="${REST%%.*}"
IMAGE_LC="$(echo "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" | tr '[:upper:]' '[:lower:]')"
# BEFORE_SHA often has no image (release-only / docs-only commits). Walk first-parent
# chain until we find a sha-* tag that exists in GHCR (matches docker/metadata).
CURRENT="$BEFORE_SHA"
MAX_WALK=50
SRC_REF=""
for _ in $(seq 1 "$MAX_WALK"); do
TAG="sha-${CURRENT:0:7}"
REF="${IMAGE_LC}:${TAG}"
if crane digest "$REF" >/dev/null 2>&1; then
SRC_REF="$REF"
echo "Using existing image tag $TAG (commit $CURRENT) as retag source."
break
fi
echo "No image for $TAG, walking parent..."
CURRENT="$(git rev-parse "${CURRENT}^" 2>/dev/null)" || break
done
if [ -z "$SRC_REF" ]; then
echo "::error::No sha-* tag found in GHCR walking back up to $MAX_WALK commits from $BEFORE_SHA. Push a change that runs build-and-push on main, then retry the release merge."
exit 1
fi
mapfile -t NEW_TAGS < <(printf '%s\n' \
"$VERSION" \
"${MAJOR}.${MINOR}" \
"$MAJOR" \
"$MERGE_TAG" \
latest \
main | awk 'NF && !seen[$0]++')
for t in "${NEW_TAGS[@]}"; do
echo "Tagging ${SRC_REF} -> ${IMAGE_LC}:${t}"
crane copy "$SRC_REF" "${IMAGE_LC}:${t}"
done
echo "Retag complete for: ${NEW_TAGS[*]}"