-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
action.yml
302 lines (271 loc) · 11.6 KB
/
action.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
name: Build and Publish Chainlink
description: A composite action that allows building and publishing signed chainlink images.
inputs:
# Inputs for publishing
publish:
description: When set to the string boolean value of "true", the resulting built image will be published
default: "false"
required: false
dockerfile:
description: Path to the Dockerfile (relative to the repo root)
default: core/chainlink.Dockerfile
required: false
dockerhub_username:
description: Username for Docker Hub to avoid rate limits when pulling public images
required: false
dockerhub_password:
description: Password for Docker Hub to avoid rate limits when pulling public images
required: false
ecr-hostname:
description: The ECR registry scope
default: public.ecr.aws
required: false
ecr-image-name:
description: |
The image name with path, in the format of `[registry]/repository`. For private ECR repos the registry name is optional, where for public repos, it is required.
Eg. Public ECR repo `chainlink` and registry alias `chainlinklabs` should be `chainlinklabs/chainlink`. For a private ECR repo `chainlink` the image name should be `chainlink`
default: chainlink/chainlink
required: false
ecr-tag-suffix:
description: Docker image tag suffix
required: false
git-commit-sha:
description: Git commit SHA used as metadata when building the application (appears in logs)
default: ${{ github.event.pull_request.head.sha || github.sha }}
required: false
aws-role-to-assume:
description: The AWS role to assume as the CD user, if any. Used in configuring the docker/login-action
required: false
aws-role-duration-seconds:
description: The duration of the role assumed
required: false
aws-region:
description: The AWS region the ECR repository is located in, should only be needed for public ECR repositories, used in configuring docker/login-action
required: false
# Inputs for signing
sign-images:
description: When set to the string boolean value of "true", the resulting build image will be signed
default: "false"
required: false
cosign-private-key:
description: The private key to be used with cosign to sign the image
required: false
cosign-public-key:
description: The public key to be used with cosign for verification
required: false
cosign-password:
description: The password to decrypt the cosign private key needed to sign the image
required: false
sign-method:
description: Build image will be signed using keypair or keyless methods
default: "keypair"
required: true
verify-signature:
description: When set to the string boolean value of "true", the resulting build image signature will be verified
default: "false"
required: false
runs:
using: composite
steps:
- name: Set shared variables
shell: bash
# See https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#multiline-strings
run: |
SHARED_IMAGES=${{ inputs.ecr-hostname }}/${{ inputs.ecr-image-name }}
SHARED_TAG_LIST=$(cat << EOF
type=ref,event=branch,suffix=${{ inputs.ecr-tag-suffix }}
type=semver,pattern={{version}},suffix=${{ inputs.ecr-tag-suffix }}
type=sha,format=short,suffix=${{ inputs.ecr-tag-suffix }}
EOF
)
SHARED_BUILD_ARGS=$(cat << EOF
COMMIT_SHA=${{ inputs.git-commit-sha }}
EOF
)
echo "shared-images<<EOF" >> $GITHUB_ENV
echo "$SHARED_IMAGES" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
echo "shared-tag-list<<EOF" >> $GITHUB_ENV
echo "$SHARED_TAG_LIST" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
echo "shared-build-args<<EOF" >> $GITHUB_ENV
echo "$SHARED_BUILD_ARGS" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- if: inputs.publish == 'true'
# Log in to AWS for publish to ECR
name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
role-to-assume: ${{ inputs.aws-role-to-assume }}
role-duration-seconds: ${{ inputs.aws-role-duration-seconds }}
aws-region: ${{ inputs.aws-region }}
mask-aws-account-id: true
role-session-name: build-sign-publish-chainlink
- if: inputs.publish == 'true'
name: Login to ECR
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
with:
registry: ${{ inputs.ecr-hostname }}
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0
- name: Generate docker metadata for root image
id: meta-root
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
env:
DOCKER_METADATA_PR_HEAD_SHA: "true"
with:
# list of Docker images to use as base name for tags
images: ${{ env.shared-images }}
# XXX: DO NOT USE SHARED TAGS HERE
tags: |
type=ref,event=branch,suffix=${{ inputs.ecr-tag-suffix }}-root
type=semver,pattern={{version}},suffix=${{ inputs.ecr-tag-suffix }}-root
type=sha,format=short,suffix=${{ inputs.ecr-tag-suffix }}-root
# To avoid rate limiting from Docker Hub, we login with a paid user account.
- name: Login to Docker Hub
if: inputs.dockerhub_username && inputs.dockerhub_password
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
with:
username: ${{ inputs.dockerhub_username }}
password: ${{ inputs.dockerhub_password }}
- name: Build and push root docker image
id: buildpush-root
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
with:
push: ${{ inputs.publish }}
context: .
load: ${{ contains(inputs.publish, false) }}
tags: ${{ steps.meta-root.outputs.tags }}
labels: ${{ steps.meta-root.outputs.labels }}
file: ${{ inputs.dockerfile }}
build-args: |
CHAINLINK_USER=root
${{ env.shared-build-args }}
- name: Save root image name in GITHUB_ENV
id: save-root-image-name-env
shell: sh
run: |
IMAGES_NAME_RAW=${{ fromJSON(steps.buildpush-root.outputs.metadata)['image.name'] }}
IMAGE_NAME=$(echo "$IMAGES_NAME_RAW" | cut -d"," -f1)
echo "root_image_name=${IMAGE_NAME}" >> $GITHUB_ENV
- name: Generate docker metadata for non-root image
id: meta-nonroot
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
env:
DOCKER_METADATA_PR_HEAD_SHA: "true"
with:
flavor: |
latest=auto
prefix=
suffix=
images: ${{ env.shared-images }}
tags: ${{ env.shared-tag-list }}
# To avoid rate limiting from Docker Hub, we login with a paid user account.
- name: Login to Docker Hub
if: inputs.dockerhub_username && inputs.dockerhub_password
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
with:
username: ${{ inputs.dockerhub_username }}
password: ${{ inputs.dockerhub_password }}
- name: Build and push non-root docker image
id: buildpush-nonroot
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
with:
push: ${{ inputs.publish }}
context: .
load: ${{ contains(inputs.publish, false) }}
tags: ${{ steps.meta-nonroot.outputs.tags }}
labels: ${{ steps.meta-nonroot.outputs.labels }}
file: ${{ inputs.dockerfile }}
build-args: |
CHAINLINK_USER=chainlink
${{ env.shared-build-args }}
- name: Save non-root image name in GITHUB_ENV and GITHUB_STEP_SUMMARY
id: save-non-root-image-name-env
shell: sh
run: |
IMAGES_NAME_RAW=${{ fromJSON(steps.buildpush-nonroot.outputs.metadata)['image.name'] }}
IMAGE_DIGEST=${{ fromJSON(steps.buildpush-nonroot.outputs.metadata)['containerimage.digest'] }}
IMAGE_NAME=$(echo "$IMAGES_NAME_RAW" | cut -d"," -f1)
echo "nonroot_image_name=${IMAGE_NAME}" >> $GITHUB_ENV
echo '### Docker Image' >> $GITHUB_STEP_SUMMARY
echo "Image Name: ${IMAGE_NAME}" >> $GITHUB_STEP_SUMMARY
echo "Image Digest: ${IMAGE_DIGEST}" >> $GITHUB_STEP_SUMMARY
- name: Check if non-root image runs as root
id: check-nonroot-runs-root
shell: sh
env:
PUBLISH: ${{ inputs.publish }}
run: |
echo "Fail build if non-root image runs as user: root"
# if we're publishing the image, it doesn't get loaded into the local docker daemon
# so we need to pull the image into our daemon
if [ $PUBLISH = "true" ]; then
docker pull "${nonroot_image_name}"
fi
docker inspect "${nonroot_image_name}" | jq -r '.[].Config.User' | ( ! grep "root" )
- if: inputs.sign-images == 'true'
name: Install cosign
uses: sigstore/cosign-installer@e1523de7571e31dbe865fd2e80c5c7c23ae71eb4 # v3.4.0
with:
cosign-release: "v1.6.0"
- if: inputs.sign-images == 'true' && inputs.sign-method == 'keypair'
name: Sign the published root Docker image using keypair method
shell: sh
env:
COSIGN_PASSWORD: "${{ inputs.cosign-password }}"
run: |
echo "${{ inputs.cosign-private-key }}" > cosign.key
cosign sign --key cosign.key "${{ env.root_image_name }}"
rm -f cosign.key
- if: inputs.verify-signature == 'true' && inputs.sign-method == 'keypair'
name: Verify the signature of the published root Docker image using keypair
shell: sh
run: |
echo "${{ inputs.cosign-public-key }}" > cosign.key
cosign verify --key cosign.key "${{ env.root_image_name }}"
rm -f cosign.key
- if: inputs.sign-images == 'true' && inputs.sign-method == 'keyless'
name: Sign the published root Docker image using keyless method
shell: sh
env:
COSIGN_EXPERIMENTAL: 1
run: |
cosign sign "${{ env.root_image_name }}"
- if: inputs.verify-signature == 'true' && inputs.sign-method == 'keyless'
name: Verify the signature of the published root Docker image using keyless
shell: sh
env:
COSIGN_EXPERIMENTAL: 1
run: |
cosign verify "${{ env.root_image_name }}"
- if: inputs.sign-images == 'true' && inputs.sign-method == 'keypair'
name: Sign the published non-root Docker image using keypair method
shell: sh
env:
COSIGN_PASSWORD: "${{ inputs.cosign-password }}"
run: |
echo "${{ inputs.cosign-private-key }}" > cosign.key
cosign sign --key cosign.key "${{ env.nonroot_image_name }}"
rm -f cosign.key
- if: inputs.verify-signature == 'true' && inputs.sign-method == 'keypair'
name: Verify the signature of the published non-root Docker image using keypair
shell: sh
run: |
echo "${{ inputs.cosign-public-key }}" > cosign.key
cosign verify --key cosign.key "${{ env.nonroot_image_name }}"
rm -f cosign.key
- if: inputs.sign-images == 'true' && inputs.sign-method == 'keyless'
name: Sign the published non-root Docker image using keyless method
shell: sh
env:
COSIGN_EXPERIMENTAL: 1
run: |
cosign sign "${{ env.nonroot_image_name }}"
- if: inputs.verify-signature == 'true' && inputs.sign-method == 'keyless'
name: Verify the signature of the published non-root Docker image using keyless
shell: sh
env:
COSIGN_EXPERIMENTAL: 1
run: |
cosign verify "${{ env.nonroot_image_name }}"