Skip to content

Commit 3bccdc5

Browse files
authored
feat: optimize skip_push and skip_retag (#233)
* feat: optimize skip_push and skip_retag * Disable trivy cache * Use correct components * Disable trivy for now * Skip empty matrix builds * Remove some more things for testing * Only provide test_images_report if folder isn't empty
1 parent 6e27a4a commit 3bccdc5

File tree

1 file changed

+42
-25
lines changed

1 file changed

+42
-25
lines changed

.github/workflows/build-docker-artifacts.yml

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -102,23 +102,37 @@ jobs:
102102
103103
const builds = process.env.BUILDS ? process.env.BUILDS.split(',') : Object.keys(config.build);
104104
const push_to = process.env.PUSH_TO ? process.env.PUSH_TO.split(',') : Object.keys(config.push || {});
105+
const skip_push = process.env.SKIP_PUSH === 'true';
105106
106107
const flavors = builds.map(id => [id, config.build[id]]).filter(([id, flavor]) => flavor.skip !== true).map(([id, flavor]) => {
108+
const hooksDirectory = path.join('./deploy/build', flavor.directory, 'hooks');
109+
const testImagesHookScript = path.join(hooksDirectory, 'test-images.sh');
110+
const testImagesHookReport = path.join(hooksDirectory, 'test-images-report');
111+
const testImageEnabled = fs.existsSync(testImagesHookScript);
112+
107113
return {
108114
...flavor,
109115
id,
116+
skip_retag: skip_push,
110117
// Add metadata to the flavor object (will be used as matrix input)
111118
build_time: buildTime,
112119
image_tag: imageTag,
113120
image_tag_branch_name: imageTagBranchName,
114-
ecr_respositories: flavor.components.map(component => component.ecr_repository),
121+
ecr_repositories: flavor.components.map(component => component.ecr_repository),
122+
test_images: {
123+
enabled: testImageEnabled,
124+
script_path: testImagesHookScript,
125+
report_path: testImagesHookReport,
126+
},
115127
components: flavor.components.map(component => {
116128
// Format build arguments as build-args string
117129
const formattedBuildArgs = component.build_args ?
118130
Object.entries(component.build_args).map(([key, value]) => `${key}=${value}`).join('\n') : '';
119131
120132
return {
121133
...component,
134+
// We can skip the push only if we don't want to test the image below
135+
skip_push: skip_push && !testImageEnabled,
122136
// Add metadata to the component object (will be used as matrix input),
123137
flavor,
124138
flavor_id: id,
@@ -133,16 +147,18 @@ jobs:
133147
};
134148
});
135149
136-
const flattenedComponents = flavors.flatMap(flavor => flavor.components);
137-
138150
const result = {
139151
flavors,
140-
components: flattenedComponents,
152+
flavorsToTest: flavors.filter(flavor => flavor.test_images.enabled),
153+
flavorsToRetag: flavors.filter(flavor => flavor.skip_retag !== true),
154+
componentsToBuild: flavors.flatMap(flavor => flavor.components),
141155
push_to: push_to.join(','),
156+
skip_push,
142157
};
143158
console.log(result);
144159
return result;
145160
env:
161+
SKIP_PUSH: ${{ inputs.skip_push }}
146162
BUILDS: ${{ inputs.builds }}
147163
PUSH_TO: ${{ inputs.push_to }}
148164

@@ -152,7 +168,7 @@ jobs:
152168
strategy:
153169
fail-fast: ${{ inputs.fail_fast }}
154170
matrix:
155-
component: ${{ fromJson(needs.get-flavors.outputs.result).components }}
171+
component: ${{ fromJson(needs.get-flavors.outputs.result).componentsToBuild }}
156172
runs-on: ${{ vars.BUILD_DOCKER_RUNS_ON_OVERRIDE || vars.RUNS_ON_OVERRIDE || inputs.runs_on || 'ubuntu-22.04' }}
157173
steps:
158174
- name: View flavor and component
@@ -279,9 +295,12 @@ jobs:
279295
ignore-unfixed: false
280296
vuln-type: "os,library"
281297
severity: ${{ steps.set_severity.outputs.severity }}
298+
# The cache update takes quite long, so let's try to disable it for now: https://github.com/aquasecurity/trivy-action#cache
299+
cache: "false"
282300
continue-on-error: false
283301

284302
- name: Push image
303+
if: ${{ matrix.component.skip_push != true }}
285304
# Instead of the docker/build-push-action@v6 which will rebuild the image, just push it directly
286305
run: docker push ${{ matrix.component.image_ref }}
287306

@@ -292,10 +311,12 @@ jobs:
292311
test-images:
293312
name: Test images of flavor ${{ matrix.flavor.id || 'default' }}
294313
needs: [get-flavors, build-flavors]
314+
# Skip in case we would have an empty matrix. Note that in this case it also skips all downstream jobs...
315+
if: ${{ toJSON(fromJson(needs.get-flavors.outputs.result).flavorsToTest) != '[]' }}
295316
strategy:
296317
fail-fast: false
297318
matrix:
298-
flavor: ${{ fromJson(needs.get-flavors.outputs.result).flavors }}
319+
flavor: ${{ fromJson(needs.get-flavors.outputs.result).flavorsToTest }}
299320
runs-on: ${{ inputs.runs_on || 'ubuntu-22.04' }}
300321
steps:
301322
- name: Checkout repository
@@ -304,13 +325,6 @@ jobs:
304325
ref: ${{ inputs.branch || github.sha }}
305326
token: ${{ secrets.CHECKOUT_TOKEN || github.event.repository.private == true && secrets.DATAVISYN_BOT_REPO_TOKEN || github.token }}
306327

307-
- name: Checkout github-workflows repository
308-
uses: actions/checkout@v5
309-
with:
310-
repository: datavisyn/github-workflows
311-
ref: ${{ env.WORKFLOW_BRANCH }}
312-
path: ./tmp/github-workflows
313-
314328
- name: Configure AWS Credentials
315329
uses: aws-actions/[email protected]
316330
with:
@@ -325,9 +339,8 @@ jobs:
325339
shell: bash
326340
id: test-images
327341
run: |
328-
hooks_folder="$(realpath -m "./deploy/build/${{ matrix.flavor.directory }}/hooks")"
329-
test_images_hook="$hooks_folder/test-images.sh"
330-
test_images_report="$hooks_folder/test-images-report"
342+
test_images_hook=$(jq -r '.test_images.script_path' <<< "$FLAVOR")
343+
test_images_report=$(jq -r '.test_images.report_path' <<< "$FLAVOR")
331344
332345
if [[ -f "$test_images_hook" ]]; then
333346
# Iterate through all components and store their image ref in an environment variable
@@ -340,15 +353,17 @@ jobs:
340353
export "IMAGE_${name_upper}=${image_ref}"
341354
done;
342355
343-
# Create report folder to avoid any downstream Docker volume issues
344-
# TODO: For some reason this doesn't work yet, i.e. if a docker-compose script mounts a volume here, nothing shows up...
356+
# Create a directory to store the report results
345357
mkdir -p "$test_images_report"
346-
chmod 777 "$test_images_report"
347-
echo "test_images_report=${test_images_report}" >> "$GITHUB_OUTPUT"
348358
349359
echo "Run $test_images_hook"
350360
chmod +x "$test_images_hook"
351361
bash "$test_images_hook"
362+
363+
# If the report folder is not empty, we store it as output
364+
if [[ -n "$(ls -A "$test_images_report")" ]]; then
365+
echo "test_images_report=${test_images_report}" >> "$GITHUB_OUTPUT"
366+
fi
352367
else
353368
echo "No $test_images_hook found, skipping tests."
354369
fi
@@ -369,11 +384,13 @@ jobs:
369384
retag-images:
370385
name: Retag images of flavor ${{ matrix.flavor.id || 'default' }}
371386
needs: [get-flavors, test-images]
372-
if: ${{ inputs.skip_push != true }}
387+
# Skip in case we would have an empty matrix. Note that in this case it also skips all downstream jobs...
388+
# We need the always() && !cancelled() && !failure() because the test-images may have been skipped (which is fine). See https://github.com/actions/runner/issues/491#issuecomment-1507495166
389+
if: ${{ always() && !cancelled() && !failure() && toJSON(fromJson(needs.get-flavors.outputs.result).flavorsToRetag) != '[]' }}
373390
strategy:
374391
fail-fast: false
375392
matrix:
376-
flavor: ${{ fromJson(needs.get-flavors.outputs.result).flavors }}
393+
flavor: ${{ fromJson(needs.get-flavors.outputs.result).flavorsToRetag }}
377394
# Do not run this on self-hosted, as it is faster and shouldn't be blocking anything
378395
# runs-on: ${{ inputs.runs_on || 'ubuntu-22.04' }}
379396
runs-on: "ubuntu-22.04"
@@ -410,7 +427,7 @@ jobs:
410427
echo "image_tag=$image_tag"
411428
echo "image_tag_branch_name=$image_tag_branch_name"
412429
413-
for repository_name in $(jq -r '.ecr_respositories[]' <<< "$FLAVOR"); do
430+
for repository_name in $(jq -r '.ecr_repositories[]' <<< "$FLAVOR"); do
414431
IMAGE_META=$(aws ecr describe-images --repository-name "$repository_name" --image-ids imageTag="$image_tag" --output json | jq --arg var "${image_tag_branch_name}" '.imageDetails[0].imageTags | index( $var )')
415432
if [[ -z "${IMAGE_META}" || ${IMAGE_META} == "null" ]]; then
416433
MANIFEST=$(aws ecr batch-get-image --repository-name "$repository_name" --image-ids imageTag="$image_tag" --output json | jq --raw-output --join-output '.images[0].imageManifest')
@@ -428,9 +445,9 @@ jobs:
428445

429446
push-to-repositories:
430447
name: Push images to push targets
431-
# if? When should we do this? Always? Only for certain branches? If so, how should we define that, in the config.json?
432-
if: ${{ inputs.skip_push != true && fromJson(needs.get-flavors.outputs.result).push_to != '' }}
433448
needs: [retag-images, get-flavors]
449+
# if? When should we do this? Always? Only for certain branches? If so, how should we define that, in the config.json?
450+
if: ${{ fromJson(needs.get-flavors.outputs.result).skip_push != true && fromJson(needs.get-flavors.outputs.result).push_to != '' }}
434451
uses: datavisyn/github-workflows/.github/workflows/build-docker-artifacts-trigger-push.yml@main
435452
secrets: inherit
436453
with:

0 commit comments

Comments
 (0)