forked from canonical/oci-factory
-
Notifications
You must be signed in to change notification settings - Fork 0
352 lines (317 loc) · 13.7 KB
/
Copy pathBuild-Rock.yaml
File metadata and controls
352 lines (317 loc) · 13.7 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
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
name: Build rock
on:
workflow_call:
inputs:
# Build parameters
oci-archive-name:
description: "Final filename of the rock OCI archive."
type: string
required: true
build-id:
description: "Optional string for identifying workflow jobs in GitHub UI"
type: string
rockcraft-test:
description: "Whether to run rockcraft test when packing the rock"
type: boolean
default: false
# Source parameters
rock-repo:
description: "Public Git repo where to build the rock from."
type: string
required: true
rock-repo-commit:
description: "Git ref from where to build the rock from."
type: string
required: true
rockfile-directory:
description: "Directory in repository where to find the rockcraft.yaml file."
type: string
required: true
lfs:
description: "Whether to download Git LFS files from target repo."
type: boolean
default: false
lfs-include:
description: "Value to provide to git lfs pull --include when downloading LFS files. If this is not provided then all LFS files are pulled"
type: string
default: ''
pro-services:
description: "The pro services to enable during the build. Requires pro-token to be set."
type: string
default: ''
# Parameters for multi-arch builds
# specifying the runners with size label to prevent from running on private/tiobe runners
arch-map:
description: "JSON string mapping target architecture to runners."
type: string
default: ''
lpci-fallback:
description: "Enable fallback to Launchpad build when runners for target arch are not available."
type: boolean
default: false
secrets:
# Authentication parameters
host-github-token:
description: "Deprecated: GitHub token from repository executing this workflow."
source-github-token:
description: "GitHub token for pulling a Rockcraft project from a private repository."
pro-artifact-passphrase:
description: "Passphrase for encrypting/decrypting rock artifacts when pro-services is used."
pro-token:
description: "The Ubuntu Pro token. Required for building Ubuntu Pro based rocks."
env:
ROCK_REPO_DIR: rock-repo # path where the image repo is cloned into
ROCK_CI_FOLDER: ci-rocks # path of uploaded/downloaded artifacts
DEFAULT_ARCH_MAP: '{
"amd64": ["self-hosted-linux-amd64-noble-large"],
"arm64": ["self-hosted-linux-arm64-noble-medium"],
"s390x": ["self-hosted-linux-s390x-noble-medium"],
"ppc64el": ["self-hosted-linux-ppc64el-noble-edge"]
}'
jobs:
configure-build:
# configure-build reads the rockcraft.yaml, creating one or more *-build job runs
# depending on the target architecture.
runs-on: ubuntu-22.04
outputs:
runner-build-matrix: ${{ steps.configure.outputs.runner-build-matrix }}
lpci-build-matrix: ${{ steps.configure.outputs.lpci-build-matrix }}
pro-build: ${{ steps.check-pro-build.outputs.pro-build }}
name: "configure-build ${{ inputs.build-id != '' && format('| {0}', inputs.build-id) || ' '}}"
steps:
- name: Warn deprecated secret
env:
HOST_GITHUB_TOKEN: ${{ secrets.host-github-token }}
if: ${{ env.HOST_GITHUB_TOKEN != '' }}
run: |
echo "::warning:: 'host-github-token' is unused and deprecated. Please remove this secret from the caller workflow."
- name: Check Pro Build
id: check-pro-build
env:
UBUNTU_PRO_TOKEN: ${{ secrets.pro-token }}
run: |
if [[ -n "${{ inputs.pro-services }}" ]]; then
if [[ -z "${UBUNTU_PRO_TOKEN:-}" ]]; then
echo "Error: 'pro-token' must be provided in order to use 'pro-services'."
exit 1
fi
echo "pro-build=true" >> $GITHUB_OUTPUT
else
echo "pro-build=false" >> $GITHUB_OUTPUT
fi
- name: Cloning OCI Factory
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
# Here we clone the oci-factory repo using the default ref of the checkout action.
# It will be set to a ref that triggered this workflow if the workflow is run within the oci-factory repo,
# or to the default branch of the oci-factory repo if the workflow is called from another repo.
repository: canonical/oci-factory
fetch-depth: 1
- name: Cloning Target Repo
uses: ./.github/actions/checkout
with:
repository: ${{ inputs.rock-repo }}
path: ${{ env.ROCK_REPO_DIR }}
ref: ${{ inputs.rock-repo-commit }}
submodules: "recursive"
token: ${{ secrets.source-github-token }}
lfs: ${{ inputs.lfs }}
lfs-include: ${{ inputs.lfs-include }}
- name: Installing Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
with:
python-version: "3.x"
- name: Installing Python requirements
run: python3 -m pip install -r src/build_rock/configure/requirements.txt
# Configure matrices for each *-build job
- name: Configuring Jobs
id: configure
run: |
python3 -m src.build_rock.configure.generate_build_matrix \
--rockfile-directory "${{ env.ROCK_REPO_DIR }}/${{ inputs.rockfile-directory }}" \
--lpci-fallback "${{ toJSON(inputs.lpci-fallback) }}" \
--config ${{ toJSON(inputs.arch-map || env.DEFAULT_ARCH_MAP) }} # important: do not use quotes here
runner-build:
# runner-build builds rocks per target architecture using pre configured runner images.
needs: [configure-build]
if: fromJSON(needs.configure-build.outputs.runner-build-matrix).include[0] != ''
strategy:
fail-fast: true
matrix: ${{ fromJSON(needs.configure-build.outputs.runner-build-matrix) }}
runs-on: ${{ matrix.runner }}
name: "runner-build | ${{ matrix.architecture }} ${{ inputs.build-id != '' && format('| {0}', inputs.build-id) || ' '}}"
steps:
- name: Cloning OCI Factory
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
repository: canonical/oci-factory
fetch-depth: 1
- name: Cloning Target Repo
uses: ./.github/actions/checkout
with:
repository: ${{ inputs.rock-repo }}
path: ${{ env.ROCK_REPO_DIR }}
ref: ${{ inputs.rock-repo-commit }}
submodules: "recursive"
token: ${{ secrets.source-github-token }}
lfs: ${{ inputs.lfs }}
lfs-include: ${{ inputs.lfs-include }}
- name: Attaching Pro Token
if: ${{ needs.configure-build.outputs.pro-build == 'true' }}
id: attach_pro
env:
UBUNTU_PRO_TOKEN: ${{ secrets.pro-token }}
run: |
sudo pro attach --no-auto-enable "$UBUNTU_PRO_TOKEN"
- name: Building Target
id: rockcraft
uses: canonical/craft-actions/rockcraft-pack@main
with:
path: "${{ env.ROCK_REPO_DIR }}/${{ inputs.rockfile-directory }}"
test: "${{ inputs.rockcraft-test }}"
pro: "${{ inputs.pro-services }}"
verbosity: debug
- name: Detaching Pro Token
if: always() && steps.attach_pro.outcome == 'success'
run: |
sudo pro detach --assume-yes
- name: Collecting Artifacts
id: collect-artifacts
run: |
mkdir -p ${{ env.ROCK_CI_FOLDER }} && cp ${{ steps.rockcraft.outputs.rock }} "$_"
echo "filename=$(basename ${{ steps.rockcraft.outputs.rock }})" >> $GITHUB_OUTPUT
- name: Encrypting Single Arch Rock Artifacts
if: ${{ needs.configure-build.outputs.pro-build == 'true' }}
uses: ./.github/actions/crypt-artifact
with:
mode: encrypt
input-path: ${{ env.ROCK_CI_FOLDER }}/${{ steps.collect-artifacts.outputs.filename }}
output-path: ${{ env.ROCK_CI_FOLDER }}/${{ steps.collect-artifacts.outputs.filename }}.gpg
passphrase: ${{ secrets.pro-artifact-passphrase }}
preserve-original: false
- name: Uploading Artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
with:
name: ${{ inputs.oci-archive-name }}-${{ steps.collect-artifacts.outputs.filename }}
path: ${{ env.ROCK_CI_FOLDER }}
if-no-files-found: error
lpci-build:
# lpci-build is a fallback for building rocks if no suitable runners are
# configured for the required architecture. Builds in this job will be
# outsourced to Launchpad for completion.
# Note the Secret
needs: [configure-build]
if: fromJSON(needs.configure-build.outputs.lpci-build-matrix).include[0] != ''
strategy:
fail-fast: true
matrix: ${{ fromJSON(needs.configure-build.outputs.lpci-build-matrix) }}
runs-on: ubuntu-22.04
name: "lpci-build | ${{ matrix.architecture }} ${{ inputs.build-id != '' && format('| {0}', inputs.build-id) || ' '}}"
steps:
- name: Cloning OCI Factory
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
repository: canonical/oci-factory
fetch-depth: 1
- name: Cloning Target Repo
uses: ./.github/actions/checkout
with:
repository: ${{ inputs.rock-repo }}
path: ${{ env.ROCK_REPO_DIR }}
ref: ${{ inputs.rock-repo-commit }}
submodules: "recursive"
token: ${{ secrets.source-github-token }}
- name: Building Target
# TODO: Replace this retry action with bash equivalent for better testing
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60
id: lpci-build
with:
timeout_minutes: 180
max_attempts: 4
polling_interval_seconds: 5
retry_wait_seconds: 30
command: |
src/build_rock/lpci_build/lpci_build.sh \
-c "${{ secrets.LP_CREDENTIALS_B64 }}" \
-d "${{ env.ROCK_REPO_DIR }}/${{ inputs.rockfile-directory }}"
- name: Upload Build Logs
if: ${{ !cancelled() }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
with:
name: lpci-build-logs-${{ matrix.architecture }}
path: ${{ steps.lpci-build.outputs.build-log }}
- name: Collecting Artifacts
id: collect-artifacts
run: |
mkdir -p ${{ env.ROCK_CI_FOLDER }} && cp ${{ env.ROCK_REPO_DIR }}/${{ inputs.rockfile-directory }}/*.rock "$_"
echo "filename=${{ matrix.rock-name }}_${{ matrix.architecture }}" >> $GITHUB_OUTPUT
- name: Uploading Artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
with:
name: ${{ inputs.oci-archive-name }}-${{ steps.collect-artifacts.outputs.filename }}
path: ${{ env.ROCK_CI_FOLDER }}
if-no-files-found: error
assemble-rock:
# Assemble individual single-arch rocks into multi-arch rocks
needs: [runner-build, lpci-build, configure-build]
runs-on: ubuntu-24.04
# Always run even if one of the *-build jobs are skipped
# Nice example from benjamin-bergia/github-workflow-patterns...
if: ${{ always() && contains(needs.*.result, 'success') && !(contains(needs.*.result, 'failure')) }}
name: "assemble-rock ${{ inputs.build-id != '' && format('| {0}', inputs.build-id) || ' '}}"
steps:
# Job Setup
- name: Cloning OCI Factory
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
repository: canonical/oci-factory
fetch-depth: 1
- run: src/build_rock/assemble_rock/requirements.sh
- name: Downloading Single Arch rocks
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
id: download
with:
path: ${{ env.ROCK_CI_FOLDER }}
pattern: ${{ inputs.oci-archive-name }}-*
merge-multiple: true
# We cannot use the action here, as we need to iterate over
# multiple files if there are multiple single-arch rocks.
- name: Decrypting Single Arch Rock Artifacts
if: ${{ needs.configure-build.outputs.pro-build == 'true' }}
env:
ARTIFACT_PASSPHRASE: ${{ secrets.pro-artifact-passphrase }}
run: |
for rock in ${{ env.ROCK_CI_FOLDER }}/*; do
./.github/actions/crypt-artifact/crypt-artifact.sh decrypt \
-i "$rock" \
-p "$ARTIFACT_PASSPHRASE" \
-o "${rock%%.*}.rock"
done
- name: Assembling Multi Arch rock
run: |
src/build_rock/assemble_rock/assemble.sh \
-n "${{ inputs.oci-archive-name }}" \
-d "${{ env.ROCK_CI_FOLDER }}"
- name: Get artifact name
id: final-artifact
run: |
name="${{ inputs.oci-archive-name }}"
if [[ ${{ needs.configure-build.outputs.pro-build }} == 'true' ]]; then
name="${name}.gpg"
fi
echo "name=$name" >> $GITHUB_OUTPUT
- name: Encrypting Multi Arch Rock Artifact
if: ${{ needs.configure-build.outputs.pro-build == 'true' }}
uses: ./.github/actions/crypt-artifact
with:
mode: encrypt
input-path: ${{ inputs.oci-archive-name }}
output-path: ${{ steps.final-artifact.outputs.name }}
passphrase: ${{ secrets.pro-artifact-passphrase }}
preserve-original: false
- name: Uploading Multi Arch rock
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
with:
name: ${{ inputs.oci-archive-name }}
path: ${{ steps.final-artifact.outputs.name }}
if-no-files-found: error