33
33
type : boolean
34
34
required : false
35
35
default : true
36
+ push-dirty :
37
+ description : Push scanned images that have vulnerabilities?
38
+ type : boolean
39
+ required : false
40
+ # NOTE(Alex-Welsh): This default should be flipped once we resolve existing failures
41
+ default : true
36
42
37
43
env :
38
44
ANSIBLE_FORCE_COLOR : True
54
60
id : openstack_release
55
61
run : |
56
62
BRANCH=$(awk -F'=' '/defaultbranch/ {print $2}' .gitreview)
57
- echo "openstack_release=${BRANCH}" | sed "s| stable/|| " >> $GITHUB_OUTPUT
63
+ echo "openstack_release=${BRANCH}" | sed -E "s,( stable|unmaintained)/,, " >> $GITHUB_OUTPUT
58
64
59
65
# Generate a tag to apply to all built container images.
60
66
# Without this, each kayobe * container image build command would use a different tag.
@@ -100,7 +106,15 @@ jobs:
100
106
- name : Install package dependencies
101
107
run : |
102
108
sudo apt update
103
- sudo apt install -y build-essential git unzip nodejs python3-wheel python3-pip python3-venv
109
+ sudo apt install -y build-essential git unzip nodejs python3-wheel python3-pip python3-venv curl jq wget
110
+
111
+ - name : Install gh
112
+ run : |
113
+ sudo mkdir -p -m 755 /etc/apt/keyrings && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null
114
+ sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg
115
+ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
116
+ sudo apt update
117
+ sudo apt install gh -y
104
118
105
119
- name : Checkout
106
120
uses : actions/checkout@v4
@@ -118,6 +132,10 @@ jobs:
118
132
run : |
119
133
docker ps
120
134
135
+ - name : Install Trivy
136
+ run : |
137
+ curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin v0.49.0
138
+
121
139
- name : Install Kayobe
122
140
run : |
123
141
mkdir -p venvs &&
@@ -132,6 +150,10 @@ jobs:
132
150
- name : Install Docker Python SDK
133
151
run : |
134
152
sudo pip install docker
153
+
154
+ - name : Get Kolla tag
155
+ id : write-kolla-tag
156
+ run : echo "kolla-tag=${{ needs.generate-tag.outputs.openstack_release }}-${{ matrix.distro }}-${{ matrix.distro == 'rocky' && '9' || 'jammy' }}-${{ needs.generate-tag.outputs.datetime_tag }}" >> $GITHUB_OUTPUT
135
157
136
158
- name : Configure localhost as a seed
137
159
run : |
@@ -153,67 +175,124 @@ jobs:
153
175
env :
154
176
KAYOBE_VAULT_PASSWORD : ${{ secrets.KAYOBE_VAULT_PASSWORD }}
155
177
156
- - name : Build and push kolla overcloud images
178
+ - name : Create build logs output directory
179
+ run : mkdir image-build-logs
180
+
181
+ - name : Build kolla overcloud images
182
+ id : build_overcloud_images
183
+ continue-on-error : true
157
184
run : |
158
- args="${{ github.event. inputs.regexes }}"
185
+ args="${{ inputs.regexes }}"
159
186
args="$args -e kolla_base_distro=${{ matrix.distro }}"
160
- args="$args -e kolla_tag=$KOLLA_TAG "
187
+ args="$args -e kolla_tag=${{ steps.write-kolla-tag.outputs.kolla-tag }} "
161
188
args="$args -e stackhpc_repo_mirror_auth_proxy_enabled=true"
162
- if ${{ inputs.push }} == 'true'; then
163
- args="$args --push"
164
- fi
165
189
source venvs/kayobe/bin/activate &&
166
190
source src/kayobe-config/kayobe-env --environment ci-builder &&
167
191
kayobe overcloud container image build $args
168
192
env :
169
193
KAYOBE_VAULT_PASSWORD : ${{ secrets.KAYOBE_VAULT_PASSWORD }}
170
- KOLLA_TAG : " ${{ needs.generate-tag.outputs.openstack_release }}-${{ matrix.distro }}-${{ matrix.distro == 'rocky' && '9' || 'jammy' }}-${{ needs.generate-tag.outputs.datetime_tag }}"
171
- if : github.event.inputs.overcloud == 'true'
194
+ if : inputs.overcloud
195
+
196
+ - name : Copy overcloud container image build logs to output directory
197
+ run : sudo mv /var/log/kolla-build.log image-build-logs/kolla-build-overcloud.log
198
+ if : inputs.overcloud
172
199
173
- - name : Build and push kolla seed images
200
+ - name : Build kolla seed images
201
+ id : build_seed_images
202
+ continue-on-error : true
174
203
run : |
175
204
args="-e kolla_base_distro=${{ matrix.distro }}"
176
- args="$args -e kolla_tag=$KOLLA_TAG "
205
+ args="$args -e kolla_tag=${{ steps.write-kolla-tag.outputs.kolla-tag }} "
177
206
args="$args -e stackhpc_repo_mirror_auth_proxy_enabled=true"
178
- if ${{ inputs.push }} == 'true'; then
179
- args="$args --push"
180
- fi
181
207
source venvs/kayobe/bin/activate &&
182
208
source src/kayobe-config/kayobe-env --environment ci-builder &&
183
209
kayobe seed container image build $args
184
210
env :
185
211
KAYOBE_VAULT_PASSWORD : ${{ secrets.KAYOBE_VAULT_PASSWORD }}
186
- KOLLA_TAG : " ${{ needs.generate-tag.outputs.openstack_release }}-${{ matrix.distro }}-${{ matrix.distro == 'rocky' && '9' || 'jammy' }}-${{ needs.generate-tag.outputs.datetime_tag }}"
187
- if : github.event.inputs.seed == 'true'
212
+ if : inputs.seed
213
+
214
+ - name : Copy seed container image build logs to output directory
215
+ run : sudo mv /var/log/kolla-build.log image-build-logs/kolla-build-seed.log
216
+ if : inputs.seed
188
217
189
218
- name : Get built container images
190
- run : |
191
- docker image ls --filter "reference=ark.stackhpc.com/stackhpc-dev/*:*${{ matrix.distro }}*${{ needs.generate-tag.outputs.datetime_tag }}" > ${{ matrix.distro }}-container-images
219
+ run : docker image ls --filter "reference=ark.stackhpc.com/stackhpc-dev/*:${{ steps.write-kolla-tag.outputs.kolla-tag }}" > ${{ matrix.distro }}-container-images
192
220
193
221
- name : Fail if no images have been built
194
222
run : if [ $(wc -l < ${{ matrix.distro }}-container-images) -le 1 ]; then exit 1; fi
195
223
196
- - name : Upload container images artifact
224
+ - name : Scan built container images
225
+ run : src/kayobe-config/tools/scan-images.sh ${{ matrix.distro }} ${{ steps.write-kolla-tag.outputs.kolla-tag }}
226
+
227
+ - name : Move image scan logs to output artifact
228
+ run : mv image-scan-output image-build-logs/image-scan-output
229
+
230
+ - name : Fail if no images have passed scanning
231
+ run : if [ $(wc -l < image-build-logs/image-scan-output/clean-images.txt) -le 0 ]; then exit 1; fi
232
+ if : ${{ !inputs.push-dirty }}
233
+
234
+ - name : Copy clean images to push-attempt-images list
235
+ run : cp image-build-logs/image-scan-output/clean-images.txt image-build-logs/push-attempt-images.txt
236
+ if : inputs.push
237
+
238
+ - name : Append dirty images to push list
239
+ run : |
240
+ cat image-build-logs/image-scan-output/dirty-images.txt >> image-build-logs/push-attempt-images.txt
241
+ if : ${{ inputs.push && inputs.push-dirty }}
242
+
243
+ - name : Push images
244
+ run : |
245
+ touch image-build-logs/push-failed-images.txt
246
+ source venvs/kayobe/bin/activate &&
247
+ source src/kayobe-config/kayobe-env --environment ci-builder &&
248
+ kayobe playbook run ${KAYOBE_CONFIG_PATH}/ansible/docker-registry-login.yml &&
249
+
250
+ while read -r image; do
251
+ # Retries!
252
+ for i in {1..5}; do
253
+ if docker push $image; then
254
+ echo "Pushed $image"
255
+ break
256
+ elif $i == 5; then
257
+ echo "Failed to push $image"
258
+ echo $image >> image-build-logs/push-failed-images.txt
259
+ else
260
+ echo "Failed on retry $i"
261
+ sleep 5
262
+ fi;
263
+ done
264
+ done < image-build-logs/push-attempt-images.txt
265
+ shell : bash
266
+ env :
267
+ KAYOBE_VAULT_PASSWORD : ${{ secrets.KAYOBE_VAULT_PASSWORD }}
268
+ if : inputs.push
269
+
270
+ - name : Upload output artifact
197
271
uses : actions/upload-artifact@v4
198
272
with :
199
- name : ${{ matrix.distro }} container images
200
- path : ${{ matrix.distro }}-container-images
273
+ name : ${{ matrix.distro }}-logs
274
+ path : image-build-logs
201
275
retention-days : 7
276
+ if : ${{ !cancelled() }}
277
+
278
+ - name : Fail when images failed to build
279
+ run : echo "An image build failed. Check the workflow artifact for build logs" && exit 1
280
+ if : ${{ steps.build_overcloud_images.outcome == 'failure' || steps.build_seed_images.outcome == 'failure' }}
281
+
282
+ - name : Fail when images failed to push
283
+ run : if [ $(wc -l < image-build-logs/push-failed-images.txt) -gt 0 ]; then cat image-build-logs/push-failed-images.txt && exit 1; fi
284
+ if : ${{ !cancelled() }}
285
+
286
+ - name : Fail when images failed scanning
287
+ run : if [ $(wc -l < image-build-logs/dirty-images.txt) -gt 0 ]; then cat image-build-logs/dirty-images.txt && exit 1; fi
288
+ if : ${{ !inputs.push-dirty && !cancelled() }}
202
289
203
- sync-container-repositories :
204
- name : Trigger container image repository sync
205
- needs :
206
- - container-image-build
207
- if : github.repository == 'stackhpc/stackhpc-kayobe-config' && inputs.push
208
- runs-on : ubuntu-latest
209
- permissions : {}
210
- steps :
211
290
# NOTE(mgoddard): Trigger another CI workflow in the
212
291
# stackhpc-release-train repository.
213
292
- name : Trigger container image repository sync
214
293
run : |
215
294
filter='${{ inputs.regexes }}'
216
- if [[ -n $filter ]] && [[ ${{ github.event. inputs.seed }} == 'true' ]]; then
295
+ if [[ -n $filter ]] && [[ ${{ inputs.seed }} == 'true' ]]; then
217
296
filter="$filter bifrost"
218
297
fi
219
298
gh workflow run \
@@ -224,7 +303,9 @@ jobs:
224
303
-f sync-old-images=false
225
304
env :
226
305
GITHUB_TOKEN : ${{ secrets.STACKHPC_RELEASE_TRAIN_TOKEN }}
306
+ if : ${{ github.repository == 'stackhpc/stackhpc-kayobe-config' && inputs.push && !cancelled() }}
227
307
228
308
- name : Display link to container image repository sync workflows
229
309
run : |
230
310
echo "::notice Container image repository sync workflows: https://github.com/stackhpc/stackhpc-release-train/actions/workflows/container-sync.yml"
311
+ if : ${{ github.repository == 'stackhpc/stackhpc-kayobe-config' && inputs.push && !cancelled() }}
0 commit comments