-
Notifications
You must be signed in to change notification settings - Fork 0
299 lines (259 loc) Β· 10 KB
/
BUILD-01_build-push-devcontainer-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
# .github/workflows/BUILD-01_build-push-devcontainer-image.yml
# Workflow Name: Build and Push Dev Container Image
# Description: This workflow is responsible for building and pushing Dev Container images to GitHub Container Registry (GHCR).
# It triggers on manual dispatch, a schedule (every Monday at 3:00 UTC), and tag pushes that match 'v*'.
# The workflow ensures that only the latest run for a particular branch or tag is executed, cancelling any in-progress runs.
name: "Build and Push Dev Container Image"
# Concurrency ensures that only one workflow run is in progress for a given branch/tag.
# This prevents race conditions during build and push operations.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Triggers for the workflow
on:
workflow_dispatch: # Allows manual triggering of the workflow.
schedule:
- cron: "23 3 * * Mon" # This updates the `weekly` image tag.
push:
tags:
- "v*" # Trigger for tags that start with 'v'.
# Environment variables used across all jobs.
env:
REGISTRY: ghcr.io
IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/devcontainers/m365-dev
jobs:
build:
name: "Build ${{ matrix.platform }} Image"
permissions:
contents: read # Required for checking out the code.
packages: write # Required for pushing images to GHCR.
attestations: write # Allows writing attestations to images, if used.
strategy:
fail-fast: false
matrix:
builder:
- ubuntu-22.04
- workoho-4vcpu-ubuntu-2204-arm
platform:
- amd64
- arm64
exclude:
- builder: ubuntu-22.04
platform: arm64
- builder: workoho-4vcpu-ubuntu-2204-arm
platform: amd64
outputs:
primary_tag_amd64: ${{ steps.dcmeta.outputs.primary_tag_amd64 }}
primary_tag_arm64: ${{ steps.dcmeta.outputs.primary_tag_arm64 }}
runs-on: ${{ matrix.builder }}
concurrency:
group: ${{ matrix.platform }}
steps:
- name: Update skopeo
run: |
set -e
REPO_URL="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_22.04"
sudo sh -c "echo 'deb ${REPO_URL}/ /' > /etc/apt/sources.list.d/skopeo.list"
curl -fsSL ${REPO_URL}/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/skopeo.gpg > /dev/null
sudo apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install skopeo
skopeo --version
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
logout: false
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
# list of Docker images to use as base name for tags
images: ${{ env.IMAGE_NAME }}
# generate Docker tags based on the following events/attributes
tags: |
type=schedule,pattern=weekly
type=semver,pattern={{version}}
type=semver,pattern=v{{major}}.{{minor}}
type=semver,pattern=v{{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }}
type=ref,event=branch
type=ref,event=pr
sep-tags: ","
flavor: |
latest=false
prefix=
suffix=-${{ matrix.platform }}
- name: Update Tags to Fit into devcontainers/cli format
id: dcmeta
run: |
prefix="${{ env.IMAGE_NAME }}"
input_list="$DOCKER_METADATA_OUTPUT_TAGS"
delimiter=","
result_list=$(echo "$input_list" | sed "s|${prefix}:||g")
echo "primary_tag_${{ matrix.platform }}=${result_list%%,*}" >> "$GITHUB_OUTPUT"
echo "tags=$result_list" >> "$GITHUB_OUTPUT"
- name: "[${{ matrix.platform }}] Pre-build Dev Container Image"
uses: devcontainers/[email protected]
env:
# see: https://github.com/devcontainers/ci/issues/191#issuecomment-1603857155
BUILDX_NO_DEFAULT_ATTESTATIONS: true
with:
subFolder: .devcontainer/src
configFile: .devcontainer/src/devcontainer.json
platform: linux/${{ matrix.platform }}
cacheFrom: ${{ env.IMAGE_NAME }}
imageName: ${{ env.IMAGE_NAME }}
imageTag: ${{ steps.dcmeta.outputs.tags }}
push: always
skipContainerUserIdUpdate: true
post-build:
name: "${{ matrix.platform }} Digest Collection"
needs: build
permissions:
packages: read
strategy:
fail-fast: false
matrix:
builder:
- ubuntu-22.04
- workoho-4vcpu-ubuntu-2204-arm
platform:
- amd64
- arm64
exclude:
- builder: ubuntu-22.04
platform: arm64
- builder: workoho-4vcpu-ubuntu-2204-arm
platform: amd64
runs-on:
- ${{ matrix.builder }}
concurrency:
group: ${{ matrix.platform }}
steps:
- name: Export digests
run: |
if [ "${{ matrix.platform }}" == "amd64" ]; then
primary_tag="${{ needs.build.outputs.primary_tag_amd64 }}"
elif [ "${{ matrix.platform }}" == "arm64" ]; then
primary_tag="${{ needs.build.outputs.primary_tag_arm64 }}"
fi
image_name="${{ env.IMAGE_NAME }}:$primary_tag"
echo "Pulling image: $image_name"
docker pull "$image_name"
docker images
echo "Inspecting image: $image_name"
mkdir -p /tmp/digests
digests=$(docker inspect --format='{{json .RepoDigests}}' "$image_name" | jq -r '.[]')
for digest in $digests; do
digest_sha="${digest#*@}"
touch "/tmp/digests/${digest_sha#sha256:}"
echo "Found digest: $digest_sha"
done
- name: Upload digests
uses: actions/upload-artifact@v4
with:
name: digests-${{ matrix.platform }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
name: Update multi-layer image tags
needs: post-build
permissions:
contents: read # Required for checking out the code.
packages: write # Required for pushing images to GHCR.
runs-on: ubuntu-latest
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
logout: false
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
# list of Docker images to use as base name for tags
images: ${{ env.IMAGE_NAME }}
# generate Docker tags based on the following events/attributes
tags: |
type=schedule,pattern=weekly
type=semver,pattern={{version}}
type=semver,pattern=v{{major}}.{{minor}}
type=semver,pattern=v{{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }}
type=ref,event=branch
type=ref,event=pr
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v1.') && !contains(github.ref, '-') }}
flavor: |
latest=false
prefix=
suffix=
- name: Create Manifest List and Push
working-directory: /tmp/digests
run: |
docker buildx imagetools create \
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.IMAGE_NAME }}@sha256:%s ' *)
- name: Inspect Manifest List for Each Tag
run: |
tags=$(jq -cr '.tags[]' <<< "$DOCKER_METADATA_OUTPUT_JSON")
for tag in $tags; do
# Inspecting image: $tag
docker buildx imagetools inspect $tag
done
publish-release:
name: Publish release
if: startsWith(github.ref, 'refs/tags/v')
needs:
- merge
permissions:
contents: write
packages: read
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Generate Release Notes Introduction
id: release_notes
run: |
if [[ "${{ github.ref_name }}" == *-* ]]; then
BODY="This is a pre-release version of the Admin Container for Microsoft 365. It is not recommended for production use."
else
BODY="This is a release version of the Admin Container for Microsoft 365 and may be used in production environments."
fi
BODY+="\n\nVisit the [container registry](https://${{ env.IMAGE_NAME }}) to learn more."
BODY+="\n\nAlso note the [README](https://github.com/${{ github.repository }}/blob/${{ github.ref_name }}/README.md) of this particular release."
BODY+="\n\nAutomatically generated release notes:\n\n"
echo "body<<EOF" >> $GITHUB_OUTPUT
echo -e "$BODY" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
shell: bash
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref_name }}
name: ${{ github.ref_name }} of the Admin Container for Microsoft 365 Image
draft: ${{ !contains(github.ref_name, '-') }}
prerelease: ${{ contains(github.ref_name, '-') }}
make_latest: ${{ !contains(github.ref_name, '-') }}
generate_release_notes: true
body: ${{ steps.release_notes.outputs.body }}