-
Notifications
You must be signed in to change notification settings - Fork 52
/
garbage_collect.sh
285 lines (252 loc) · 10.8 KB
/
garbage_collect.sh
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
#!/bin/bash
#
# Copyright (c) 2021 The Flatcar Maintainers.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# >>> This file is supposed to be SOURCED from the repository ROOT. <<<
#
# garbage_collect() should be called after sourcing.
#
# The garbage collector will remove artifacts of all NON-RELEASE versions from the build cache
# which BOTH
# * exceed the number of builds to keep (defaults to 50)
# AND
# * are older than the minimum purge age (14 days by default)
#
# Note that the min age threshold can lead to MORE than 50 builds being kept if this script
# is run with its default values.
#
# Additionally, the garbage collector will remove all artifacts and directories that do not have
# a version TAG in the scripts repository.
#
# OPTIONAL INPUT
# - Number of (recent) versions to keep. Defaults to 50.
# Explicitly setting this value will reset the minimum age (see below) to 0 days.
# - Minimum age of version tag to be purged, in days. Defaults to 14.
# Only artifacts older than this AND exceeding the builds to keep threshold
# will be removed.
# - PURGE_VERSIONS (Env variable). Space-separated list of versions to purge
# instead of all but the 50 most recent ones.
# Setting this will IGNORE minimum age and number of versions to keep.
# NOTE that only dev versions (not official releases) may be specified.
# This is to prevent accidental deletion of official release tags from the git repo.
# - DRY_RUN (Env variable). Set to "y" to just list what would be done but not
# actually purge anything.
# Flatcar CI automation garbage collector.
# This script removes development (non-official) build artifacts:
# - SDK tarballs, build step containers, and vendor images on buildcache
# - SDK containers built via Github actions (e.g. from PRs).
# See https://github.com/flatcar/scripts/blob/main/.github/workflows/update-sdk.yaml
# - tags from the scripts repository
#
# Garbage collection is based on development (non-official) version tags
# in the scripts repo. The newest 50 builds will be retained,
# all older builds will be purged (50 is the default, see OPTIONAL INPUT above).
function garbage_collect() {
# Run a subshell, so the traps, environment changes and global
# variables are not spilled into the caller.
(
set -euo pipefail
_garbage_collect_impl "${@}"
)
}
# --
function _garbage_collect_impl() {
local keep="${1:-}"
local min_age_days="${2:-}"
local dry_run="${DRY_RUN:-}"
local purge_versions="${PURGE_VERSIONS:-}"
# Set defaults; user-provided 'keep' has priority over default 'min_age_days'
if [ -n "${keep}" -a -z "${min_age_days}" ] ; then
min_age_days="0"
elif [ -z "${keep}" ] ; then
keep="50"
fi
if [ -z "${min_age_days}" ] ; then
min_age_days="14"
fi
local min_age_date="$(date -d "${min_age_days} days ago" +'%Y-%m-%d')"
echo "######## Garbage collector starting ########"
echo
if [ -z "${purge_versions}" ] ; then
echo "Number of versions to keep: '${keep}'"
echo "Keep newer than: '${min_age_date}' (overrides number of versions to keep)"
fi
echo
if [ -z "${purge_versions}" ] ; then
# Generate a list "<timestamp> | <tagname>" from all repo tags that look like dev versions
local versions_detected="$(git tag -l --sort=-committerdate \
--format="%(creatordate:format:%Y-%m-%d) | %(refname:strip=2)" \
| grep -E '.*\| (main|alpha|beta|stable|lts)-[0-9]+\.[0-9]+\.[0-9]+-.*' \
| grep -vE '(-pro)$')"
echo "######## Full list of version(s) and their creation dates ########"
echo
echo "${versions_detected}" | awk '{printf "%5d %s\n", NR, $0}'
# Filter minimum number of versions to keep, min age
purge_versions="$(echo "${versions_detected}" \
| awk -v keep="${keep}" -v min_age="${min_age_date}" '{
if (keep > 0) {
keep = keep - 1
next
}
if ($1 > min_age)
next
print $3
}')"
else
# User-provided version list, make sure we only accept dev versions
purge_versions="$(echo "${purge_versions}" | sed 's/ /\n/g' \
| grep -E '(main|alpha|beta|stable|lts)-[0-9]+\.[0-9]+\.[0-9]+\-.*' \
| grep -vE '(-pro)$')"
keep=0
fi
source ci-automation/ci_automation_common.sh
local sshcmd="$(gen_sshcmd)"
echo
echo "######## The following version(s) will be purged ########"
if [ "$dry_run" = "y" ] ; then
echo
echo "(NOTE this is just a dry run since DRY_RUN=y)"
echo
fi
echo "${purge_versions}" | awk '{if ($0 == "") next; printf "%5d %s\n", NR, $0}'
echo
echo
local version
for version in ${purge_versions}; do
echo "--------------------------------------------"
echo
echo "#### Processing version '${version}' ####"
echo
git checkout "${version}" -- sdk_container/.repo/manifests/version.txt
source sdk_container/.repo/manifests/version.txt
# Assuming that the SDK build version also has the same OS version
local os_vernum="${FLATCAR_VERSION}"
local os_docker_vernum="$(vernum_to_docker_image_version "${FLATCAR_VERSION}")"
# Remove container image tarballs and SDK tarball (if applicable)
# Keep in sync with "orphaned directories" clean-up below.
local rmpat=""
rmpat="${BUILDCACHE_PATH_PREFIX}/sdk/*/${os_vernum}/"
rmpat="${rmpat} ${BUILDCACHE_PATH_PREFIX}/containers/${os_docker_vernum}/flatcar-sdk-*"
rmpat="${rmpat} ${BUILDCACHE_PATH_PREFIX}/containers/${os_docker_vernum}/flatcar-packages-*"
rmpat="${rmpat} ${BUILDCACHE_PATH_PREFIX}/boards/*/${os_vernum}/"
rmpat="${rmpat} ${BUILDCACHE_PATH_PREFIX}/containers/${os_docker_vernum}/flatcar-images-*"
rmpat="${rmpat} ${BUILDCACHE_PATH_PREFIX}/images/*/${os_vernum}/"
rmpat="${rmpat} ${BUILDCACHE_PATH_PREFIX}/testing/${os_vernum}/"
echo "## The following files will be removed ##"
$sshcmd "${BUILDCACHE_USER}@${BUILDCACHE_SERVER}" \
"ls -la ${rmpat} || true"
if [ "$dry_run" != "y" ] ; then
set -x
$sshcmd "${BUILDCACHE_USER}@${BUILDCACHE_SERVER}" \
"rm -rf ${rmpat}"
set +x
else
echo "## (DRY_RUN=y so not doing anything) ##"
fi
# Remove container image directory if empty
#
rmpat="${BUILDCACHE_PATH_PREFIX}/containers/${os_docker_vernum}/"
echo "## Checking if container directory is empty and can be removed (it's OK if this fails) ##"
echo "## The following directory will be removed if below output is empty: '${rmpat}' ##"
$sshcmd "${BUILDCACHE_USER}@${BUILDCACHE_SERVER}" \
"ls -la ${rmpat} || true"
if [ "$dry_run" != "y" ] ; then
set -x
$sshcmd "${BUILDCACHE_USER}@${BUILDCACHE_SERVER}" \
"rmdir ${rmpat} || true"
set +x
else
echo "## (DRY_RUN=y so not doing anything) ##"
fi
# Remove git tag (local and remote)
#
echo "## The following TAG will be deleted: '${version}' ##"
if [ "$dry_run" != "y" ] ; then
set -x
git tag -d "${version}"
git push --delete origin "${version}"
set +x
else
echo "## (DRY_RUN=y so not doing anything) ##"
fi
done
echo
echo "########################################"
echo
echo Checking for orphaned directories
echo
local dir=""
for dir in "sdk/amd64" \
"containers" \
"boards/amd64-usr" \
"boards/arm64-usr" \
"images/amd64" \
"images/arm64" \
"testing" \
; do
local fullpath="${BUILDCACHE_PATH_PREFIX}/${dir}"
echo
echo "## Processing '${fullpath}'"
echo "---------------------------"
local version=""
for version in $($sshcmd "${BUILDCACHE_USER}@${BUILDCACHE_SERVER}" "ls -1 ${BUILDCACHE_PATH_PREFIX}/${dir}"); do
if [ "${dir}" = "containers" ] && echo "${version/+/-}" | grep -qE '.*-github-.*'; then
echo "Ignoring github CI SDK container in '${fullpath}/${version}'."
echo "Github CI SDK artifacts are handled by 'garbage_collect_github_ci_sdk.sh'"
echo " in a later step".
continue
fi
if ! git tag -l | grep -q "${version/+/-}"; then
local o_fullpath="${fullpath}/${version}"
echo
echo "## No tag '${version/+/-}' for orphan directory '${o_fullpath}'; removing."
echo "## The following files will be removed ##"
$sshcmd "${BUILDCACHE_USER}@${BUILDCACHE_SERVER}" \
"ls -la ${o_fullpath} || true"
if [ "$dry_run" != "y" ] ; then
set -x
$sshcmd "${BUILDCACHE_USER}@${BUILDCACHE_SERVER}" \
"rm -rf ${o_fullpath} || true"
set +x
else
echo "## (DRY_RUN=y so not doing anything) ##"
fi
echo
fi
done
done
echo
echo "########################################"
echo
echo Running cloud garbage collector
echo
local mantle_ref
mantle_ref=$(cat sdk_container/.repo/manifests/mantle-container)
docker run --pull always --rm --net host \
--env AZURE_AUTH_CREDENTIALS --env AZURE_PROFILE \
--env AWS_ACCESS_KEY_ID --env AWS_SECRET_ACCESS_KEY \
--env AWS_CREDENTIALS \
--env DIGITALOCEAN_TOKEN_JSON \
--env EQUINIXMETAL_KEY --env EQUINIXMETAL_PROJECT \
--env GCP_JSON_KEY \
--env VMWARE_ESX_CREDS \
--env OPENSTACK_CREDS \
--env BRIGHTBOX_CLIENT_ID --env BRIGHTBOX_CLIENT_SECRET \
-w /work -v "$PWD":/work "${mantle_ref}" /work/ci-automation/garbage_collect_cloud.sh
echo
echo "#############################################"
echo
echo Running Github CI SDK garbage collector
echo
source ci-automation/garbage_collect_github_ci_sdk.sh
garbage_collect_github_ci 1 "${min_age_days}"
echo
echo "########################################"
echo
echo Running Release Artifacts cache garbage collector
echo
source ci-automation/garbage_collect_releases.sh
garbage_collect_releases
}
# --