Last active
May 4, 2018 22:37
-
-
Save dmrolfs/de481311f8f0d89c293270fee20d56a7 to your computer and use it in GitHub Desktop.
Publish into Artifactory Repository
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# _ _ _ _ | |
# _ __ _ _| |__ | (_)___| |__ | |
# | '_ \| | | | '_ \| | / __| '_ \ | |
# | |_) | |_| | |_) | | \__ \ | | | | |
# | .__/ \__,_|_.__/|_|_|___/_| |_| | |
# |_| | |
# | |
# | |
# Usage: | |
# Publish artifacts into prod or sit artifactory repositories | |
# | |
# Usage: | |
# publish [--options] [<arguments>] | |
# publish -h | --help | |
# | |
# Options: | |
# -h --help Display this help information. | |
# -d --dry-run Perform a dry run publish in order to verify options | |
# -u --user Set the artifactory username. If not specified | |
# $ARTIFACTORY_USER is used. | |
# -p --password Set the artifactory password. If not specified | |
# $ARTIFACTORY_PASS is used. | |
# -r --repo Target repository. Valid values include 'prod' or 'sit' | |
# 'sit' is default | |
# -o --org Organization component of maven coordinate | |
# -a --artifact Artifact ID component of maven coordinate | |
# -v --version Version component of maven coordinate | |
# | |
# Bash Boilerplate: https://github.com/alphabetum/bash-boilerplate | |
# | |
# Copyright (c) 2018 Damon Rolfs | |
############################################################################### | |
# Strict Mode | |
############################################################################### | |
# Treat unset variables and parameters other than the special parameters ‘@’ or | |
# ‘*’ as an error when performing parameter expansion. An 'unbound variable' | |
# error message will be written to the standard error, and a non-interactive | |
# shell will exit. | |
# | |
# This requires using parameter expansion to test for unset variables. | |
# | |
# http://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion | |
# | |
# The two approaches that are probably the most appropriate are: | |
# | |
# ${parameter:-word} | |
# If parameter is unset or null, the expansion of word is substituted. | |
# Otherwise, the value of parameter is substituted. In other words, "word" | |
# acts as a default value when the value of "$parameter" is blank. If "word" | |
# is not present, then the default is blank (essentially an empty string). | |
# | |
# ${parameter:?word} | |
# If parameter is null or unset, the expansion of word (or a message to that | |
# effect if word is not present) is written to the standard error and the | |
# shell, if it is not interactive, exits. Otherwise, the value of parameter | |
# is substituted. | |
# | |
# Examples | |
# ======== | |
# | |
# Arrays: | |
# | |
# ${some_array[@]:-} # blank default value | |
# ${some_array[*]:-} # blank default value | |
# ${some_array[0]:-} # blank default value | |
# ${some_array[0]:-default_value} # default value: the string 'default_value' | |
# | |
# Positional variables: | |
# | |
# ${1:-alternative} # default value: the string 'alternative' | |
# ${2:-} # blank default value | |
# | |
# With an error message: | |
# | |
# ${1:?'error message'} # exit with 'error message' if variable is unbound | |
# | |
# Short form: set -u | |
set -o nounset | |
# Exit immediately if a pipeline returns non-zero. | |
# | |
# NOTE: this has issues. When using read -rd '' with a heredoc, the exit | |
# status is non-zero, even though there isn't an error, and this setting | |
# then causes the script to exit. read -rd '' is synonymous to read -d $'\0', | |
# which means read until it finds a NUL byte, but it reaches the EOF (end of | |
# heredoc) without finding one and exits with a 1 status. Therefore, when | |
# reading from heredocs with set -e, there are three potential solutions: | |
# | |
# Solution 1. set +e / set -e again: | |
# | |
# set +e | |
# read -rd '' variable <<EOF | |
# EOF | |
# set -e | |
# | |
# Solution 2. <<EOF || true: | |
# | |
# read -rd '' variable <<EOF || true | |
# EOF | |
# | |
# Solution 3. Don't use set -e or set -o errexit at all. | |
# | |
# More information: | |
# | |
# https://www.mail-archive.com/bug-bash@gnu.org/msg12170.html | |
# | |
# Short form: set -e | |
set -o errexit | |
# Print a helpful message if a pipeline with non-zero exit code causes the | |
# script to exit as described above. | |
trap 'echo "Aborting due to errexit on line $LINENO. Exit code: $?" >&2' ERR | |
# Allow the above trap be inherited by all functions in the script. | |
# | |
# Short form: set -E | |
set -o errtrace | |
# Return value of a pipeline is the value of the last (rightmost) command to | |
# exit with a non-zero status, or zero if all commands in the pipeline exit | |
# successfully. | |
set -o pipefail | |
# Set $IFS to only newline and tab. | |
# | |
# http://www.dwheeler.com/essays/filenames-in-shell.html | |
IFS=$'\n\t' | |
############################################################################### | |
# Environment | |
############################################################################### | |
# $_ME | |
# | |
# Set to the program's basename. | |
_ME=$(basename "${0}") | |
############################################################################### | |
# Debug | |
############################################################################### | |
# _debug() | |
# | |
# Usage: | |
# _debug printf "Debug info. Variable: %s\n" "$0" | |
# | |
# A simple function for executing a specified command if the `$_USE_DEBUG` | |
# variable has been set. The command is expected to print a message and | |
# should typically be either `echo`, `printf`, or `cat`. | |
__DEBUG_COUNTER=0 | |
_debug() { | |
if [[ "${_USE_DEBUG:-"0"}" -eq 1 ]] | |
then | |
__DEBUG_COUNTER=$((__DEBUG_COUNTER+1)) | |
# Prefix debug message with "bug (U+1F41B)" | |
printf "🐛 %s " "${__DEBUG_COUNTER}" | |
"${@}" | |
printf "――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――\\n" | |
fi | |
} | |
# debug() | |
# | |
# Usage: | |
# debug "Debug info. Variable: $0" | |
# | |
# Print the specified message if the `$_USE_DEBUG` variable has been set. | |
# | |
# This is a shortcut for the _debug() function that simply echos the message. | |
debug() { | |
_debug echo "${@}" | |
} | |
############################################################################### | |
# Die | |
############################################################################### | |
#todo maybe convert to this set | |
# _yell() { echo "$0: $*" >&2; } | |
# die() { yell "$*"; exit 111; } | |
# try() { "$@" || die "cannot $*"; } | |
# _die() | |
# | |
# Usage: | |
# _die printf "Error message. Variable: %s\n" "$0" | |
# | |
# A simple function for exiting with an error after executing the specified | |
# command. The command is expected to print a message and should typically | |
# be either `echo`, `printf`, or `cat`. | |
_die() { | |
# Prefix die message with "cross mark (U+274C)", often displayed as a red x. | |
printf "❌ " | |
"${@}" 1>&2 | |
exit 1 | |
} | |
# die() | |
# | |
# Usage: | |
# die "Error message. Variable: $0" | |
# | |
# Exit with an error and print the specified message. | |
# | |
# This is a shortcut for the _die() function that simply echos the message. | |
die() { | |
_die echo "${@}" | |
} | |
############################################################################### | |
# Help | |
############################################################################### | |
# _print_help() | |
# | |
# Usage: | |
# _print_help | |
# | |
# Print the program help information. | |
_print_help() { | |
cat <<HEREDOC | |
_ _ _ _ | |
_ __ _ _| |__ | (_)___| |__ | |
| '_ \| | | | '_ \| | / __| '_ \ | |
| |_) | |_| | |_) | | \__ \ | | | | |
| .__/ \__,_|_.__/|_|_|___/_| |_| | |
|_| | |
Publish artifacts into prod or sit artifactory repositories | |
Usage: | |
${_ME} [--options] [<arguments>] | |
${_ME} -h | --help | |
Options: | |
-h --help Display this help information. | |
-d --dry-run Perform a dry run publish in order to verify options | |
-u --user Set the artifactory username. If not specified | |
$ARTIFACTORY_USER is used. | |
-p --password Set the artifactory password. If not specified | |
$ARTIFACTORY_PASS is used. | |
-r --repo Target repository. Valid values include 'prod' or 'sit' | |
'sit' is default | |
-o --org Organization component of maven coordinate | |
-a --artifact Artifact ID component of maven coordinate | |
-v --version Version component of maven coordinate | |
HEREDOC | |
} | |
############################################################################### | |
# Options | |
############################################################################### | |
# Steps: | |
# | |
# 1. set expected short options in `optstring` at beginning of the "Normalize | |
# Options" section, | |
# 2. parse options in while loop in the "Parse Options" section. | |
# Normalize Options ########################################################### | |
# Source: | |
# https://github.com/e36freak/templates/blob/master/options | |
# The first loop, even though it uses 'optstring', will NOT check if an | |
# option that takes a required argument has the argument provided. That must | |
# be done within the second loop and case statement, yourself. Its purpose | |
# is solely to determine that -oARG is split into -o ARG, and not -o -A -R -G. | |
# Set short options ----------------------------------------------------------- | |
# option string, for short options. | |
# | |
# Very much like getopts, expected short options should be appended to the | |
# string here. Any option followed by a ':' takes a required argument. | |
# | |
# In this example, `-x` and `-h` are regular short options, while `o` is | |
# assumed to have an argument and will be split if joined with the string, | |
# meaning `-oARG` would be split to `-o ARG`. | |
optstring=dr:o:a:v:u:p: | |
# Normalize ------------------------------------------------------------------- | |
# iterate over options, breaking -ab into -a -b and --foo=bar into --foo bar | |
# also turns -- into --endopts to avoid issues with things like '-o-', the '-' | |
# should not indicate the end of options, but be an invalid option (or the | |
# argument to the option, such as wget -qO-) | |
unset options | |
# while the number of arguments is greater than 0 | |
while ((${#})) | |
do | |
case ${1} in | |
# if option is of type -ab | |
-[!-]?*) | |
# loop over each character starting with the second | |
for ((i=1; i<${#1}; i++)) | |
do | |
# extract 1 character from position 'i' | |
c=${1:i:1} | |
# add current char to options | |
options+=("-${c}") | |
# if option takes a required argument, and it's not the last char | |
# make the rest of the string its argument | |
if [[ ${optstring} = *"${c}:"* && ${1:i+1} ]] | |
then | |
options+=("${1:i+1}") | |
break | |
fi | |
done | |
;; | |
# if option is of type --foo=bar, split on first '=' | |
--?*=*) | |
options+=("${1%%=*}" "${1#*=}") | |
;; | |
# end of options, stop breaking them up | |
--) | |
options+=(--endopts) | |
shift | |
options+=("${@}") | |
break | |
;; | |
# otherwise, nothing special | |
*) | |
options+=("${1}") | |
;; | |
esac | |
shift | |
done | |
# set new positional parameters to altered options. Set default to blank. | |
set -- "${options[@]:-}" | |
unset options | |
# Parse Options ############################################################### | |
_SIT_REPO="https://artifactory.in.here.com/artifactory/here-olp-sit" | |
_PROD_REPO="https://repo.platform.here.com/artifactory/open-location-platform" | |
# Initialize $_CMD, which can continue to be blank depending | |
# on what the program needs. | |
_CMD="publish" | |
# Initialize $_COMMAND_ARGV array | |
# | |
# This array contains all of the arguments that get passed along to each | |
# command. This is essentially the same as the program arguments, minus those | |
# that have been filtered out in the program option parsing loop. This array | |
# is initialized with $0, which is the program's name. | |
_COMMAND_ARGV=("${0}") | |
# Initialize program option variables. | |
_PRINT_HELP=0 | |
_USE_DEBUG=0 | |
# Initialize additional expected option variables. | |
_IS_DRY_RUN=0 | |
_ACTIVE_REPO=${_SIT_REPO} | |
_USERNAME=${ARTIFACTORY_USER} | |
_PASSWORD=${ARTIFACTORY_PASS} | |
_ORGANIZATION="" | |
_ARTIFACT_NAME="" | |
_VERSION="" | |
# _require_argument() | |
# | |
# Usage: | |
# _require_argument <option> <argument> | |
# | |
# If <argument> is blank or another option, print an error message and exit | |
# with status 1. | |
_require_argument() { | |
# Set local variables from arguments. | |
# | |
# NOTE: 'local' is a non-POSIX bash feature and keeps the variable local to | |
# the block of code, as defined by curly braces. It's easiest to just think | |
# of them as local to a function. | |
local _option="${1:-}" | |
local _argument="${2:-}" | |
if [[ -z "${_argument}" ]] || [[ "${_argument}" =~ ^- ]] | |
then | |
_die printf "Option requires a argument: %s\\n" "${_option}" | |
fi | |
} | |
# getopts and getopts have inconsistent behavior, so using a simple home-brewed | |
# while loop. This isn't perfectly compliant with POSIX, but it's close enough | |
# and this appears to be a widely used approach. | |
# | |
# More info: | |
# http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html | |
# http://stackoverflow.com/a/14203146 | |
# http://stackoverflow.com/a/7948533 | |
while [ ${#} -gt 0 ] | |
do | |
__option="${1:-}" | |
__maybe_param="${2:-}" | |
debug "option:[${__option}] maybe_param:[${__maybe_param}]" | |
case "${__option}" in | |
-h|--help) | |
_PRINT_HELP=1 | |
;; | |
--debug) | |
_USE_DEBUG=1 | |
;; | |
-d|--dry-run) | |
_IS_DRY_RUN=1 | |
;; | |
-u|--user) | |
_require_argument "${__option}" "${__maybe_param}" | |
_USERNAME="${__maybe_param}" | |
shift | |
;; | |
-p|--password) | |
_require_argument "${__option}" "${__maybe_param}" | |
_PASSWORD="${__maybe_param}" | |
shift | |
;; | |
-r|--repo) | |
_require_argument "${__option}" "${__maybe_param}" | |
case "${__maybe_param}" in | |
"sit") _ACTIVE_REPO=${_SIT_REPO};; | |
"prod") _ACTIVE_REPO=${_PROD_REPO};; | |
*) die "expected repo option: sit or prod\n" | |
esac | |
shift | |
;; | |
-o|--org) | |
_require_argument "${__option}" "${__maybe_param}" | |
_ORGANIZATION="${__maybe_param}" | |
shift | |
;; | |
-a|--artifact) | |
_require_argument "${__option}" "${__maybe_param}" | |
_ARTIFACT_NAME="${__maybe_param}" | |
shift | |
;; | |
-v|--version) | |
_require_argument "${__option}" "${__maybe_param}" | |
_VERSION="${__maybe_param}" | |
shift | |
;; | |
--endopts) | |
# Terminate option parsing. | |
break | |
;; | |
*) | |
debug "non-option: ${__option}" | |
# The first non-option argument is assumed to be the command name. | |
# All subsequent arguments are added to $_COMMAND_ARGV. | |
if [[ -n ${_CMD} ]] | |
then | |
debug "adding ${__option} to ${_COMMAND_ARGV}" | |
_COMMAND_ARGV+=("${__option}") | |
debug "resulting _COMMAND_ARGV:\n${_COMMAND_ARGV[*]}" | |
else | |
_CMD="${__option}" | |
debug "setting command to be: ${_CMD}" | |
fi | |
# _die printf "Unexpected option: %s\\n" "${__option}" | |
;; | |
esac | |
shift | |
done | |
# Set $_COMMAND_PARAMETERS to $_COMMAND_ARGV, minus the initial element, $0. This | |
# provides an array that is equivalent to $* and $@ within each command | |
# function, though the array is zero-indexed, which could lead to confusion. | |
# | |
# Use `unset` to remove the first element rather than slicing (e.g., | |
# `_COMMAND_PARAMETERS=("${_COMMAND_ARGV[@]:1}")`) because under bash 3.2 the | |
# resulting slice is treated as a quoted string and doesn't easily get coaxed | |
# into a new array. | |
_COMMAND_PARAMETERS=(${_COMMAND_ARGV[*]}) | |
unset "_COMMAND_PARAMETERS[0]" | |
_debug printf \ | |
"\${_CMD}: %s\\n" \ | |
"${_CMD}" | |
_debug printf \ | |
"\${_COMMAND_ARGV[*]}:\\n%s\\n" \ | |
"${_COMMAND_ARGV[*]}" | |
_debug printf \ | |
"\${_COMMAND_PARAMETERS[*]:-}:\\n%s\\n" \ | |
"${_COMMAND_PARAMETERS[*]:-}" | |
############################################################################### | |
# Program Functions | |
############################################################################### | |
_path_for() { | |
${1//.//} | |
# sed -e 's/c/z/' $1 | |
} | |
_simple() { | |
local org_path=${_ORGANIZATION//.//} | |
debug "simple org path=${org_path}" | |
_debug printf ">> Performing operation...\\n" | |
# shopt -s globstar | |
for file in ${_COMMAND_PARAMETERS[*]}; do | |
local name=$(basename ${file}) | |
local url="${_ACTIVE_REPO}/${org_path}/${_ARTIFACT_NAME}/${_VERSION}/${name}" | |
printf "\nPublishing ${_ORGANIZATION}:${_ARTIFACT_NAME}:${_VERSION} to ${url} :\n" | |
if [[ "${_IS_DRY_RUN:-"0"}" -eq 0 ]] | |
then | |
curl -u ${_USERNAME}:${_PASSWORD} -X PUT "${url}" -T ${file}; | |
printf "\n" | |
fi | |
done | |
# if ((_OPTION_X)) | |
# then | |
# printf "Perform a simple operation with --option-x.\\n" | |
# else | |
# printf "Perform a simple operation.\\n" | |
# fi | |
# if [[ -n "${_SHORT_OPTION_WITH_PARAMETER}" ]] | |
# then | |
# printf "Short option parameter: %s\\n" "${_SHORT_OPTION_WITH_PARAMETER}" | |
# fi | |
# if [[ -n "${_LONG_OPTION_WITH_PARAMETER}" ]] | |
# then | |
# printf "Long option parameter: %s\\n" "${_LONG_OPTION_WITH_PARAMETER}" | |
# fi | |
} | |
############################################################################### | |
# Main | |
############################################################################### | |
# _main() | |
# | |
# Usage: | |
# _main [<options>] [<arguments>] | |
# | |
# Description: | |
# Entry point for the program, handling basic option parsing and dispatching. | |
_main() { | |
if ((_PRINT_HELP)) | |
then | |
_print_help | |
else | |
_simple "$@" | |
fi | |
} | |
# Call `_main` after everything has been defined. | |
_main "$@" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment