-
Notifications
You must be signed in to change notification settings - Fork 245
286 lines (266 loc) · 16.2 KB
/
docker-images.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
# Workflows pertaining to the jsii/superchain Docker image
name: Docker Images
on:
merge_group: {}
pull_request:
branches: [main, release]
push:
branches: [main, release]
env:
DOCKER_BUILDKIT: 1
jobs:
superchain:
name: jsii/superchain
permissions:
contents: read
id-token: write # Necessary for OIDC federation
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
debian:
- 'bullseye' # 11
- 'bookworm' # 12
node: ['18', '20']
exclude:
# We publish bullseye only with Node >= 20
- debian: 'bullseye'
node: '18'
env:
# Node version whose images will be aliased without the -nodeXX segment
DEFAULT_NODE_MAJOR_VERSION: 18
steps:
- name: Check out
uses: actions/checkout@v4
# Determine if we should run the validation or not
- name: Should this run?
id: should-run
run: |-
if [ "${{ github.event_name }}" = "push" ]; then
echo '⏯ Triggered by "push" event'
echo "result=true" >> $GITHUB_OUTPUT
elif [ "${{ github.base_ref }}" = "release" ]; then
echo '⏯ Triggered by "pull_request" event against "release"'
echo "result=true" >> $GITHUB_OUTPUT
else
# Fetch the base and head refs from origin so we can safely diff 'em
git fetch --depth=1 --quiet origin ${{ github.base_ref }}
# Otherwise, only run if the Dockerfile changed
changed=$(git diff --name-only origin/${{ github.base_ref }}..HEAD)
if grep Dockerfile <<< "${changed}" ; then
echo '⏯ Dockerfile changed'
echo "result=true" >> $GITHUB_OUTPUT
else
if grep '.github/workflows/docker-images.yml' <<< "${changed}" ; then
echo '⏯ docker-images workflow changed'
echo "result=true" >> $GITHUB_OUTPUT
else
echo '⏭ Dockerfile not changed'
echo "result=false" >> $GITHUB_OUTPUT
fi
fi
fi
# Check if federation into AWS is configured. This is necessary because
# GitHub does not interpret ${{ secret.FOO }} within `if:` conditions...
# See: https://github.com/actions/runner/issues/520
- name: Check AWS federation configuration
id: federate_to_aws
if: steps.should-run.outputs.result == 'true'
run: |-
if [[ "${{ secrets.AWS_ROLE_TO_ASSUME }}" != "" ]]; then
echo "🔑 Federation into AWS is possible (AWS_ROLE_TO_ASSUME is available)"
echo "enabled=true" >> $GITHUB_OUTPUT
else
echo "❌ Federation into AWS is disabled (no AWS_ROLE_TO_ASSUME secret found)"
echo "enabled=false" >> $GITHUB_OUTPUT
fi
# Federate into the PR Validation AWS Account
- name: Federate into AWS
if: steps.should-run.outputs.result == 'true' && steps.federate_to_aws.outputs.enabled == 'true'
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-east-1
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
role-session-name: GHA_aws-jsii_docker-images
# Login to ECR Public registry, so we don't get throttled at 1 TPS
- name: Login to ECR Public
if: steps.should-run.outputs.result == 'true' && steps.federate_to_aws.outputs.enabled == 'true'
run: |-
aws ecr-public get-login-password --region=us-east-1 \
| docker login --username AWS --password-stdin public.ecr.aws
- name: Slice DockerHub credentials
id: credentials
run: |-
echo "username=$(cut -d: -f1 <<< '${{ secrets.DOCKER_CREDENTIALS }}')" >> "$GITHUB_OUTPUT"
echo "password=$(cut -d: -f2 <<< '${{ secrets.DOCKER_CREDENTIALS }}')" >> "$GITHUB_OUTPUT"
echo "::add-mask::$(cut -d: -f2 <<< '${{ secrets.DOCKER_CREDENTIALS }}')"
# We only authenticate to Docker on the 'aws/jsii' repo, as forks will not have the secret
- name: Login to Docker Hub
if: steps.should-run.outputs.result == 'true' && github.repository == 'aws/jsii'
# The DOCKER_CREDENTIALS secret is expected to contain a username:token pair
run: |-
docker login \
--username=${{ steps.credentials.outputs.username }} \
--password=${{ steps.credentials.outputs.password }}
# Ensure we run with bash, because that's the syntax we're using here...
shell: bash
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64
- name: Set up docker buildx
id: buildx
if: steps.should-run.outputs.result == 'true'
uses: docker/setup-buildx-action@v3
with:
# Disable parallelism because IO contention makes it too slow on GitHub
# workers...
config-inline: |-
[worker.oci]
max-parallelism = 1
# 1 pull per second from ECR Public
- name: Jitter the start time to avoid ECR Public throttling
id: sleep-start
if: steps.should-run.outputs.result == 'true' && steps.federate_to_aws.outputs.enabled != true
run: |-
sleep $((RANDOM % 60))
- name: Determine build time
id: build-time
if: steps.should-run.outputs.result == 'true'
run: |-
echo "value=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
- name: Show Available Disk Space
run: df -h && du -h
- name: Free Disk Space
uses: jlumbroso/free-disk-space@v1.3.1
- name: Build Image
if: steps.should-run.outputs.result == 'true'
run: |-
docker buildx build \
--quiet \
--builder ${{ steps.buildx.outputs.name }} \
--platform linux/amd64,linux/arm64 \
--target superchain \
--pull \
--build-arg BUILD_TIMESTAMP="${{ steps.build-time.outputs.value }}" \
--build-arg COMMIT_ID='${{ github.sha }}' \
--build-arg DEBIAN_VERSION=${{ matrix.debian }} \
--build-arg NODE_MAJOR_VERSION=${{ matrix.node }} \
-f superchain/Dockerfile \
.
- name: Test Image
if: steps.should-run.outputs.result == 'true'
run: |-
docker buildx build \
--builder ${{ steps.buildx.outputs.name }} \
--platform linux/amd64,linux/arm64 \
--target superchain \
--build-arg BUILD_TIMESTAMP="${{ steps.build-time.outputs.value }}" \
--build-arg COMMIT_ID='${{ github.sha }}' \
--build-arg DEBIAN_VERSION=${{ matrix.debian }} \
--build-arg NODE_MAJOR_VERSION=${{ matrix.node }} \
-f superchain/Dockerfile \
.
# Re-authenticate to ECR Public, this time with image-push permissions
- name: Federate with AWS role for ECR Public push
if: steps.should-run.outputs.result == 'true' && github.event_name == 'push' && (github.ref == 'refs/heads/release' || github.ref == 'refs/heads/main')
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-east-1
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME_FOR_ECR_PUBLIC_PUSH }}
role-session-name: GHA_aws-jsii_docker-images-PUSH
- name: Authenticate with ECR Public for Push
if: steps.should-run.outputs.result == 'true' && github.event_name == 'push' && (github.ref == 'refs/heads/release' || github.ref == 'refs/heads/main')
uses: aws-actions/amazon-ecr-login@v2
with:
registry-type: public
# Only when puhsing to main/release from now on
- name: Publish (nightly)
if: steps.should-run.outputs.result == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main'
# NOTE BELOW: The `--tag` flags can be provided multiple times... we use that capability...
run: |-
# If the current version is the default version, also tag this with the unqualified ':nightly' label
if [[ "${{ matrix.node }}" == "$DEFAULT_NODE_MAJOR_VERSION" ]]; then
docker buildx build \
--builder ${{ steps.buildx.outputs.name }} \
--platform linux/amd64,linux/arm64 \
--target superchain \
--push \
--build-arg BUILD_TIMESTAMP="${{ steps.build-time.outputs.value }}" \
--build-arg COMMIT_ID='${{ github.sha }}' \
--build-arg DEBIAN_VERSION=${{ matrix.debian }} \
--build-arg NODE_MAJOR_VERSION=${{ matrix.node }} \
--tag "${{ secrets.ECR_PUBLIC_REGISTRY }}:1-${{ matrix.debian }}-slim-nightly" \
--tag "${{ secrets.ECR_PUBLIC_REGISTRY }}:1-${{ matrix.debian }}-slim-node${{ matrix.node }}-nightly" \
--tag "jsii/superchain:1-${{ matrix.debian }}-slim-nightly" \
--tag "jsii/superchain:1-${{ matrix.debian }}-slim-node${{ matrix.node }}-nightly" \
-f superchain/Dockerfile \
.
else
docker buildx build \
--builder ${{ steps.buildx.outputs.name }} \
--platform linux/amd64,linux/arm64 \
--target superchain \
--push \
--build-arg BUILD_TIMESTAMP="${{ steps.build-time.outputs.value }}" \
--build-arg COMMIT_ID='${{ github.sha }}' \
--build-arg DEBIAN_VERSION=${{ matrix.debian }} \
--build-arg NODE_MAJOR_VERSION=${{ matrix.node }} \
--tag "${{ secrets.ECR_PUBLIC_REGISTRY }}:1-${{ matrix.debian }}-slim-node${{ matrix.node }}-nightly" \
--tag "jsii/superchain:1-${{ matrix.debian }}-slim-node${{ matrix.node }}-nightly" \
-f superchain/Dockerfile \
.
fi
- name: Update README (nightly)
if: steps.should-run.outputs.result == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: peter-evans/dockerhub-description@v4
with:
username: ${{ steps.credentials.outputs.username }}
password: ${{ steps.credentials.outputs.password }}
repository: jsii/superchain
readme-filepath: ./superchain/README.md
- name: Publish (latest)
if: steps.should-run.outputs.result == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/release'
# NOTE BELOW: The `--tag` flags can be provided multiple times... we use that capability...
run: |-
# If the current version is the default version, also tag this with the unqualified ':1-*' label
if [[ "${{ matrix.node }}" == "$DEFAULT_NODE_MAJOR_VERSION" ]]; then
docker buildx build \
--builder ${{ steps.buildx.outputs.name }} \
--platform linux/amd64,linux/arm64 \
--target superchain \
--push \
--build-arg BUILD_TIMESTAMP="${{ steps.build-time.outputs.value }}" \
--build-arg COMMIT_ID='${{ github.sha }}' \
--build-arg DEBIAN_VERSION=${{ matrix.debian }} \
--build-arg NODE_MAJOR_VERSION=${{ matrix.node }} \
--tag "${{ secrets.ECR_PUBLIC_REGISTRY }}:1-${{ matrix.debian }}-slim" \
--tag "${{ secrets.ECR_PUBLIC_REGISTRY }}:1-${{ matrix.debian }}-slim-node${{ matrix.node }}" \
--tag "jsii/superchain:1-${{ matrix.debian }}-slim" \
--tag "jsii/superchain:1-${{ matrix.debian }}-slim-node${{ matrix.node }}" \
-f superchain/Dockerfile \
.
else
docker buildx build \
--builder ${{ steps.buildx.outputs.name }} \
--platform linux/amd64,linux/arm64 \
--target superchain \
--push \
--build-arg BUILD_TIMESTAMP="${{ steps.build-time.outputs.value }}" \
--build-arg COMMIT_ID='${{ github.sha }}' \
--build-arg DEBIAN_VERSION=${{ matrix.debian }} \
--build-arg NODE_MAJOR_VERSION=${{ matrix.node }} \
--tag "${{ secrets.ECR_PUBLIC_REGISTRY }}:1-${{ matrix.debian }}-slim-node${{ matrix.node }}" \
--tag "jsii/superchain:1-${{ matrix.debian }}-slim-node${{ matrix.node }}" \
-f superchain/Dockerfile \
.
fi
done:
name: 'Done'
runs-on: ['ubuntu-latest']
needs: ['superchain']
steps:
# This is just a join target to simplify branch protection settings...
- name: 'All done'
run: |-
echo "All done!"