mirror of
				https://github.com/flatcar/scripts.git
				synced 2025-10-31 08:11:03 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			286 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			286 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
| #!/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 BRIGHTBOX_CLIENT_ID --env BRIGHTBOX_CLIENT_SECRET \
 | |
|       --env AKAMAI_TOKEN \
 | |
|       -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
 | |
| }
 | |
| # --
 |