|
| 1 | +#!/bin/sh |
| 2 | +#/ |
| 3 | +#/ NAME: |
| 4 | +#/ delete-empty-repos - For a GitHub Enterprise Instance, lists every empty repository |
| 5 | +#/ in format <organization>:<repository> and deletes them if option is passed. |
| 6 | +#/ |
| 7 | +#/ AUTHOR: @IAmHughes |
| 8 | +#/ |
| 9 | +#/ SYNOPSIS: |
| 10 | +#/ delete-empty-repos.sh [--org=MyOrganization] [--execute=TRUE] |
| 11 | +#/ |
| 12 | +#/ DESCRIPTION: |
| 13 | +#/ For a GitHub Enterprise Instance, lists every empty repository in format |
| 14 | +#/ <organization>:<repository> separated by new lines. Deleting them if passed |
| 15 | +#/ the option [--execute=true]. "Empty" meaning any repository with a zero size |
| 16 | +#/ attribute, i.e. initialized only or those with no content at all. |
| 17 | +#/ - Example Output: List all empty repositories |
| 18 | +#/ <organization>:<repository1> |
| 19 | +#/ <organization>:<repository2> |
| 20 | +#/ <organization>:<repository3> |
| 21 | +#/ |
| 22 | +#/ PRE-REQUISITES: |
| 23 | +#/ Before running this script, you must create a Personal Access Token (PAT) |
| 24 | +#/ at https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/ |
| 25 | +#/ with the permissions <repo> and <admin:org> scopes and <delete_repo>. Read more |
| 26 | +#/ about scopes here: https://developer.github.com/apps/building-oauth-apps/scopes-for-oauth-apps/ |
| 27 | +#/ |
| 28 | +#/ Once created, you must export your PAT as an environment variable |
| 29 | +#/ named <GITHUB_TOKEN>. |
| 30 | +#/ - Exporting PAT as GITHUB_TOKEN |
| 31 | +#/ $ export GITHUB_TOKEN=abcd1234efg567 |
| 32 | +#/ |
| 33 | +#/ Additionally you will need to set the $API_ROOT at the top of the script to |
| 34 | +#/ your instance of GitHub Enterprise. |
| 35 | +#/ - _i.e._: https://MyGitHubEnterprise.com/api/v3 |
| 36 | +#/ |
| 37 | +#/ Finally, you will need to ensure you have installed jq: https://stedolan.github.io/jq/ |
| 38 | +#/ |
| 39 | +#/ OPTIONS: |
| 40 | +#/ --org |
| 41 | +#/ -o |
| 42 | +#/ When running the tool, this flag sets which organization's repositories you |
| 43 | +#/ want to inspect and delete (if they're empty). |
| 44 | +#/ |
| 45 | +#/ --execute |
| 46 | +#/ -e |
| 47 | +#/ When running the tool, this flag will delete every repo listed. |
| 48 | +#/ * _NOTE:_ You should run the script without this option first, verifying |
| 49 | +#/ that you want to delete every repository listed. |
| 50 | +#/ |
| 51 | +#/ EXAMPLES: |
| 52 | +#/ |
| 53 | +#/ - Lists all empty repositories for the given organization. |
| 54 | +#/ $ bash delete-empty-repos.sh --org=MyOrganization |
| 55 | +#/ |
| 56 | +#/ - Deletes all empty repositories for the given organization. |
| 57 | +#/ $ bash delete-empty-repos.sh --org=MyOrganization --execute=TRUE |
| 58 | +#/ |
| 59 | +#/ API DOCUMENTATION: |
| 60 | +#/ All documentation can be found at https://developer.github.com/v3/ |
| 61 | + |
| 62 | +########## |
| 63 | +# HEADER # |
| 64 | +########## |
| 65 | + |
| 66 | +echo "" |
| 67 | +echo "############################################" |
| 68 | +echo "############################################" |
| 69 | +echo "### ###" |
| 70 | +echo "### Delete Empty Repos from Organization ###" |
| 71 | +echo "### ###" |
| 72 | +echo "############################################" |
| 73 | +echo "############################################" |
| 74 | +echo "" |
| 75 | + |
| 76 | +######## |
| 77 | +# VARS # |
| 78 | +######## |
| 79 | +API_ROOT="https://<your-domain>/api/v3" |
| 80 | +EXECUTE="FALSE" |
| 81 | +EMPTY_REPO_COUNTER=0 |
| 82 | + |
| 83 | +################################## |
| 84 | +# Parse options/flags passed in. # |
| 85 | +################################## |
| 86 | + |
| 87 | +for param in "$@" |
| 88 | +do |
| 89 | + case $param in |
| 90 | + -e=*|--execute=*) |
| 91 | + EXECUTE="${param#*=}" |
| 92 | + shift |
| 93 | + ;; |
| 94 | + -o=*|--org=*) |
| 95 | + ORG_NAME="${param#*=}" |
| 96 | + shift |
| 97 | + ;; |
| 98 | + *) |
| 99 | + # unknown option, do nothing |
| 100 | + ;; |
| 101 | + esac |
| 102 | +done |
| 103 | + |
| 104 | +################# |
| 105 | +# Verify Inputs # |
| 106 | +################# |
| 107 | + |
| 108 | +# If GITHUB_TOKEN wasn't set in Environment |
| 109 | +if [[ -z ${GITHUB_TOKEN} ]]; then |
| 110 | + echo "ERROR: GITHUB_TOKEN was not found in your environment. You must export " |
| 111 | + echo "this token prior to running the script." |
| 112 | + echo " Ex: export GITHUB_TOKEN=abc123def456" |
| 113 | + echo "" |
| 114 | + echo "Exiting script with no changes." |
| 115 | + echo "" |
| 116 | + exit 1 |
| 117 | +fi |
| 118 | + |
| 119 | +# If ORG_NAME wasn't passed |
| 120 | +if [[ -z ${ORG_NAME} ]]; then |
| 121 | + echo "ERROR: ORG_NAME was not provided." |
| 122 | + echo " Ex: bash delete-empty-repos.sh --org=MyOrganization --execute=TRUE" |
| 123 | + echo "" |
| 124 | + echo "Exiting script with no changes." |
| 125 | + echo "" |
| 126 | + exit 1 |
| 127 | +fi |
| 128 | + |
| 129 | +# If EXECUTE exists, it needs to equal TRUE or FALSE |
| 130 | +if [[ ${EXECUTE} != "TRUE" ]] && [[ ${EXECUTE} != "FALSE" ]]; then |
| 131 | + echo "ERROR: EXECUTE was not set to a proper value." |
| 132 | + echo " Ex: bash delete-empty-repos.sh --org=MyOrganization --execute=TRUE" |
| 133 | + echo "" |
| 134 | + echo "Exiting script with no changes." |
| 135 | + echo "" |
| 136 | + exit 1 |
| 137 | +fi |
| 138 | + |
| 139 | +if [[ ${EXECUTE} = "TRUE" ]]; then |
| 140 | + echo "Searching for empty repositories within the Organization: "${ORG_NAME} |
| 141 | + echo "EXECUTE was set to TRUE!!! Empty repositories will be deleted!!!" |
| 142 | + echo "You have 5 seconds to cancel this script." |
| 143 | + sleep 5 |
| 144 | +else |
| 145 | + echo "Searching for empty repositories within the Organization: "${ORG_NAME} |
| 146 | + echo "EXECUTE was set to FALSE, no repositories will be deleted." |
| 147 | +fi |
| 148 | + |
| 149 | +################################################## |
| 150 | +# Grab JSON of all repositories for organization # |
| 151 | +################################################## |
| 152 | +echo "Getting a list of the repositories within "${ORG_NAME} |
| 153 | + |
| 154 | +REPO_RESPONSE="$(curl --request GET \ |
| 155 | +--url ${API_ROOT}/orgs/${ORG_NAME}/repos \ |
| 156 | +-s \ |
| 157 | +--header "authorization: Bearer ${GITHUB_TOKEN}" \ |
| 158 | +--header "content-type: application/json")" |
| 159 | + |
| 160 | +########################################################################## |
| 161 | +# Loop through every organization's repo to get repository name and size # |
| 162 | +########################################################################## |
| 163 | +echo "Generating list of empty repositories." |
| 164 | +echo "" |
| 165 | +echo "-------------------" |
| 166 | +echo "| Empty Repo List |" |
| 167 | +echo "| Org : Repo Name |" |
| 168 | +echo "-------------------" |
| 169 | + |
| 170 | +for repo in $(echo "${REPO_RESPONSE}" | jq -r '.[] | @base64'); |
| 171 | +do |
| 172 | + ##################################### |
| 173 | + # Get the info from the json object # |
| 174 | + ##################################### |
| 175 | + get_repo_info() |
| 176 | + { |
| 177 | + echo ${repo} | base64 --decode | jq -r ${1} |
| 178 | + } |
| 179 | + |
| 180 | + # Get the info from the JSON object |
| 181 | + REPO_NAME=$(get_repo_info '.name') |
| 182 | + REPO_SIZE=$(get_repo_info '.size') |
| 183 | + |
| 184 | + # If repository has data, size will not be zero, therefore skip. |
| 185 | + if [[ ${REPO_SIZE} -ne 0 ]]; then |
| 186 | + continue; |
| 187 | + fi |
| 188 | + |
| 189 | + ################################################ |
| 190 | + # If we are NOT deleting repository, list them # |
| 191 | + ################################################ |
| 192 | + if [[ ${EXECUTE} = "FALSE" ]]; then |
| 193 | + echo "${ORG_NAME}:${REPO_NAME}" |
| 194 | + |
| 195 | + # Increment counter |
| 196 | + EMPTY_REPO_COUNTER=$((EMPTY_REPO_COUNTER+1)) |
| 197 | + |
| 198 | + ################################################# |
| 199 | + # EXECUTE is TRUE, we are deleting repositories # |
| 200 | + ################################################# |
| 201 | + elif [[ ${EXECUTE} = "TRUE" ]]; then |
| 202 | + echo "${REPO_NAME} will be deleted from ${ORG_NAME}!" |
| 203 | + |
| 204 | + ############################ |
| 205 | + # Call API to delete repos # |
| 206 | + ############################ |
| 207 | + curl --request DELETE \ |
| 208 | + -s \ |
| 209 | + --url ${API_ROOT}/repos/${ORG_NAME}/${REPO_NAME} \ |
| 210 | + --header "authorization: Bearer ${GITHUB_TOKEN}" |
| 211 | + |
| 212 | + echo "${REPO_NAME} was deleted from ${ORG_NAME} successfully." |
| 213 | + |
| 214 | + # Increment counter |
| 215 | + EMPTY_REPO_COUNTER=$((EMPTY_REPO_COUNTER+1)) |
| 216 | + fi |
| 217 | + |
| 218 | +done |
| 219 | + |
| 220 | +################## |
| 221 | +# Exit Messaging # |
| 222 | +################## |
| 223 | +if [[ ${EXECUTE} = "TRUE" ]]; then |
| 224 | + echo "" |
| 225 | + echo "Successfully deleted ${EMPTY_REPO_COUNTER} empty repos from ${ORG_NAME}." |
| 226 | +else |
| 227 | + echo "" |
| 228 | + echo "Successfully discovered ${EMPTY_REPO_COUNTER} empty repos within ${ORG_NAME}." |
| 229 | +fi |
| 230 | +exit 0 |
0 commit comments