-
Notifications
You must be signed in to change notification settings - Fork 0
425 lines (391 loc) · 14.8 KB
/
build-ecr-image.yml
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
---
name: 'Build docker image for ECR'
on:
workflow_call:
inputs:
ref:
description: 'The branch/sha/tag to build from'
type: string
default: ''
repository-name:
description: 'The name of the ecr repository to push the docker image to'
type: string
required: true
aws-region:
description: 'The aws region where resources live'
type: string
default: us-east-1
role-name:
description: 'The name of the IAM role allowed to upload the ECR repository'
type: string
required: true
skip-if-exists:
description: 'If true, skips all build steps if the image already exists. This is helpful for immutable ECR repositories'
type: boolean
default: false
# begin docker/setup-buildx-action inputs
buildx-version:
description: 'Buildx version. (eg. v0.3.0)'
required: false
type: string
driver:
description: 'Sets the builder driver to be used'
default: 'docker-container'
required: false
type: string
driver-opts:
description: 'List of additional driver-specific options. (eg. image=moby/buildkit:master)'
required: false
type: string
buildkitd-flags:
description: 'Flags for buildkitd daemon'
default: '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host'
required: false
type: string
install:
description: 'Sets up docker build command as an alias to docker buildx build'
default: 'false'
required: false
type: string
use:
description: 'Switch to this builder instance'
default: 'true'
required: false
type: string
endpoint:
description: 'Optional address for docker socket or context from `docker context ls`'
required: false
type: string
platforms:
description: 'Fixed platforms for current node. If not empty, values take priority over the detected ones'
required: false
type: string
config:
description: 'BuildKit config file'
required: false
type: string
config-inline:
description: 'Inline BuildKit config'
required: false
type: string
append:
description: 'Append additional nodes to the builder'
required: false
type: string
# end docker/setup-buildx-action inputs
# begin docker/build-push-action inputs
add-hosts:
description: "List of a customs host-to-IP mapping (e.g., docker:10.180.0.1)"
required: false
type: string
allow:
description: "List of extra privileged entitlement (e.g., network.host,security.insecure)"
required: false
type: string
attests:
description: "List of attestation parameters (e.g., type=sbom,generator=image)"
required: false
type: string
build-args:
description: "List of build-time variables"
required: false
type: string
build-contexts:
description: "List of additional build contexts (e.g., name=path)"
required: false
type: string
builder:
description: "Builder instance"
required: false
type: string
cache-from:
description: "List of external cache sources for buildx (e.g., user/app:cache, type=local,src=path/to/dir)"
required: false
type: string
cache-to:
description: "List of cache export destinations for buildx (e.g., user/app:cache, type=local,dest=path/to/dir)"
required: false
type: string
cgroup-parent:
description: "Optional parent cgroup for the container used in the build"
required: false
type: string
context:
description: "Build's context is the set of files located in the specified PATH or URL"
required: false
type: string
default: . # uses checkout ref
file:
description: "Path to the Dockerfile"
required: false
type: string
labels:
description: "List of metadata for an image"
required: false
type: string
load:
description: "Load is a shorthand for --output=type=docker"
required: false
default: 'false'
type: string
network:
description: "Set the networking mode for the RUN instructions during build"
required: false
type: string
no-cache:
description: "Do not use cache when building the image"
required: false
default: 'false'
type: string
no-cache-filters:
description: "Do not cache specified stages"
required: false
type: string
outputs:
description: "List of output destinations (format: type=local,dest=path)"
required: false
type: string
# duplicate from buildx action
# platforms:
# description: "List of target platforms for build"
# required: false
provenance:
description: "Generate provenance attestation for the build (shorthand for --attest=type=provenance)"
required: false
type: string
pull:
description: "Always attempt to pull all referenced images"
required: false
default: 'false'
type: string
push:
description: "Push is a shorthand for --output=type=registry"
required: false
default: 'true' # BD default
type: string
sbom:
description: "Generate SBOM attestation for the build (shorthand for --attest=type=sbom)"
required: false
type: string
secret-files:
description: "List of secret files to expose to the build (e.g., key=filename, MY_SECRET=./secret.txt)"
required: false
type: string
shm-size:
description: "Size of /dev/shm (e.g., 2g)"
required: false
type: string
ssh:
description: "List of SSH agent socket or keys to expose to the build"
required: false
type: string
tags:
description: "List of tags"
required: false
type: string
target:
description: "Sets the target stage to build"
required: false
type: string
ulimit:
description: "Ulimit options (e.g., nofile=1024:1024)"
required: false
type: string
# end docker/build-push-action inputs
# notify-slack
notify-slack:
description: 'Indicates if a slack notification should go out before and after the deploy'
type: boolean
default: false
application:
description: 'The name of the application; required if notify-slack is true'
type: string
required: false
slack-template:
description: 'The j2 template to pass to the notify-slack action'
type: string
required: false
secrets:
aws-account-id:
description: 'The AWS account id that the ecr repository lives under'
required: true
ssh-private-key:
description: 'If using private repositories for dependencies, the ssh key to add to the agent and pass along to the docker build'
required: false
secrets:
description: "List of secrets to expose to the build (e.g., key=string, GIT_AUTH_TOKEN=mytoken)"
required: false
github-token:
description: "GitHub Token used to authenticate against a repository for Git context"
required: false
slack-webhook-url:
description: 'The webhook URL to send the slack notification to; requires notify-slack to be true'
required: false
env:
DOCKER_IMAGE: ${{ secrets.aws-account-id }}.dkr.ecr.${{ inputs.aws-region }}.amazonaws.com/${{ inputs.repository-name }}
DEPLOY_IAM_ROLE: arn:aws:iam::${{ secrets.aws-account-id }}:role/${{ inputs.role-name }}
defaults:
run:
shell: bash
jobs:
build-docker-image:
name: 'Build docker image'
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@v4
with:
ref: ${{ inputs.ref }}
- name: 'Resolve sha from ref'
id: sha
run: |
sha="$(git rev-parse HEAD)"
echo "sha=$sha" >> $GITHUB_OUTPUT
- name: 'Configure AWS credentials'
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ inputs.aws-region }}
role-to-assume: ${{ env.DEPLOY_IAM_ROLE }}
role-duration-seconds: 1200
- name: 'Login to Amazon ECR'
uses: aws-actions/amazon-ecr-login@v2
- name: 'Check if the image already exists'
id: already-exists
run: |
# Do not error out if it does not exist
set +e
answer=false
aws ecr describe-images --output json --no-cli-pager \
--repository-name=${{ inputs.repository-name }} \
--image-ids=imageTag=${{ steps.sha.outputs.sha }}
if [ "$?" -eq 0 ]; then
answer=true
fi
echo "answer=$answer" >> "$GITHUB_OUTPUT"
- name: 'Notify slack of build started'
if: (inputs.skip-if-exists == false || steps.already-exists.outputs.answer == 'false') && inputs.notify-slack == true
uses: shopsmart/github-actions/actions/notify-slack@v4
with:
application: ${{ inputs.application }}
status: started
type: build
template: ${{ inputs.slack-template }}
version: ${{ inputs.ref || steps.sha.outputs.sha }}
slack-webhook-url: ${{ secrets.slack-webhook-url }}
- name: 'Is github release?'
id: is-gh-release
if: inputs.skip-if-exists == false || steps.already-exists.outputs.answer == 'false'
uses: shopsmart/github-actions/actions/is-gh-release@v4
with:
ref: ${{ inputs.ref }}
- name: 'If release, add additional tag'
id: additional-tag
if: inputs.skip-if-exists == false || steps.already-exists.outputs.answer == 'false'
run: |
additional_tag=''
if [[ "${{ steps.is-gh-release.outputs.is-release }}" == 'true' ]]; then
additional_tag="${{ env.DOCKER_IMAGE }}:${{ inputs.ref }}"
fi
echo "tag=$additional_tag" >> $GITHUB_OUTPUT
- name: 'If ssh private key provided, pass the default ssh agent'
id: ssh
if: inputs.skip-if-exists == false || steps.already-exists.outputs.answer == 'false'
run: |
ssh=''
if [ -n "${{ secrets.ssh-private-key }}" ]; then
ssh=default
fi
echo "ssh=$ssh" >> $GITHUB_OUTPUT
# for private dependencies
- name: 'Install SSH Key'
if: (inputs.skip-if-exists == false || steps.already-exists.outputs.answer == 'false') && steps.ssh.outputs.ssh != ''
uses: webfactory/[email protected]
with:
ssh-private-key: ${{ secrets.ssh-private-key }}
- name: 'Setup docker buildx'
if: inputs.skip-if-exists == false || steps.already-exists.outputs.answer == 'false'
uses: docker/setup-buildx-action@v3
with:
version: ${{ inputs.buildx-version }}
driver: ${{ inputs.driver }}
driver-opts: ${{ inputs.driver-opts }}
buildkitd-flags: ${{ inputs.buildkitd-flags }}
install: ${{ inputs.install }}
use: ${{ inputs.use }}
endpoint: ${{ inputs.endpoint }}
platforms: ${{ inputs.platforms }}
config: ${{ inputs.config }}
config-inline: ${{ inputs.config-inline }}
append: ${{ inputs.append }}
- name: 'Build docker image'
if: inputs.skip-if-exists == false || steps.already-exists.outputs.answer == 'false'
uses: docker/build-push-action@v6
with:
add-hosts: ${{ inputs.add-hosts }}
allow: ${{ inputs.allow }}
attests: ${{ inputs.attests }}
build-args: ${{ inputs.build-args }}
build-contexts: ${{ inputs.build-contexts }}
builder: ${{ inputs.builder }}
cache-from: ${{ inputs.cache-from }}
cache-to: ${{ inputs.cache-to }}
cgroup-parent: ${{ inputs.cgroup-parent }}
context: ${{ inputs.context }}
file: ${{ inputs.file }}
labels: |
github.sha=${{ steps.sha.outputs.sha }}
github.ref=${{ inputs.ref }}
${{ inputs.labels }}
load: ${{ inputs.load }}
network: ${{ inputs.network }}
no-cache: ${{ inputs.no-cache }}
no-cache-filters: ${{ inputs.no-cache-filters }}
outputs: ${{ inputs.outputs }}
platforms: ${{ inputs.platforms }}
provenance: ${{ inputs.provenance }}
pull: ${{ inputs.pull }}
push: ${{ inputs.push }}
sbom: ${{ inputs.sbom }}
secrets: |
GIT_AUTH_TOKEN=${{ secrets.github-token || github.token }}
${{ secrets.secrets }}
secret-files: ${{ inputs.secret-files }}
shm-size: ${{ inputs.shm-size }}
ssh: |
${{ steps.ssh.outputs.ssh }}
${{ inputs.ssh }}
tags: |
${{ env.DOCKER_IMAGE }}:${{ steps.sha.outputs.sha }}
${{ steps.additional-tag.outputs.tag }}
${{ inputs.tags }}
target: ${{ inputs.target }}
ulimit: ${{ inputs.ulimit }}
github-token: ${{ secrets.github-token || github.token }}
- name: 'Pull and package docker image'
if: (inputs.skip-if-exists == false || steps.already-exists.outputs.answer == 'false') && steps.is-gh-release.outputs.is-release == 'true'
env:
NAME: ${{ inputs.repository-name }}
IMAGE: ${{ env.DOCKER_IMAGE }}:${{ steps.sha.outputs.sha }}
TAG: ${{ inputs.ref }}
run: |
set -eo pipefail
echo "[INFO ] Exporting $IMAGE and zipping to docker-image-$NAME-$TAG.tgz" >&2
docker pull "$IMAGE"
docker save "$IMAGE" | gzip > "docker-image-$NAME-$TAG.tgz"
- name: 'Upload docker image'
if: (inputs.skip-if-exists == false || steps.already-exists.outputs.answer == 'false') && steps.is-gh-release.outputs.is-release == 'true'
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ inputs.ref }}
files: docker-image-*.tgz
token: ${{ secrets.github-token || github.token }}
- name: 'Notify slack of build status'
if: always() && (inputs.skip-if-exists == false || steps.already-exists.outputs.answer == 'false') && inputs.notify-slack == true
uses: shopsmart/github-actions/actions/notify-slack@v4
with:
application: ${{ inputs.application }}
status: ${{ job.status }}
type: build
template: ${{ inputs.slack-template }}
version: ${{ inputs.ref || steps.sha.outputs.sha }}
slack-webhook-url: ${{ secrets.slack-webhook-url }}