Skip to content

Commit 4bda8af

Browse files
committed
RHOAIENG-20088: chore(GHA CI): check images size change
Enhances our existing ci scripts for the params.env and existing runtimes definitions with the actual image size check - we have preset expected size for each of the image and we check that this size isn't changed too much. With this implementation we are checking the compressed image size to avoid the image download. https://issues.redhat.com/browse/RHOAIENG-20088
1 parent b5af841 commit 4bda8af

File tree

2 files changed

+187
-19
lines changed

2 files changed

+187
-19
lines changed

ci/check-params-env.sh

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ PARAMS_ENV_PATH="manifests/base/params.env"
2727
# images we want to have in the `params.env` file.
2828
EXPECTED_NUM_RECORDS=21
2929

30+
# Size change tresholds:
31+
# Max percentual change
32+
SIZE_PERCENTUAL_TRESHOLD=10
33+
# Max absolute change in MB
34+
SIZE_ABSOLUTE_TRESHOLD=100
35+
3036
# ---------------------------- DEFINED FUNCTIONS ----------------------------- #
3137

3238
function check_variables_uniq() {
@@ -80,95 +86,114 @@ function check_variables_uniq() {
8086
return "${ret_code}"
8187
}
8288

83-
function check_image_variable_matches_name_and_commitref() {
89+
function check_image_variable_matches_name_and_commitref_and_size() {
8490
local image_variable="${1}"
8591
local image_name="${2}"
8692
local image_commitref="${3}"
8793
local openshift_build_name="${4}"
94+
local actual_img_size="${5}"
8895

8996
local expected_name
9097
local expected_commitref
91-
local expected_build_name # Why some of the images has `-amd64` suffix and others not?
98+
local expected_build_name
99+
local expected_img_size
100+
92101
case "${image_variable}" in
93102
odh-minimal-notebook-image-n)
94103
expected_name="odh-notebook-jupyter-minimal-ubi9-python-3.11"
95104
expected_commitref="2024b"
96105
expected_build_name="jupyter-minimal-ubi9-python-3.11-amd64"
106+
expected_img_size=520
97107
;;
98108
odh-minimal-notebook-image-n-1)
99109
expected_name="odh-notebook-jupyter-minimal-ubi9-python-3.9"
100110
expected_commitref="2024a"
101111
expected_build_name="jupyter-minimal-ubi9-python-3.9-amd64"
112+
expected_img_size=503
102113
;;
103114
odh-minimal-gpu-notebook-image-n)
104115
expected_name="odh-notebook-jupyter-minimal-ubi9-python-3.11"
105116
expected_commitref="2024b"
106117
expected_build_name="cuda-jupyter-minimal-ubi9-python-3.11-amd64"
118+
expected_img_size=5157
107119
;;
108120
odh-minimal-gpu-notebook-image-n-1)
109121
expected_name="odh-notebook-jupyter-minimal-ubi9-python-3.9"
110122
expected_commitref="2024a"
111123
expected_build_name="cuda-jupyter-minimal-ubi9-python-3.9-amd64"
124+
expected_img_size=5718
112125
;;
113126
odh-pytorch-gpu-notebook-image-n)
114127
expected_name="odh-notebook-jupyter-pytorch-ubi9-python-3.11"
115128
expected_commitref="2024b"
116129
expected_build_name="jupyter-pytorch-ubi9-python-3.11-amd64"
130+
expected_img_size=8571
117131
;;
118132
odh-pytorch-gpu-notebook-image-n-1)
119133
expected_name="odh-notebook-jupyter-pytorch-ubi9-python-3.9"
120134
expected_commitref="2024a"
121135
expected_build_name="jupyter-pytorch-ubi9-python-3.9-amd64"
136+
expected_img_size=9037
122137
;;
123138
odh-generic-data-science-notebook-image-n)
124139
expected_name="odh-notebook-jupyter-datascience-ubi9-python-3.11"
125140
expected_commitref="2024b"
126141
expected_build_name="jupyter-datascience-ubi9-python-3.11-amd64"
142+
expected_img_size=961
127143
;;
128144
odh-generic-data-science-notebook-image-n-1)
129145
expected_name="odh-notebook-jupyter-datascience-ubi9-python-3.9"
130146
expected_commitref="2024a"
131147
expected_build_name="jupyter-datascience-ubi9-python-3.9-amd64"
148+
expected_img_size=904
132149
;;
133150
odh-tensorflow-gpu-notebook-image-n)
134151
expected_name="odh-notebook-cuda-jupyter-tensorflow-ubi9-python-3.11"
135152
expected_commitref="2024b"
136153
expected_build_name="cuda-jupyter-tensorflow-ubi9-python-3.11-amd64"
154+
expected_img_size=8211
137155
;;
138156
odh-tensorflow-gpu-notebook-image-n-1)
139157
expected_name="odh-notebook-cuda-jupyter-tensorflow-ubi9-python-3.9"
140158
expected_commitref="2024a"
141159
expected_build_name="cuda-jupyter-tensorflow-ubi9-python-3.9-amd64"
160+
expected_img_size=6667
142161
;;
143162
odh-trustyai-notebook-image-n)
144163
expected_name="odh-notebook-jupyter-trustyai-ubi9-python-3.11"
145164
expected_commitref="2024b"
146165
expected_build_name="jupyter-trustyai-ubi9-python-3.11-amd64"
166+
expected_img_size=4197
147167
;;
148168
odh-trustyai-notebook-image-n-1)
149169
expected_name="odh-notebook-jupyter-trustyai-ubi9-python-3.9"
150170
expected_commitref="2024a"
151171
expected_build_name="jupyter-trustyai-ubi9-python-3.9-amd64"
172+
expected_img_size=1158
152173
;;
153174
odh-codeserver-notebook-image-n)
154175
expected_name="odh-notebook-code-server-ubi9-python-3.11"
155176
expected_commitref="2024b"
156177
expected_build_name="codeserver-ubi9-python-3.11-amd64"
178+
expected_img_size=893
157179
;;
158180
odh-codeserver-notebook-image-n-1)
159181
expected_name="odh-notebook-code-server-ubi9-python-3.9"
160182
expected_commitref="2024a"
161183
expected_build_name="codeserver-ubi9-python-3.9-amd64"
184+
expected_img_size=850
162185
;;
163186
odh-rstudio-notebook-image-n)
164187
expected_name="odh-notebook-rstudio-server-c9s-python-3.11"
165188
expected_commitref="2024b"
166189
expected_build_name="rstudio-c9s-python-3.11-amd64"
190+
expected_img_size=1242
167191
;;
168192
odh-rstudio-notebook-image-n-1)
169193
expected_name="odh-notebook-rstudio-server-c9s-python-3.9"
170194
expected_commitref="2024a"
171195
expected_build_name="rstudio-c9s-python-3.9-amd64"
196+
expected_img_size=1208
172197
;;
173198
# For both RStudio GPU workbenches - the final name labels are identical to plain RStudio ones
174199
# This is because the very same RStudio Dockerfile is used but different base images in both cases
@@ -177,26 +202,31 @@ function check_image_variable_matches_name_and_commitref() {
177202
expected_name="odh-notebook-rstudio-server-c9s-python-3.11"
178203
expected_commitref="2024b"
179204
expected_build_name="cuda-rstudio-c9s-python-3.11-amd64"
205+
expected_img_size=7184
180206
;;
181207
odh-rstudio-gpu-notebook-image-n-1)
182208
expected_name="odh-notebook-rstudio-server-c9s-python-3.9"
183209
expected_commitref="2024a"
184210
expected_build_name="cuda-rstudio-c9s-python-3.9-amd64"
211+
expected_img_size=7129
185212
;;
186213
odh-rocm-minimal-notebook-image-n)
187214
expected_name="odh-notebook-jupyter-minimal-ubi9-python-3.11"
188215
expected_commitref="2024b"
189216
expected_build_name="rocm-jupyter-minimal-ubi9-python-3.11-amd64"
217+
expected_img_size=4830
190218
;;
191219
odh-rocm-pytorch-notebook-image-n)
192220
expected_name="odh-notebook-jupyter-rocm-pytorch-ubi9-python-3.11"
193221
expected_commitref="2024b"
194222
expected_build_name="rocm-jupyter-pytorch-ubi9-python-3.11-amd64"
223+
expected_img_size=6571
195224
;;
196225
odh-rocm-tensorflow-notebook-image-n)
197226
expected_name="odh-notebook-jupyter-rocm-tensorflow-ubi9-python-3.11"
198227
expected_commitref="2024b"
199228
expected_build_name="rocm-jupyter-tensorflow-ubi9-python-3.11-amd64"
229+
expected_img_size=5782
200230
;;
201231
*)
202232
echo "Unimplemented variable name: '${image_variable}'"
@@ -217,6 +247,22 @@ function check_image_variable_matches_name_and_commitref() {
217247
echo "Image URL points to an incorrect image: expected OPENSHIFT_BUILD_NAME '${expected_build_name}'; actual '${openshift_build_name}'"
218248
return 1
219249
}
250+
251+
# Check the size change constraints now
252+
# 1. Percentual size change
253+
percent_change=$((100 * actual_img_size / expected_img_size - 100))
254+
abs_percent_change=${percent_change#-*}
255+
test ${abs_percent_change} -le ${SIZE_PERCENTUAL_TRESHOLD} || {
256+
echo "Image size changed by ${abs_percent_change}% (expected: ${expected_img_size} MB; actual: ${actual_img_size} MB; treshold: ${SIZE_PERCENTUAL_TRESHOLD}%)."
257+
return 1
258+
}
259+
# 2. Absolute size change
260+
size_difference=$((actual_img_size - expected_img_size))
261+
abs_size_difference=${size_difference#-*}
262+
test ${abs_size_difference} -le ${SIZE_ABSOLUTE_TRESHOLD} || {
263+
echo "Image size changed by ${abs_size_difference} MB (expected: ${expected_img_size} MB; actual: ${actual_img_size} MB; treshold: ${SIZE_ABSOLUTE_TRESHOLD} MB)."
264+
return 1
265+
}
220266
}
221267

222268
function check_image_commit_id_matches_metadata() {
@@ -249,29 +295,29 @@ function check_image() {
249295

250296
echo "Checking metadata for image '${image_variable}' with URL '${image_url}'"
251297

252-
local image_metadata
298+
local image_metadata_config
253299
local image_name
254300
local image_commit_id
255301
local image_commitref
256302
local image_created
257303

258-
image_metadata="$(skopeo inspect --config "docker://${image_url}")" || {
259-
echo "Couldn't download image metadata with skopeo tool!"
304+
image_metadata_config="$(skopeo inspect --config "docker://${image_url}")" || {
305+
echo "Couldn't download image config metadata with skopeo tool!"
260306
return 1
261307
}
262-
image_name=$(echo "${image_metadata}" | jq --raw-output '.config.Labels.name') || {
308+
image_name=$(echo "${image_metadata_config}" | jq --raw-output '.config.Labels.name') || {
263309
echo "Couldn't parse '.config.Labels.name' from image metadata!"
264310
return 1
265311
}
266-
image_commit_id=$(echo "${image_metadata}" | jq --raw-output '.config.Labels."io.openshift.build.commit.id"') || {
312+
image_commit_id=$(echo "${image_metadata_config}" | jq --raw-output '.config.Labels."io.openshift.build.commit.id"') || {
267313
echo "Couldn't parse '.config.Labels."io.openshift.build.commit.id"' from image metadata!"
268314
return 1
269315
}
270-
image_commitref=$(echo "${image_metadata}" | jq --raw-output '.config.Labels."io.openshift.build.commit.ref"') || {
316+
image_commitref=$(echo "${image_metadata_config}" | jq --raw-output '.config.Labels."io.openshift.build.commit.ref"') || {
271317
echo "Couldn't parse '.config.Labels."io.openshift.build.commit.ref"' from image metadata!"
272318
return 1
273319
}
274-
image_created=$(echo "${image_metadata}" | jq --raw-output '.created') || {
320+
image_created=$(echo "${image_metadata_config}" | jq --raw-output '.created') || {
275321
echo "Couldn't parse '.created' from image metadata!"
276322
return 1
277323
}
@@ -280,7 +326,7 @@ function check_image() {
280326
local build_name_raw
281327
local openshift_build_name
282328

283-
config_env=$(echo "${image_metadata}" | jq --raw-output '.config.Env') || {
329+
config_env=$(echo "${image_metadata_config}" | jq --raw-output '.config.Env') || {
284330
echo "Couldn't parse '.config.Env' from image metadata!"
285331
return 1
286332
}
@@ -293,15 +339,38 @@ function check_image() {
293339
return 1
294340
}
295341

342+
local image_metadata
343+
local image_size
344+
local image_size_mb
345+
346+
image_metadata="$(skopeo inspect --raw "docker://${image_url}")" || {
347+
echo "Couldn't download image metadata with skopeo tool!"
348+
return 1
349+
}
350+
# Here we get the image size as a compressed image. This differs to what we gather in
351+
# 'tests/containers/base_image_test.py#test_image_size_change' where we check against the extracted image size.
352+
# There is no actual reason to compare these different sizes except that in this case we want to do check the
353+
# image remotely, whereas in the othe test, we have the image present locally on the machine.
354+
image_size=$(echo "${image_metadata}" | jq '[ .layers[].size ] | add') || {
355+
echo "Couldn't count image size from image metadata!"
356+
return 1
357+
}
358+
image_size_mb=$((image_size / 1024 / 1024)) || {
359+
echo "Couldn't count image size from image metadata!"
360+
return 1
361+
}
362+
296363
test -n "${image_name}" || {
297364
echo "Couldn't retrieve the name of the image - got empty value!"
298365
return 1
299366
}
300367

301368
echo "Image name retrieved: '${image_name}'"
302369
echo "Image created: '${image_created}'"
370+
echo "Image size: ${image_size_mb} MB"
303371

304-
check_image_variable_matches_name_and_commitref "${image_variable}" "${image_name}" "${image_commitref}" "${openshift_build_name}" || return 1
372+
check_image_variable_matches_name_and_commitref_and_size "${image_variable}" "${image_name}" "${image_commitref}" \
373+
"${openshift_build_name}" "${image_size_mb}" || return 1
305374

306375
check_image_commit_id_matches_metadata "${image_variable}" "${image_commit_id}" || return 1
307376

@@ -374,4 +443,4 @@ else
374443
echo "The '${PARAMS_ENV_PATH}' file isn't valid, please check above!"
375444
fi
376445

377-
exit "${ret_code}"
446+
exit "${ret_code}"

0 commit comments

Comments
 (0)