|
#!/bin/bash |
|
|
|
# The MIT License (MIT) |
|
# |
|
# Copyright (c) 2013 https://gist.github.com/rbf |
|
# |
|
# Permission is hereby granted, free of charge, to any person obtaining a copy of |
|
# this software and associated documentation files (the "Software"), to deal in |
|
# the Software without restriction, including without limitation the rights to |
|
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
|
# the Software, and to permit persons to whom the Software is furnished to do so, |
|
# subject to the following conditions: |
|
# |
|
# The above copyright notice and this permission notice shall be included in all |
|
# copies or substantial portions of the Software. |
|
# |
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
|
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
|
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
|
|
|
|
### File info: |
|
|
|
CGL_VERSION="v2.0" |
|
CGL_SOURCE="https://raw.github.com/gist/5983134/create_github_labels.sh" |
|
CGL_DOC="https://gist.github.com/rbf/5983134" |
|
|
|
### |
|
|
|
|
|
# # Requirements |
|
# |
|
# Create a "GitHub access token" with "repo" scope at https://github.com/settings/tokens. |
|
# You can use this token either when 1) asked in the interactive mode, 2) as the last |
|
# argument in the direct mode or 3) stored as an ENV variable named 'GITHUB_TOKEN'. In the |
|
# latter case you might want to add this variable in your ~/.bashrc or similar, e.g.: |
|
# |
|
# echo 'export GITHUB_TOKEN=your_token_here' >> ~/.bashrc |
|
# |
|
# |
|
# # Labels and Milestones |
|
# |
|
# The first part of this script defines the necessary functions to communicate with |
|
# the GitHub API (https://developer.github.com/v3/) to manage labels and milestones. |
|
# |
|
# At the bottom of this script, there are the some examples of milestones and labels. |
|
# Comment or uncomment the ones that you'd like to use, and/or create new ones before |
|
# running the script. |
|
# |
|
# |
|
# # Usage |
|
# |
|
# Once the token is available and the wanted labels and milestones are uncommented (see |
|
# above), you can use this script as follows: |
|
# |
|
# ./create_github_labels.sh [repo_owner [repo_name [access_token]]] |
|
# |
|
# The script will ask for the missing parameters interactively. Note that 'repo_owner' |
|
# is the GitHub username of the _owner_ of the repo (which might be a plain user or an |
|
# organization), not your GitHub username (although they will be the same for a repo of |
|
# yours). |
|
# |
|
# |
|
# # Batch usage |
|
# |
|
# To apply this script to several repos at the same time, take a look at the companion |
|
# script 'batch_create_github_labels_and_milestones.sh'. |
|
# |
|
# |
|
# # Logs |
|
# |
|
# This script logs it's activity to a file named 'github_labels_creation.log' in the same |
|
# directory as the script file itself. It contains the list of all 'curl' requests done with |
|
# the corresponding responses. Please note that they include your 'GITHUB_TOKEN' in plain |
|
# text, should that be an issue for you. |
|
# |
|
# |
|
# API_DOC: https://developer.github.com/v3/ |
|
|
|
|
|
# Log functions |
|
|
|
LOG_PREFIX_DEBUG="[DEBUG]" |
|
LOG_PREFIX_INFO="[INFO] " |
|
LOG_PREFIX_WARN="[WARN] " |
|
LOG_PREFIX_ERROR="[ERROR]" |
|
LOG_PREFIX_INPUT=" > " |
|
|
|
GITHUB_LABEL_LOG_FILE="github_labels_creation.log" |
|
|
|
logblankline(){ |
|
echo >> ${GITHUB_LABEL_LOG_FILE} |
|
} |
|
|
|
log(){ |
|
echo $(date +"[%Y-%m-%d %H:%M:%S]") "$@" >> ${GITHUB_LABEL_LOG_FILE} |
|
} |
|
|
|
log-echo(){ |
|
echo "$@" |
|
log "$@" |
|
} |
|
|
|
|
|
# Global functions |
|
|
|
github-request(){ |
|
GITHUB_REQUEST_LOG_MSG="${1}" |
|
GITHUB_REQUEST="${2}" |
|
GITHUB_REQUEST_NEEDS_LOGIN="${3}" |
|
GITHUB_REQUEST_CALLBACK_ON_OK="${4}" |
|
GITHUB_REQUEST_CALLBACK_ON_FAIL="${5}" |
|
GITHUB_REQUEST_RESPONSE_FILE="github_request_response.log" |
|
log |
|
if [ "${GITHUB_REQUEST_NEEDS_LOGIN}" == "needs_login" ] |
|
then |
|
log-echo "${LOG_PREFIX_INFO} ${GITHUB_REQUEST_LOG_MSG}" |
|
echo -n "${LOG_PREFIX_INPUT} " |
|
GITHUB_REQUEST_SUCCESS_STATUS_OK="${LOG_PREFIX_INFO} OK" |
|
GITHUB_REQUEST_SUCCESS_STATUS_FAILED="${LOG_PREFIX_WARN} FAILED" |
|
else |
|
log "${LOG_PREFIX_INFO} ${GITHUB_REQUEST_LOG_MSG}" |
|
echo -n "${LOG_PREFIX_INFO} ${GITHUB_REQUEST_LOG_MSG}" |
|
GITHUB_REQUEST_SUCCESS_STATUS_OK="OK" |
|
GITHUB_REQUEST_SUCCESS_STATUS_FAILED="\r${LOG_PREFIX_WARN} ${GITHUB_REQUEST_LOG_MSG}FAILED" |
|
fi |
|
log ${LOG_PREFIX_DEBUG} ${GITHUB_REQUEST} |
|
GITHUB_REQUEST_RESPONSE=$(eval ${GITHUB_REQUEST}) |
|
log ${LOG_PREFIX_DEBUG} ${GITHUB_REQUEST_RESPONSE} |
|
echo ${GITHUB_REQUEST_RESPONSE} > ${GITHUB_REQUEST_RESPONSE_FILE} |
|
if [ "$(echo ${GITHUB_REQUEST_RESPONSE} | grep "Bad credentials")" != "" ] || \ |
|
[ "$(echo ${GITHUB_REQUEST_RESPONSE} | grep "Max number of login attempt exceeded")" != "" ] |
|
then |
|
echo -e "${GITHUB_REQUEST_SUCCESS_STATUS_FAILED}" |
|
log-echo "${LOG_PREFIX_ERROR} Bad credentials" |
|
log "${LOG_PREFIX_ERROR} ${GITHUB_REQUEST_LOG_MSG} FAILED" |
|
eval "${GITHUB_REQUEST_CALLBACK_ON_FAIL}" |
|
elif [ "$(echo ${GITHUB_REQUEST_RESPONSE} | grep "Validation Failed")" != "" ] || \ |
|
[ "$(echo ${GITHUB_REQUEST_RESPONSE} | grep "Body should be a JSON Hash")" != "" ] || \ |
|
[ "$(echo ${GITHUB_REQUEST_RESPONSE} | grep "Not Found")" != "" ] |
|
then |
|
log "${LOG_PREFIX_WARN} ${GITHUB_REQUEST_LOG_MSG} FAILED" |
|
echo -e "${GITHUB_REQUEST_SUCCESS_STATUS_FAILED}" |
|
eval "${GITHUB_REQUEST_CALLBACK_ON_FAIL}" |
|
else |
|
log "${LOG_PREFIX_INFO} ${GITHUB_REQUEST_LOG_MSG} OK" |
|
echo "${GITHUB_REQUEST_SUCCESS_STATUS_OK}" |
|
eval "${GITHUB_REQUEST_CALLBACK_ON_OK}" |
|
fi |
|
} |
|
|
|
deletecreatedtoken(){ |
|
if [ "${GITHUB_TOKEN_ID}" != "" ] |
|
then |
|
echo "${LOG_PREFIX_INFO} " |
|
echo "${LOG_PREFIX_INFO} You will find the created access token ${GITHUB_TOKEN} in the GitHub web" |
|
echo "${LOG_PREFIX_INFO} interface (https://github.com/settings/applications), where you can revoke it at any point. Alternatively, " |
|
echo "${LOG_PREFIX_INFO} you can also do in now (You will have to enter your GitHub password again for that)." |
|
read -p "${LOG_PREFIX_INPUT} Delete created token now? [y or n]: " answer |
|
if [ "${answer}" == "y" ] |
|
then |
|
github-request \ |
|
"Deleting token \"${GITHUB_TOKEN}\"... " \ |
|
"curl -sS -X DELETE -u ${GITHUB_USER} https://api.github.com/authorizations/${GITHUB_TOKEN_ID}" \ |
|
"needs_login" |
|
fi |
|
fi |
|
} |
|
|
|
terminate(){ |
|
deletecreatedtoken |
|
echo "${LOG_PREFIX_INFO} For detailed info look at file \"${GITHUB_LABEL_LOG_FILE}\"" |
|
logblankline |
|
exit ${1} |
|
} |
|
|
|
createlabel() { |
|
# The color is the first arg to make a bunch of calls to this function more readable, |
|
# since color arg will have always the same width, but the name of the label won't. |
|
github-request \ |
|
"Creating label \"${2}\"... " \ |
|
"curl -sS -d '{\"name\":\"${2}\",\"color\":\"${1}\"}' https://api.github.com/repos/${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}/labels?access_token=${GITHUB_TOKEN}" |
|
} |
|
|
|
deletelabel() { |
|
github-request \ |
|
"Deleting label \"${1}\"... " \ |
|
"curl -sS -X DELETE https://api.github.com/repos/${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}/labels/${1}?access_token=${GITHUB_TOKEN}" |
|
} |
|
|
|
createmilestone() { |
|
# Param 1: Milestone title (required) |
|
# Param 2: Description |
|
# Param 3: Date in format '2012-10-09T23:39:01Z' |
|
github-request \ |
|
"Creating milestone \"${1}\"... " \ |
|
"curl -sS -d '{\"title\":\"${1}\",\"state\":\"open\",\"description\":\"${2}\",\"due_on\":\"${3}\"}' https://api.github.com/repos/${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}/milestones?access_token=${GITHUB_TOKEN}" |
|
} |
|
|
|
# DOC: https://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository |
|
# NOTE: Does not seem to work for private repos (???) |
|
__set_milestone_url_env_var() { |
|
# Param 1: Milestone title (required) |
|
unset GITHUB_MILESTONE_URL |
|
github-request \ |
|
"Getting url for milestone \"${1}\"... " \ |
|
"curl -sS https://api.github.com/repos/${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}/milestones?state=all&access_token=${GITHUB_TOKEN}" \ |
|
"no_needs_login" \ |
|
":" \ |
|
"terminate 1" |
|
GITHUB_MILESTONE_URL="$(python -c "import json; milestones = json.loads(open('"${GITHUB_REQUEST_RESPONSE_FILE}"').read()); urls = [ milestone['url'] for milestone in milestones if milestone['title'] == '"${1}"' ]; url = urls[0] if urls else ''; print url; ")" |
|
[ -z "${GITHUB_MILESTONE_URL}" ] && log-echo "Milestone '${1}' cannot be found in repo '${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}'" |
|
} |
|
|
|
deletemilestone() { |
|
# Param 1: Milestone title (required) |
|
__set_milestone_url_env_var "${1}" |
|
[ -z "${GITHUB_MILESTONE_URL}" ] && log-echo "Milestone '${1}' was not deleted from repo '${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}'" && return |
|
github-request \ |
|
"Deleting milestone \"${1}\"... " \ |
|
"curl -sS -X DELETE "${GITHUB_MILESTONE_URL}"?access_token=${GITHUB_TOKEN}" |
|
} |
|
|
|
updatemilestone() { |
|
# Param 1: Milestone current title (required) |
|
# Param 2: New milestone title (required) |
|
# Param 3: New description (required) |
|
# Param 4: New date in format '2012-10-09T23:39:01Z' (required) |
|
__set_milestone_url_env_var "${1}" |
|
[ -z "${GITHUB_MILESTONE_URL}" ] && log-echo "Milestone '${1}' was not updated in repo '${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}'" && return |
|
github-request \ |
|
"Updating milestone \"${1}\"... " \ |
|
"curl -sS -X PATCH "${GITHUB_MILESTONE_URL}"?access_token=${GITHUB_TOKEN} -d '{\"title\":\"${2}\",\"description\":\"${3}\",\"due_on\":\"${4}\"}'" |
|
} |
|
|
|
|
|
# Gather the three needed parameters: repo_owner, repo_name and access_token |
|
|
|
PERFORM_TOKEN_VALIDATION=false |
|
if [ "${1}" == "--perform-token-validation" ] |
|
then |
|
PERFORM_TOKEN_VALIDATION=true |
|
shift |
|
fi |
|
|
|
log-echo "${LOG_PREFIX_INFO} Begining creation of labels in GitHub..." |
|
|
|
if [ "${1}" != "" ] |
|
then |
|
GITHUB_REPO_OWNER=${1} |
|
log-echo "${LOG_PREFIX_INFO} GitHub repo owner: ${GITHUB_REPO_OWNER}" |
|
else |
|
read -e -p "${LOG_PREFIX_INPUT} Repo owner (GitHub user or organisation): " GITHUB_REPO_OWNER |
|
log "${LOG_PREFIX_INFO} GitHub repo owner: ${GITHUB_REPO_OWNER}" |
|
fi |
|
|
|
if [ "${GITHUB_REPO_OWNER}" == "" ] |
|
then |
|
log-echo "${LOG_PREFIX_ERROR} Blank repo owner. Try again!" |
|
terminate 1 |
|
fi |
|
|
|
GITHUB_USER=${GITHUB_REPO_OWNER} |
|
|
|
|
|
if [ "${2}" != "" ] |
|
then |
|
GITHUB_REPO_NAME=${2} |
|
log-echo "${LOG_PREFIX_INFO} GitHub repo name: ${GITHUB_REPO_NAME}" |
|
else |
|
read -e -p "${LOG_PREFIX_INPUT} Repo: " GITHUB_REPO_NAME |
|
log "${LOG_PREFIX_INFO} GitHub repo name: ${GITHUB_REPO_NAME}" |
|
fi |
|
|
|
if [ "${GITHUB_REPO_NAME}" == "" ] |
|
then |
|
log-echo "${LOG_PREFIX_ERROR} Blank repo name. Try again!" |
|
terminate 1 |
|
fi |
|
|
|
|
|
if [ "${3}" != "" ] |
|
then |
|
GITHUB_TOKEN=${3} |
|
log-echo "${LOG_PREFIX_INFO} GitHub access token: ${GITHUB_TOKEN}" |
|
fi |
|
|
|
if [ "${GITHUB_TOKEN}" == "" ] |
|
then |
|
read -e -p "${LOG_PREFIX_INPUT} Access token (leave blank to create a new one): " GITHUB_TOKEN |
|
fi |
|
|
|
token_creation_callback_ok(){ |
|
GITHUB_TOKEN=$(echo ${GITHUB_REQUEST_RESPONSE} | sed -e "s/.*\"token\": \"\([a-zA-Z0-9]*\)\".*/\1/") |
|
GITHUB_TOKEN_ID=$(echo ${GITHUB_REQUEST_RESPONSE} | sed -e "s/.*\"id\": \([0-9]*\).*/\1/") |
|
log-echo "${LOG_PREFIX_INFO} New token created successfully: ${GITHUB_TOKEN} - Token id: ${GITHUB_TOKEN_ID}" |
|
} |
|
|
|
if [ "${GITHUB_TOKEN}" == "" ] |
|
then |
|
read -e -p "${LOG_PREFIX_INPUT} GitHub user (leave blank to use '${GITHUB_USER}'): " input |
|
GITHUB_USER="${input:-$GITHUB_USER}" |
|
GITHUB_TOKEN_REQUEST_BODY="{\"scopes\":[\"repo\"], \"note\":\"Generated on $(date +"%Y-%m-%d %H:%M:%S %z") by the script at https://gist.github.com/rbf/5983134\"}" |
|
github-request \ |
|
"Creating a new access token..." \ |
|
"curl -sS -u ${GITHUB_USER} -d '${GITHUB_TOKEN_REQUEST_BODY}' https://api.github.com/authorizations" \ |
|
"needs_login" \ |
|
token_creation_callback_ok \ |
|
"terminate 1" |
|
fi |
|
|
|
if "${PERFORM_TOKEN_VALIDATION}" |
|
then |
|
github-request \ |
|
"Validating token ${GITHUB_TOKEN}... " \ |
|
"curl -sS https://api.github.com/repos/${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}/labels?access_token=${GITHUB_TOKEN}" |
|
|
|
if [ "$(echo ${GITHUB_REQUEST_RESPONSE} | grep "Bad credentials")" != "" ] || \ |
|
[ "$(echo ${GITHUB_REQUEST_RESPONSE} | grep "Max number of login attempt exceeded")" != "" ] |
|
then |
|
log-echo "${LOG_PREFIX_ERROR} Token ${GITHUB_TOKEN} is not valid." |
|
log-echo "${LOG_PREFIX_WARN} Generate a new token at https://github.com/settings/applications or relaunching this script leaving the token parameter blank." |
|
terminate 1 |
|
fi |
|
|
|
if [ "$(echo ${GITHUB_REQUEST_RESPONSE} | grep "Not Found")" != "" ] |
|
then |
|
log-echo "${LOG_PREFIX_ERROR} Token ${GITHUB_TOKEN} doesn't seem valid for repository ${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}." |
|
log-echo "${LOG_PREFIX_WARN} Verify that the repository exists at https://github.com/${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}." |
|
log-echo "${LOG_PREFIX_WARN} Generate a new token at https://github.com/settings/applications or relaunching this script leaving the token parameter blank." |
|
terminate 1 |
|
fi |
|
fi |
|
|
|
|
|
# Milestones (usage examples) |
|
|
|
# createmilestone "v2.25" "Milestone for sprint Mar 04 - Mar 18 with target version '2.25'." "2016-03-18T18:00:00Z" |
|
# updatemilestone "v2.25" "v3.1" "Milestone for sprint Mar 04 - Mar 18 with target version '3.1'." "2016-03-18T18:00:00Z" |
|
# deletemilestone "v3.1" |
|
|
|
# Labels for priorities |
|
|
|
createlabel "fff3c3" "\u2605" # "★" on light yellow, i.e. low priority |
|
createlabel "ffe26b" "\u2605\u2605" # "★★" on yellow, i.e. medium priority |
|
createlabel "fbca04" "\u2605\u2605\u2605" # "★★★" on dark yellow, i.e. high priority |
|
|
|
|
|
# Labels for estimates |
|
|
|
createlabel "444444" "0" |
|
createlabel "444444" "0.5" |
|
createlabel "444444" "1" |
|
createlabel "444444" "2" |
|
createlabel "444444" "4" |
|
createlabel "444444" "10" |
|
|
|
|
|
# Labels for task Status |
|
|
|
createlabel "eeeeee" "S00 Backlog" |
|
createlabel "fad8c7" "S02 Top of Backlog" |
|
createlabel "ec9265" "S05 Ready to work" |
|
createlabel "eb6420" "S10 Working" |
|
createlabel "f39712" "S20 Testing" |
|
createlabel "fbca04" "S30 Ready to deploy" |
|
createlabel "d7e102" "S40 Ready to validate" |
|
createlabel "009800" "S50 Validated" |
|
createlabel "444444" "S110 Rejected" |
|
createlabel "e10c02" "S120 Blocked" |
|
|
|
|
|
# Labels for task Type |
|
|
|
createlabel "003300" "T0 Epic" |
|
createlabel "061b71" "T1 User story" |
|
createlabel "0b02e1" "T2 Task" |
|
createlabel "480cb3" "T3 Enhancement" |
|
createlabel "841685" "T4 Discussion" |
|
createlabel "fc2929" "T5 Bug" |
|
|
|
|
|
# Remove unused labels added by default by GitHub on repo creation |
|
|
|
deletelabel "bug" |
|
# deletelabel "duplicate" |
|
deletelabel "enhancement" |
|
deletelabel "invalid" |
|
# deletelabel "question" |
|
deletelabel "wontfix" |
|
# deletelabel "help%20wanted" |
|
|
|
echo "${LOG_PREFIX_INFO} Done!" |
|
|
|
terminate 0 |