├── .gitignore ├── config-sample.sh ├── LICENSE.md ├── CREDITS.md ├── CHANGELOG.md ├── CONTRIBUTING.md ├── CODE_OF_CONDUCT.md ├── README.md └── clean-registry.sh /.gitignore: -------------------------------------------------------------------------------- 1 | config.sh -------------------------------------------------------------------------------- /config-sample.sh: -------------------------------------------------------------------------------- 1 | # Place this config file in the same directory as clean-registry.sh and name it "config.sh" 2 | 3 | # Gitlab URL 4 | GITLAB_URL="https://gitlab.example.com" 5 | 6 | # Gitlab Personal Access Token 7 | GITLAB_AUTH_TOKEN="xxxxxxxxxxxxx" 8 | 9 | # Gitlab Project ID (can find this number on Project Overview page) 10 | GITLAB_PROJECT_ID="" 11 | 12 | # Gitlab Registry ID. This is per project, so if a project has a single registry, the Registry ID is 1 13 | GITLAB_REGISTRY_ID="" 14 | 15 | # Delete the tag / image if older than this many days 16 | EXPIRATION_DAYS="###" 17 | 18 | # OPTIONAL: Regex for tags/images to include. Anything not matching regex will not be removed 19 | INCLUDE_FOR_DELETION="" 20 | 21 | # OPTIONAL: Regex for tags/images to exclude. Anything matching this regex will not be removed. 22 | # Note - "latest" tag is always retained 23 | EXCLUDE_FROM_DELETION="" 24 | 25 | # Set this to "TRUE" to run the script in test mode, which will do everything except actually delete 26 | # images / tags 27 | DRY_RUN="FALSE" -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 10up 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /CREDITS.md: -------------------------------------------------------------------------------- 1 | The following acknowledges the Maintainers for this repository, those who have Contributed to this repository (via bug reports, code, design, ideas, project management, translation, testing, etc.), and any Libraries utilized. 2 | 3 | ## Maintainers 4 | 5 | The following individuals are responsible for curating the list of issues, responding to pull requests, and ensuring regular releases happen. 6 | 7 | [Jeffrey Paul (@jeffpaul)](https://github.com/jeffpaul). 8 | 9 | ## Contributors 10 | 11 | Thank you to all the people who have already contributed to this repository via bug reports, code, design, ideas, project management, translation, testing, etc. 12 | 13 | [Zachary Brown (@TheLastCicada)](https://github.com/TheLastCicada), [Jeffrey Paul (@jeffpaul)](https://github.com/jeffpaul), [Dmitry Andreev (@kemko)](https://github.com/kemko), [Peter Wilson (@peterwilsoncc)](https://github.com/peterwilsoncc), [Chase Livingston (@chaselivingston)](https://github.com/chaselivingston), [Dustin Rue (@dustinrue)](https://github.com/dustinrue), [Darin Kotter (@dkotter)](https://github.com/dkotter). 14 | 15 | ## Libraries 16 | 17 | The following software libraries are utilized in this repository. 18 | 19 | n/a. 20 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file, per [the Keep a Changelog standard](http://keepachangelog.com/), and will adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 4 | 5 | ## [Unreleased] - TBD 6 | 7 | ## [1.0.2] - 2023-10-23 8 | 9 | ### Changed 10 | 11 | - Call `sed` with the `i` flag for case insensitive replace (props [@kemko](https://github.com/kemko), [@peterwilsoncc](https://github.com/peterwilsoncc), [@chaselivingston](https://github.com/chaselivingston) via [#5](https://github.com/10up/Gitlab-Registry-Cleaner/pull/5)). 12 | 13 | ### Fixed 14 | 15 | - Minor fixes for macOS (props [@dustinrue](https://github.com/dustinrue), [@TheLastCicada](https://github.com/TheLastCicada) via [#3](https://github.com/10up/Gitlab-Registry-Cleaner/pull/3)). 16 | - Avoid errors if there are no images (props [@dustinrue](https://github.com/dustinrue), [@TheLastCicada](https://github.com/TheLastCicada) via [#3](https://github.com/10up/Gitlab-Registry-Cleaner/pull/3)). 17 | 18 | ## [1.0.1] - 2020-09-23 19 | 20 | ### Added 21 | 22 | - Add our default repo files (props [@jeffpaul](https://github.com/jeffpaul), [@TheLastCicada](https://github.com/TheLastCicada) via [#1](https://github.com/10up/Gitlab-Registry-Cleaner/pull/1)). 23 | 24 | ## [1.0.0] - 2020-09-23 25 | 26 | ### Added 27 | 28 | - Initial release of GitLab Registry Cleaner. 29 | 30 | [Unreleased]: https://github.com/10up/Gitlab-Registry-Cleaner/compare/trunk...develop 31 | [1.0.2]: https://github.com/10up/Gitlab-Registry-Cleaner/compare/1.0.1...1.0.2 32 | [1.0.1]: https://github.com/10up/Gitlab-Registry-Cleaner/compare/1.0.0...1.0.1 33 | [1.0.0]: https://github.com/10up/Gitlab-Registry-Cleaner/releases/tag/1.0.0 34 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing and Maintaining 2 | 3 | First, thank you for taking the time to contribute! 4 | 5 | The following is a set of guidelines for contributors as well as information and instructions around our maintenance process. The two are closely tied together in terms of how we all work together and set expectations, so while you may not need to know everything in here to submit an issue or pull request, it's best to keep them in the same document. 6 | 7 | ## Ways to contribute 8 | 9 | Contributing isn't just writing code - it's anything that improves the project. All contributions for GitLab Registry Cleaner are managed right here on GitHub. Here are some ways you can help: 10 | 11 | ### Reporting bugs 12 | 13 | If you're running into an issue, please take a look through [existing issues](https://github.com/10up/Gitlab-Registry-Cleaner/issues) and [open a new one](https://github.com/10up/Gitlab-Registry-Cleaner/issues/new) if needed. If you're able, include steps to reproduce, environment information, and screenshots/screencasts as relevant. 14 | 15 | ### Suggesting enhancements 16 | 17 | New features and enhancements are also managed via [issues](https://github.com/10up/Gitlab-Registry-Cleaner/issues). 18 | 19 | ### Pull requests 20 | 21 | Pull requests represent a proposed solution to a specified problem. They should always reference an issue that describes the problem and contains discussion about the problem itself. Discussion on pull requests should be limited to the pull request itself, i.e. code review. 22 | 23 | For more on how 10up writes and manages code, check out our [10up Engineering Best Practices](https://10up.github.io/Engineering-Best-Practices/). 24 | 25 | ## Workflow 26 | 27 | The `develop` branch is the development branch which means it contains the next version to be released. `trunk` contains the latest released stable version. Always work on the `develop` branch and open up PRs against `develop`. 28 | 29 | ## Release instructions 30 | 31 | 1. Branch: Starting from `develop`, cut a release branch named `release/X.Y.Z` for your changes. 32 | 2. Version bump: Bump the version number in `clean-registry.sh` if it does not already reflect the version being released. 33 | 3. Changelog: Add/update the changelog in `CHANGELOG.md`. 34 | 4. Props: update `CREDITS.md` with any new contributors, confirm maintainers are accurate. 35 | 5. Readme updates: Make any other readme changes as necessary in `README.md`. 36 | 6. Merge: Make a non-fast-forward merge from your release branch to `develop` (or merge the pull request), then do the same for `develop` into `trunk` (`git checkout trunk && git merge --no-ff develop`). `trunk` contains the stable development version. 37 | 7. Push: Push your `trunk` branch to GitHub (e.g. `git push origin trunk`). 38 | 8. Release: Create a [new release](https://github.com/10up/Gitlab-Registry-Cleaner/releases/new), naming the tag and the release with the new version number, and targeting the `trunk` branch. Paste the changelog from `CHANGELOG.md` into the body of the release and include a link to the [closed issues on the milestone](https://github.com/10up/Gitlab-Registry-Cleaner/milestone/#?closed=1). 39 | 9. Close the milestone: Edit the [X.Y.Z milestone](https://github.com/10up/Gitlab-Registry-Cleaner/milestone/#) with release date (in the `Due date (optional)` field) and link to GitHub release (in the `Description` field), then close the milestone. 40 | 10. Punt incomplete items: If any open issues or PRs which were milestoned for `X.Y.Z` do not make it into the release, update their milestone to `X+1.0.0`, `X.Y+1.0`, `X.Y.Z+1`, or `Future Release`. 41 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at opensource@10up.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitLab Registry Cleaner 2 | 3 | > Bash script using the GitLab API to delete images from a GitLab container registry. Supports regex and deleting images older than a specific age. 4 | 5 | [![Support Level](https://img.shields.io/badge/support-stable-blue.svg)](#support-level) [![Release Version](https://img.shields.io/github/release/10up/Gitlab-Registry-Cleaner.svg)](https://github.com/10up/Gitlab-Registry-Cleaner/releases/latest) [![MIT License](https://img.shields.io/github/license/10up/Gitlab-Registry-Cleaner.svg)](https://github.com/10up/Gitlab-Registry-Cleaner/blob/develop/LICENSE.md) 6 | 7 | ## How to Use 8 | Copy `config-sample.sh` to `config.sh` and fill in the variables to match the needs of your project. The `config-sample.sh` file is documented with comments. 9 | 10 | This script uses v4 of the GitLab API. It is tested against a self-hosted GitLab instance and it is unknown if these same commands work on projects hosted on gitlab.com. 11 | 12 | This is a bash script, so a Linux type shell is required to use it. It has been tested in Ubuntu, but it should run fine on MacOS and any version of Linux. 13 | 14 | To run the script, first give it execution permissions: 15 | 16 | `chmod +x clean-registry.sh` 17 | 18 | Running the script: 19 | 20 | `./clean-registry.sh` 21 | 22 | There are no command line arguments for this script and it is configured entirely with the `config.sh` file. 23 | 24 | This script removes the tags from the container registry, but does not actually delete the images (because this is how GitLab works). To delete the images, connect to your GitLab instance (or open a shell inside your GitLab Docker instance) and run the following: 25 | 26 | `gitlab-ctl registry-garbage-collect -m` 27 | 28 | You may need to use `sudo` for that command to work. This will take a while, but afterwards you should see a reduction in the disk space used if you've deleted any Docker images with this script. 29 | 30 | ## Frequently Asked Questions 31 | 32 | ### Why use this instead of GitLab's simliar function? 33 | 34 | GitLab does have an automatic [registry cleanup](https://docs.gitlab.com/ee/user/packages/container_registry/#enable-the-cleanup-policy) function that can be set, and in the future, this built-in cleanup policy may negate the need for this script. For now, we like having the ability to delete images immediately, which is what this script allows us to do. 35 | 36 | ## Support Level 37 | 38 | **Stable:** 10up is not planning to develop any new features for this, but will still respond to bug reports and security concerns. We welcome PRs, but any that include new features should be small and easy to integrate and should not include breaking changes. We otherwise intend to keep this tested up to the most recent version of WordPress. 39 | 40 | ## Changelog 41 | 42 | A complete listing of all notable changes to GitLab Registry Cleaner are documented in [CHANGELOG.md](https://github.com/10up/Gitlab-Registry-Cleaner/blob/develop/CHANGELOG.md). 43 | 44 | ## Contributing 45 | 46 | Please read [CODE_OF_CONDUCT.md](https://github.com/10up/Gitlab-Registry-Cleaner/blob/develop/CODE_OF_CONDUCT.md) for details on our code of conduct, [CONTRIBUTING.md](https://github.com/10up/Gitlab-Registry-Cleaner/blob/develop/CONTRIBUTING.md) for details on the process for submitting pull requests to us, and [CREDITS.md](https://github.com/10up/Gitlab-Registry-Cleaner/blob/develop/CREDITS.md) for a listing of maintainers of, contributors to, and libraries used by GitLab Registry Cleaner. 47 | 48 | ## Like what you see? 49 | 50 | Work with the 10up WordPress Practice at Fueled 51 | -------------------------------------------------------------------------------- /clean-registry.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # # # # # 4 | # 5 | # This script connects to a Gitlab self-hosted instance and cleans a user specified container 6 | # registry. Gitlab has lifecycle rules for registries now, which can accomplish 7 | # much the same thing, but this script is useful when you want to bulk delete 8 | # items immediately. 9 | # 10 | # Configure options for this script in the config.sh file. A sample config file is provided. 11 | # 12 | # Unknown if this works or applies to Gitlab.com. 13 | # 14 | # Author: 10up, Inc. 15 | # Author URI: https://10up.com 16 | # Version: 1.0.2 17 | # License: MIT 18 | # License URI: https://opensource.org/licenses/MIT 19 | # 20 | # # # # # 21 | 22 | set -e 23 | set -u 24 | set -o pipefail 25 | 26 | 27 | # 28 | # Get options from the config file 29 | # 30 | 31 | # Define the path to the config file relative to the main script and include it 32 | DIR="${BASH_SOURCE%/*}" 33 | if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi 34 | . "$DIR/config.sh" 35 | 36 | # If expiration is set less than 1 day, set the seconds to 1 to make all the rest of the math work 37 | if [ ${EXPIRATION_DAYS} -lt 1 ] 38 | then 39 | EXPIRATION_SECONDS=1 40 | fi 41 | 42 | # Check if the required variables are set, or if they are the default values 43 | if [ -z ${GITLAB_URL} ] 44 | then 45 | echo 'ERROR: Required variable GITLAB_URL not set in the config.sh file' 46 | exit 1 47 | fi 48 | if [ ${GITLAB_URL} == 'https://gitlab.example.com' ] 49 | then 50 | echo 'ERROR Required variable GITLAB_URL detected to be the default value in the config.sh file' 51 | exit 1 52 | fi 53 | if [ -z ${GITLAB_AUTH_TOKEN} ] 54 | then 55 | echo 'ERROR: Required variable GITLAB_AUTH_TOKEN not set in the config.sh file' 56 | exit 1 57 | fi 58 | if [ ${GITLAB_AUTH_TOKEN} == 'xxxxxxxxxxxxx' ] 59 | then 60 | echo 'ERROR: Required variable GITLAB_AUTH_TOKEN detected to be the default value in the config.sh file' 61 | exit 1 62 | fi 63 | if [ -z ${GITLAB_PROJECT_ID} ] 64 | then 65 | echo 'ERROR: Required variable GITLAB_PROJECT_ID not set in the config.sh file' 66 | exit 1 67 | fi 68 | if [ ${GITLAB_PROJECT_ID} == '' ] 69 | then 70 | echo 'ERROR: Required variable GITLAB_PROJECT_ID detected to be the default value in the config.sh file' 71 | exit 1 72 | fi 73 | if [ -z ${GITLAB_REGISTRY_ID} ] 74 | then 75 | echo 'ERROR: Required variable GITLAB_REGISTRY_ID not set in the config.sh file' 76 | exit 1 77 | fi 78 | if [ ${GITLAB_REGISTRY_ID} == '' ] 79 | then 80 | echo 'ERROR: Required variable GITLAB_REGISTRY_ID detected to be the default value in the config.sh file' 81 | exit 1 82 | fi 83 | if [ -z ${EXPIRATION_DAYS} ] 84 | then 85 | echo 'ERROR: Required variable EXPIRATION_DAYS not set in the config.sh file' 86 | exit 1 87 | fi 88 | if [ ${EXPIRATION_DAYS} == '###' ] 89 | then 90 | echo 'ERROR: Required variable EXPIRATION_DAYS detected to be the default value in the config.sh file' 91 | exit 1 92 | fi 93 | # Convert DRY_RUN variable to upper case for eaiser comparison 94 | DRY_RUN=$(echo ${DRY_RUN} | tr [a-z] [A-Z]) 95 | 96 | if [ ${DRY_RUN} == 'TRUE' ] 97 | then 98 | echo "~~ Running in dry-run simulation mode ~~" 99 | echo "" 100 | fi 101 | 102 | # 103 | # Convert expiration time into seconds 104 | # 105 | 106 | EXPIRATION_SECONDS=$(expr ${EXPIRATION_DAYS} \* 86400) 107 | 108 | echo "Tags / images older than ${EXPIRATION_SECONDS} seconds (${EXPIRATION_DAYS}) will be deleted" 109 | 110 | # 111 | # Get a list of container names (aka tags), put in an array 112 | # 113 | 114 | # Deal with pagination 115 | thispage=1 #variable for tracking the page we are on 116 | nextpage=1 #variable for tracking the next page (if exists) 117 | declare -a imagenames 118 | while [ ${nextpage} -gt 0 ] 119 | do 120 | echo "Getting image names page ${thispage}..." 121 | # add items to the array 122 | oldifs="$IFS" 123 | IFS=$'\n' 124 | newimagenames=($(curl --silent --location --request GET "${GITLAB_URL}/api/v4/projects/${GITLAB_PROJECT_ID}/registry/repositories/${GITLAB_REGISTRY_ID}/tags/?per_page=500&page=${thispage}" --header "Authorization: Bearer ${GITLAB_AUTH_TOKEN}" | jq '.[].name')) 125 | oldifs="$IFS" 126 | 127 | if [ ! -z "${newimagenames+x}" ]; then 128 | imagenames=("${imagenames[@]-}" "${newimagenames[@]}") 129 | else 130 | echo "Nothing to remove" 131 | exit 0 132 | fi 133 | 134 | # Check if there's another page 135 | nextpage=$(curl -I --silent --location --request GET "${GITLAB_URL}/api/v4/projects/${GITLAB_PROJECT_ID}/registry/repositories/${GITLAB_REGISTRY_ID}/tags/?per_page=500&page=${thispage}" --header "Authorization: Bearer ${GITLAB_AUTH_TOKEN}" | grep -Fi X-Next-Page | sed -r 's/X-Next-Page:\ //i' ) 136 | nextpage="${nextpage//[$'\t\r\n ']}" #clean the variable of extraneous characters 137 | if [ -z ${nextpage} ] 138 | then 139 | nextpage=0 140 | fi 141 | thispage=${nextpage} 142 | 143 | done 144 | 145 | 146 | # Loop through array of image names 147 | for imagename in "${imagenames[@]}" 148 | do 149 | # Go to next iteration of loop if the imagename is blank 150 | if [ -z ${imagename} ] 151 | then 152 | continue 153 | fi 154 | 155 | # Trim quotes from variable 156 | imagename="${imagename%\"}" 157 | imagename="${imagename#\"}" 158 | 159 | # Get the date that the tag was created 160 | created_date=$(curl --silent --location --request GET "${GITLAB_URL}/api/v4/projects/${GITLAB_PROJECT_ID}/registry/repositories/${GITLAB_REGISTRY_ID}/tags/${imagename}" --header "Authorization: Bearer ${GITLAB_AUTH_TOKEN}" | jq '.created_at') 161 | 162 | # Trim quotes from variable 163 | created_date="${created_date%\"}" 164 | created_date="${created_date#\"}" 165 | 166 | # convert the tag date to seconds 167 | if [[ "$(uname)" == "Darwin" ]]; then 168 | # macOS uses BSD date, which doesn't understand -d so we tell it what format 169 | # to convert from. It ignores the remaining data after seconds but issues a 170 | # warning to stderr, we send it to /dev/null 171 | created_date_seconds=$( date -j -f "%Y-%m-%dT%H:%M:%S" "${created_date}" +%s 2> /dev/null) 172 | else 173 | created_date_seconds=$( date -d "${created_date}" +%s ) 174 | fi 175 | 176 | # get today's date in seconds 177 | today_date=$( date +%s ) 178 | 179 | # get seconds between the dates 180 | seconds_between=$( expr ${today_date} - ${created_date_seconds} ) 181 | 182 | # Find out if the image is older than our expiration date and delete if so 183 | if [ ${seconds_between} -gt ${EXPIRATION_SECONDS} ] 184 | then 185 | # Never delete the 'latest' tag 186 | if [ ${imagename} = "latest" ] 187 | then 188 | echo "** ${imagename} not deleted because 'latest' is always preserved **" 189 | # If an exclude regex is specified, use it 190 | elif [[ -n "${EXCLUDE_FROM_DELETION}" ]] && [[ ${imagename} =~ ${EXCLUDE_FROM_DELETION} ]] 191 | then 192 | echo "** ${imagename} excluded from deletion by user defined regex **" 193 | # If an include regex is specified, use it 194 | elif [[ -n "${INCLUDE_FOR_DELETION}" ]] && [[ ${imagename} =~ ${INCLUDE_FOR_DELETION} ]] 195 | then 196 | echo "** deleting image name ${imagename} created at ${created_date} as specified in user defined regex **" 197 | if [ ${DRY_RUN} != "TRUE" ] 198 | then 199 | curl --silent --location --request DELETE "${GITLAB_URL}/api/v4/projects/${GITLAB_PROJECT_ID}/registry/repositories/${GITLAB_REGISTRY_ID}/tags/${imagename}" --header "Authorization: Bearer ${GITLAB_AUTH_TOKEN}" 200 | fi 201 | elif [[ -z "${EXCLUDE_FROM_DELETION}" ]] && [[ -z "${INCLUDE_FOR_DELETION}" ]] 202 | then 203 | echo "** deleting image name ${imagename} created at ${created_date} as no exclude or include regexes specified **" 204 | if [ ${DRY_RUN} != "TRUE" ] 205 | then 206 | curl --silent --location --request DELETE "${GITLAB_URL}/api/v4/projects/${GITLAB_PROJECT_ID}/registry/repositories/${GITLAB_REGISTRY_ID}/tags/${imagename}" --header "Authorization: Bearer ${GITLAB_AUTH_TOKEN}" 207 | fi 208 | # By default, delete everything older than the expiration date 209 | elif [[ -n "${INCLUDE_FOR_DELETION}" ]] && ! [[ ${imagename} =~ ${INCLUDE_FOR_DELETION} ]] 210 | then 211 | echo "** image ${imagename} ignored as it doesn't match the INCLUDE regex" 212 | else 213 | echo "** deleting image ${imagename} as the default policy" 214 | if [ ${DRY_RUN} != "TRUE" ] 215 | then 216 | curl --silent --location --request DELETE "${GITLAB_URL}/api/v4/projects/${GITLAB_PROJECT_ID}/registry/repositories/${GITLAB_REGISTRY_ID}/tags/${imagename}" --header "Authorization: Bearer ${GITLAB_AUTH_TOKEN}" 217 | fi 218 | fi 219 | fi 220 | 221 | 222 | done 223 | 224 | echo "" 225 | echo 'Cleanup Complete. Please run `sudo gitlab-ctl registry-garbage-collect -m` on the Gitlab instance' 226 | echo "to reclaim the space used by these deleted tags and images." 227 | echo "" 228 | --------------------------------------------------------------------------------