VOL-4905 - Deploy new voltctl version.
jjb/shell/github-release.sh
---------------------------
o Added --help text and command line switches.
o Deprecate github-release command, replace with github gh cli.
o Update authentication to use new pac strings or token file.
o Create and auto-cleanup a scratch area for the script to use.
o Added callstack display on error to help identify source.
o Command line args added to facilitate interactive use.
+ Local access functions provide value lookup and defaults.
o Begin to modularize the script, added named functions and
wrapped global vars with accessor methods that format
values for passing to the gh command.
o Updated script to fail hard VS mask error conditions. For ex do not
publish a source-only release when artifact count is zero.
o Script currently runs in (gh --draft) mode to exercise these changes.
o Always call 'gh auth logout', esp for failure conditions.
o Added the ability to query for repository release strings.
+ Simple verification for gh repository access.
jjb/verify/voltctl.yaml
-----------------------
o Use new job template jjb/github-release/voltha.yaml.
o Update to use a new jenkins credential id.
jjb/verify/voltctl.yaml
-----------------------
o Use new job template jjb/github-release/voltha.yaml
Change-Id: I75432ea353d60d655c4558c6370d91f184d3b8ad
diff --git a/.onf/github-release-notes b/.onf/github-release-notes
new file mode 100644
index 0000000..e43e6cb
--- /dev/null
+++ b/.onf/github-release-notes
@@ -0,0 +1,18 @@
+[Prototyping Edits]
+
+Sun Mar 26 09:36:24 AM EDT 2023
+-------------------------------
+
+Copy jjb/github-release.yaml into jjb/github-release/voltha.yaml:
+ o credential-id
+ - old: github-release-token
+ - new: onf-bot-voltha (todo: github-release-voltha)
+ o Change id template:
+ - old: github-release
+ - new: github-release-voltha
+
+jjb/verify/voltctl.yaml
+ o Change job template from github-release to github-release-voltha.
+
+jjb/shell/github-release.sh
+ o Replace legacy github-release command with newer github gh cli.
\ No newline at end of file
diff --git a/jjb/github-release/voltha.yaml b/jjb/github-release/voltha.yaml
new file mode 100644
index 0000000..4794e8b
--- /dev/null
+++ b/jjb/github-release/voltha.yaml
@@ -0,0 +1,57 @@
+---
+# publishing artifacts to GitHub releases
+
+- job-template:
+ id: github-release-voltha
+ name: 'github-release_{project}'
+ description: |
+ Created by {id} job-template from ci-management/jjb/github-release.yaml<br/>
+ Build and publish artifacts to GitHub as a release, with checksums
+
+ triggers:
+ - cord-infra-gerrit-trigger-merge:
+ gerrit-server-name: '{gerrit-server-name}'
+ project-regexp: '^{project}$'
+ branch-regexp: '{branch-regexp}'
+ file-include-regexp: '{all-files-regexp}'
+ dependency-jobs: '{dependency-jobs}'
+
+ properties:
+ - cord-infra-properties:
+ build-days-to-keep: '{build-days-to-keep}'
+ artifact-num-to-keep: '{artifact-num-to-keep}'
+
+ wrappers:
+ - cord-pypi-wrapper:
+ build-timeout: '{build-timeout}'
+ jenkins-ssh-credential: '{gerrit-ssh-credential}'
+ - credentials-binding:
+ - text:
+ credential-id: onf-bot-voltha
+ variable: GITHUB_TOKEN
+
+ scm:
+ - cord-infra-gerrit-scm:
+ git-url: '$GIT_URL/$GERRIT_PROJECT'
+ refspec: '$GERRIT_REFSPEC'
+ branch: '$GERRIT_BRANCH'
+ submodule-recursive: 'false'
+ choosing-strategy: gerrit
+ jenkins-ssh-credential: '{jenkins-ssh-credential}'
+ basedir: '{project}'
+
+ node: '{build-node}'
+ project-type: freestyle
+ concurrent: true
+
+ builders:
+ - inject:
+ properties-content: |
+ DEST_GOPATH={dest-gopath}
+ RELEASE_TARGETS={release-targets}
+ ARTIFACT_GLOB={artifact-glob}
+ GITHUB_ORGANIZATION={github-organization}
+
+ - shell: !include-raw-escape: ../shell/github-release.sh
+
+# [EOF]
diff --git a/jjb/shell/github-release.sh b/jjb/shell/github-release.sh
index 3c4056b..baf3a47 100755
--- a/jjb/shell/github-release.sh
+++ b/jjb/shell/github-release.sh
@@ -19,37 +19,77 @@
# given a tag also create checksums files and release notes from the commit
# message
# -----------------------------------------------------------------------
-# 1) Staging to replace command github-release with gh.
-# 2) gh auth / GIT_TOKEN handling may be needed
-# -----------------------------------------------------------------------
-# gh release create abc/1.2.3-rc2 --discussion-category "Announcements" --generate-notes hello.txt
-# https://github.com/cli/cli/issues/4993
-# -----------------------------------------------------------------------
+set -euo pipefail
+
+##-------------------##
+##---] GLOBALS [---##
+##-------------------##
+declare -g WORKSPACE
+declare -g GERRIT_PROJECT
+declare -g __githost='github.com'
+
+## -----------------------------------------------------------------------
+## Uncomment to activate
+## -----------------------------------------------------------------------
+declare -i -g draft_release=1
# declare -g TRACE=0 # uncomment to set -x
# shellcheck disable=SC2015
[[ -v TRACE ]] && { set -x; } || { set +x; } # SC2015 (shellcheck -x)
-
-##-------------------##
-##---] GLOBALS [---##
-##-------------------##
-set -euo pipefail
+declare -a -g ARGV=() # Capture args to minimize globals and arg passing
+[[ $# -gt 0 ]] && ARGV=("$@")
declare -g scratch # temp workspace for downloads
declare -g gh_cmd # path to gh command
-declare -g ARGV="$*" # archive for display
-declare -g SCRIPT_VERSION='1.1' # git changeset needed
-
-declare -g RELEASE_TEMP
+declare -g SCRIPT_VERSION='1.2' # git changeset needed
##--------------------##
##---] INCLUDES [---##
##--------------------#
-# shellcheck disable=SC1091
-# source "${pgmdir}/common/common.sh" "${common_args[@]}"
+
+## -----------------------------------------------------------------------
+## Intent: Register an interrupt handler to display a stack trace on error
+## -----------------------------------------------------------------------
+function errexit()
+{
+ local err=$?
+ set +o xtrace
+ local code="${1:-1}"
+
+ local prefix="${BASH_SOURCE[1]}:${BASH_LINENO[0]}"
+ echo -e "\nOFFENDER: ${prefix}"
+ if [ $# -gt 0 ] && [ "$1" == '--stacktrace-quiet' ]; then
+ code=1
+ else
+ echo "ERROR: '${BASH_COMMAND}' exited with status $err"
+ fi
+
+ # Print out the stack trace described by $function_stack
+ if [ ${#FUNCNAME[@]} -gt 2 ]
+ then
+ echo "Call tree:"
+ for ((i=1;i<${#FUNCNAME[@]}-1;i++))
+ do
+ echo " $i: ${BASH_SOURCE[$i+1]}:${BASH_LINENO[$i]} ${FUNCNAME[$i]}(...)"
+ done
+ fi
+
+ echo "Exiting with status ${code}"
+ echo
+ exit "${code}"
+ # return
+}
+
+# trap ERR to provide an error handler whenever a command exits nonzero
+# this is a more verbose version of set -o errexit
+trap errexit ERR
+
+# setting errtrace allows our ERR trap handler to be propagated to functions,
+# expansions and subshells
+set -o errtrace
## -----------------------------------------------------------------------
## Intent: Cleanup scratch area on exit
@@ -60,31 +100,101 @@
local is_read_only
is_read_only="$(declare -p scratch)"
if [[ $is_read_only != *"declare -r scratch="* ]]; then
- echo "ERROR: variable scratch is not read-only, cleanup skipped"
- exit 1
+ echo "ERROR: variable scratch is not read-only, cleanup skipped"
+ exit 1
fi
if [ -d "$scratch" ]; then
- /bin/rm -fr "$scratch"
+ /bin/rm -fr "$scratch"
fi
+ do_logout
return
}
trap sigtrap EXIT
## -----------------------------------------------------------------------
+## Intent: Return a release version for queries (interactive debugging)
+## -----------------------------------------------------------------------
+function get_version()
+{
+ declare -n ref="$1"
+
+ banner
+ declare -a rev=()
+ rev+=("$(( RANDOM % 10 + 1 ))")
+ rev+=("$(( RANDOM % 256 + 1 ))")
+ rev+=("$(( 6RANDOM % 10000 + 1 ))")
+ ver="v${rev[0]}.${rev[1]}.${rev[2]}"
+
+ func_echo "version: $ver"
+ ref="$ver"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Provide defaults for environment variables
+## -----------------------------------------------------------------------
+function initEnvVars()
+{
+ # when not running under Jenkins, use current dir as workspace and a blank
+ # project name
+ declare -g WORKSPACE=${WORKSPACE:-.}
+ declare -g GERRIT_PROJECT=${GERRIT_PROJECT:-}
+
+ # Github organization (or user) this project is published on. Project name should
+ # be the same on both Gerrit and GitHub
+ declare -g GITHUB_ORGANIZATION=${GITHUB_ORGANIZATION:-}
+
+ # glob pattern relative to project dir matching release artifacts
+ # ARTIFACT_GLOB=${ARTIFACT_GLOB:-"release/*"} # stat -- release/* not found, literal string (?)
+ declare -g ARTIFACT_GLOB=${ARTIFACT_GLOB:-"release/."}
+
+ # Use "release" as the default makefile target, can be a space separated list
+ declare -g RELEASE_TARGETS=${RELEASE_TARGETS:-release}
+
+ # Set and handle GOPATH and PATH
+ export GOPATH=${GOPATH:-$WORKSPACE/go}
+ export PATH=$PATH:/usr/lib/go-1.12/bin:/usr/local/go/bin:$GOPATH/bin
+ return
+}
+
+## -----------------------------------------------------------------------
## Intent: Create a scratch area for downloads and transient tools
+## temp directory will be automatically removed upon exit.
## -----------------------------------------------------------------------
function init()
{
- declare -g scratch
-
local pkgbase="${0##*/}" # basename
local pkgname="${pkgbase%.*}"
+ initEnvVars
+
+ ## Create a temp directory for auto-cleanup
+ declare -g scratch
scratch="$(mktemp -d -t "${pkgname}.XXXXXXXXXX")"
- readonly scratch
- return
+ readonly scratch
+ declare -p scratch
+
+ ## prime the stream
+ local work
+ get_release_dir work
+ declare -p work
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Verbose output for logging
+## -----------------------------------------------------------------------
+function banner()
+{
+ local iam="${0##*/}"
+ cat <<EOB
+
+** -----------------------------------------------------------------------
+** ${iam}::${FUNCNAME[1]}: $*
+** -----------------------------------------------------------------------
+EOB
}
## -----------------------------------------------------------------------
@@ -97,15 +207,15 @@
# 14:18:38 > git fetch --no-tags --progress -- https://gerrit.opencord.org/ci-management.git +refs/heads/*:refs/remotes/origin/* # timeout=10
# 14:18:39 Checking out Revision 50f6e0b97f449b32d32ec0e02d59642000351847 (master)
# -----------------------------------------------------------------------
-function banner()
+function full_banner()
{
- local iam="${0##*/}"
+ local iam="${0##*/}"#
cat <<EOH
** -----------------------------------------------------------------------
** IAM: ${iam} :: ${FUNCNAME[0]}
-** ARGV: ${ARGV}
+** ARGV: ${ARGV[@]}
** PWD: $(/bin/pwd)
** NOW: $(date '+%Y/%m/%d %H:%M:%S')
** VER: ${SCRIPT_VERSION:-'unknown'}
@@ -116,196 +226,752 @@
}
## -----------------------------------------------------------------------
-## Intent:
-## Display available command versions
-## A github release job is failing due to a command being mia.
+## Intent: Display a message with 'iam' identifier for logging
## -----------------------------------------------------------------------
-function displayCommands()
-{
- # which git || /bin/true
- # git --version || /bin/true
- # go version || /bin/true
- # helm version || /bin/true
- return
-}
-
-## -----------------------------------------------------------------------
-## Intent: Display filesystem with a banner for logging
-## -----------------------------------------------------------------------
-function displayPwd()
+function func_echo()
{
local iam="${0##*/}"
- echo "** ${iam}: ENTER"
-
-cat <<EOM
-
-** -----------------------------------------------------------------------
-** IAM: $iam :: ${FUNCNAME[0]}
-** PWD: $(/bin/pwd)
-** -----------------------------------------------------------------------
-EOM
- find . -maxdepth 1 -ls
- echo "** ${iam}: LEAVE"
+ echo "** ${iam} :: ${FUNCNAME[1]}: $*"
return
}
## -----------------------------------------------------------------------
-## Intent: Copy files from the build directory into the release staging directory.
+## Intent: Display an error message then exit with status.
+## -----------------------------------------------------------------------
+function error()
+{
+ local iam="${0##*/}"
+ echo "ERROR ${iam} :: ${FUNCNAME[1]}: $*"
+ exit 1
+}
+
+## -----------------------------------------------------------------------
+## Intent: Verify sandbox/build is versioned for release.
+## -----------------------------------------------------------------------
+function getGitVersion()
+{
+ declare -n varname="$1"; shift
+ local ver
+
+ banner
+ ver="$(git tag -l --points-at HEAD)"
+ declare -p ver
+
+ get_version 'ver'
+ declare -p ver
+
+ # ------------------------------------------------------
+ # match bare versions or v-prefixed golang style version
+ # Critical failure for new/yet-to-be-released repo ?
+ # ------------------------------------------------------
+ if [[ "$ver" =~ ^v?([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]
+ then
+ echo "git has a SemVer released version tag: '$ver'"
+ echo "Building artifacts for GitHub release."
+ else
+ error "No SemVer released version tag found, exiting..."
+ fi
+
+ varname="$ver"
+ func_echo "GIT_VERSION is [$GIT_VERSION] from $(/bin/pwd)"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent:
+## Note: Release description is sanitized version of the log message
+## -----------------------------------------------------------------------
+function getReleaseDescription()
+{
+ declare -n varname="$1"; shift
+
+ local msg
+ msg="$(git log -1 --pretty=%B)"
+
+ local val
+ val="$(tr -dc "[:alnum:]\n\r\.\[\]\:\-\\\/\`\' " <<< "$msg")"
+
+ [[ ${#val} -eq 0 ]] && error "Release Description is empty ($msg)"
+ varname="$val"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Retrieve value of the release temp directory.
+## -----------------------------------------------------------------------
+## Note: Limit use of globals so logic can be isolated in function calls.
+## -----------------------------------------------------------------------
+# declare -g RELEASE_TEMP
+function get_release_dir()
+{
+ declare -n varname=$1; shift
+
+ # Temporary staging directory to copy artifacts to
+ varname="$scratch/release"
+ mkdir -p "$varname"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Retrieve github server hostname
+## -----------------------------------------------------------------------
+function get_gh_hostname()
+{
+ declare -n varname=$1; shift
+ varname+=('--hostname' "${__githost}")
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Retrieve repository organizaiton name
+## -----------------------------------------------------------------------
+function get_gh_repo_org()
+{
+ declare -n varname=$1; shift
+ declare -g __repo_org
+
+ local org
+ if [[ -v __repo_org ]]; then
+ org="$__repo_org"
+ elif [[ ! -v GITHUB_ORGANIZATION ]]; then
+ error "--repo-org or GITHUB_ORGANIZATION= are required"
+ else
+ org="${GITHUB_ORGANIZATION}"
+ fi
+
+ # shellcheck disable=SC2178
+ varname="$org"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Retrieve repository organizaiton name
+## -----------------------------------------------------------------------
+function get_gh_repo_name()
+{
+ declare -n varname=$1; shift
+ declare -g __repo_name
+
+ local name
+ if [[ -v __repo_name ]]; then
+ name="$__repo_name"
+ elif [[ ! -v GITHUB_PROJECT ]]; then
+ error "--repo-name or GITHUB_PROJECT= are required"
+ else
+ name="${GITHUB_PROJECT}"
+ fi
+
+ varname="$name"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Return path for the gh release query
+## -----------------------------------------------------------------------
+function get_gh_releases()
+{
+ declare -n ref="$1"
+
+ local repo_org
+ get_gh_repo_org repo_org
+
+ local repo_name
+ get_gh_repo_name repo_name
+
+ ref="repos/${repo_org}/${repo_name}/releases"
+ func_echo "ref=$ref"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Retrieve repository path argument
+## -----------------------------------------------------------------------
+function get_argv_repo()
+{
+ declare -n varname=$1; shift
+
+ local repo_org
+ get_gh_repo_org repo_org
+
+ local repo_name
+ get_gh_repo_name repo_name
+
+ varname="${repo_org}/${repo_name}"
+ func_echo "VARNAME=$varname"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Retrieve release name string "project - version"
+## -----------------------------------------------------------------------
+function get_argv_name()
+{
+ declare -n varname=$1; shift
+
+ local repo_name
+ get_gh_repo_name repo_name
+ varname="${repo_name} - $GIT_VERSION"
+ func_echo "varname=$varname"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Retrieve tag version
+## -----------------------------------------------------------------------
+function get_argv_tag()
+{
+ declare -n varname=$1; shift
+
+ # cached_argv_tag='v3.41.3204'
+ if [[ ! -v cached_argv_tag ]]; then
+ declare -g cached_argv_tag
+ if [[ -v GIT_VERSION ]]; then # hello jenkins
+ cached_argv_tag="$GIT_VERSION"
+ fi
+ fi
+
+ [[ ${#cached_argv_tag} -eq 0 ]] && error "Unable to determine GIT_VERSION="
+ varname="$cached_argv_tag"
+ func_echo "varname=$varname"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent:
+## -----------------------------------------------------------------------
+# To support golang projects that require GOPATH to be set and code checked out there
+# If $DEST_GOPATH is not an empty string:
+# - create GOPATH within WORKSPACE, and destination directory within
+# - set PATH to include $GOPATH/bin and the system go binaries
+# - move project from $WORKSPACE/$GERRIT_PROJECT to new location in $GOPATH
+# - start release process within that directory
+## -----------------------------------------------------------------------
+function get_release_path()
+{
+ declare -n varname=$1; shift
+
+ DEST_GOPATH=${DEST_GOPATH:-}
+ if [ -n "$DEST_GOPATH" ]; then
+ # if [[ -v DEST_GOPATH ]] && [[ -n DEST_GOPATH ]]; then
+ ## [jenkins] Suspect this will taint the golang installation.
+ ## [jenkins] Install succeeds, release fails, next job affected due to corruption.
+ ## [jenkins] Copy golang to temp then augment ?
+ ## [jenkins] Worst case (problematic) backup then restore
+ mkdir -p "$GOPATH/src/$DEST_GOPATH"
+ varname="$GOPATH/src/$DEST_GOPATH/$GERRIT_PROJECT"
+ mv "$WORKSPACE/$GERRIT_PROJECT" "$varname"
+
+ ## [TODO] - support local dev use
+ # elif [[ ! -v WORKSPACE ]] && [[ -d '.git' ]]; then
+ # project=$(git remote -v show | awk -F' ' '{print $2}' | xargs basename)
+ # project=voltctl.git
+
+ else
+ varname="$WORKSPACE/$GERRIT_PROJECT"
+ fi
+
+ if [ ! -f "$varname/Makefile" ]; then
+ :
+ elif [ ! -f "$varname/makefile" ]; then
+ :
+ else
+ error "Makefile not found at $varname!"
+ fi
+
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Display future enhancements
+## -----------------------------------------------------------------------
+function todo()
+{
+ local iam="${0##*/}"
+
+cat <<EOT
+
+** -----------------------------------------------------------------------
+** IAM: ${iam} :: ${FUNCNAME[0]}
+** -----------------------------------------------------------------------
+ o get_release_path()
+ - refactor redundant paths into local vars.
+ - see comments, do we have a one-off failure condition ?
+
+EOT
+
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Copy files from the build directory into the release staging
+## directory for publishing to github releases/ endpoint.
## -----------------------------------------------------------------------
function copyToRelease()
{
- local iam="${FUNCNAME[0]}"
- echo "** ${iam}: ENTER"
-
- local artifact_glob="${ARTIFACT_GLOB%/*}"
- echo "** ${iam}: $(declare -p ARTIFACT_GLOB) $(declare -p artifact_glob)"
+ func_echo "ENTER"
+ local artifact_glob="${ARTIFACT_GLOB%/*}"
+ func_echo "$(declare -p artifact_glob)"
+
+ local work
+ get_release_dir work
+
+ ## Flatten filesystem, should we recurse here to release subdirs ?
+ # cp $(which ls) "$work"
+ # readarray -t arts < <(find "$artifact_glob" -type f)
+ readarray -t arts < <(find "$work" -type f)
+ [[ ${#arts[@]} -eq 0 ]] && error "Artifact dir is empty, check for build failures: $artifact_glob"
+
# Copy artifacts into the release temp dir
# shellcheck disable=SC2086
- # cp -v "$ARTIFACT_GLOB" "$RELEASE_TEMP"
- echo "rsync -rv --checksum \"$artifact_glob/.\" \"$RELEASE_TEMP/.\""
- rsync -rv --checksum "$artifact_glob/." "$RELEASE_TEMP/."
+ echo "rsync -rv --checksum \"$artifact_glob/.\" \"$work/.\""
+ rsync -rv --checksum "$artifact_glob/." "$work/."
- echo "** ${iam}: RELEASE_TEMP=${RELEASE_TEMP}"
- find "$RELEASE_TEMP" -print
+ func_echo "LEAVE"
- echo "** ${iam}: LEAVE"
- echo
return
}
## -----------------------------------------------------------------------
-## Intent:
+## https://docs.github.com/en/rest/releases?apiVersion=2022-11-28
+ # https://cli.github.com/manual/gh_release_create
+ # --target <branch> or commit SHA
+ # --title
+ # --generate-notes
+ # --release-notes (notes file)
+ # --release
+ # release create dist/*.tgz
+ # --discussion-category "General"
## -----------------------------------------------------------------------
-function github_release_list()
+# https://cli.github.com/manual/gh_release_create
+## -----------------------------------------------------------------------
+function gh_release_create()
{
- local what="$1" ; shift
- local user="$1" ; shift
- local repo="$1" ; shift
+ banner ''
- local iam="${FUNCNAME[0]}"
- echo "** ${iam}: ENTER"
+ local version="$GIT_VERSION"
+# get_version 'version'
+# create_release_by_version "$version"
- declare -a cmd=()
-
- cmd+=("$gh_cmd")
- cmd+=('--verbose')
- cmd+=('--limit' '10')
- cmd+=('release' 'list')
- cmd+=('--repo' "opencord/$repo")
-
- # gh release create [<tag>] [<files>...]
- echo "** ${iam}: RUNNING " "${cmd[@]}"
- "${cmd[@]}"
+ declare -a args=()
+ args+=('--host-repo')
+ args+=('--notes' "'Testing release create -- ignore'")
+ args+=('--title')
+ if [[ -v draft_release ]]; then
+ args+=('--draft')
+ else
+ args+=('--discussion-category' 'Announcements')
+ fi
- echo "** ${iam}: ENTER"
+ local work
+ get_release_dir work
+
+ # pushd "$work" >/dev/null
+ readarray -t payload < <(find "$work" ! -type d -print)
+ func_echo "gh release create ${version} ${args[@]}" "${payload[@]}"
+ my_gh 'release' 'create' "'$version'" "${args[@]}" "${payload[@]}"
+ # popd >/dev/null
+
return
}
## -----------------------------------------------------------------------
-## Intent:
+## Intent: Authenticate credentials for a github gh session
## -----------------------------------------------------------------------
-function github_release_pre()
+## NOTE: my_gh currently unused due to --with-token < "$pac"
+## -----------------------------------------------------------------------
+function do_login()
{
- local what="$1" ; shift
- local user="$1" ; shift
- local repo="$1" ; shift
- local tag="$1" ; shift
- local name="$1" ; shift
- local descr="$1" ; shift
+ declare -g pac
+ declare -a in_args=()
+ [[ $# -gt 0 ]] && in_args+=("$@")
- local iam="${FUNCNAME[0]}"
- echo "** ${iam}: ENTER"
+ # bridge to my_gh()
+ get_gh_hostname in_args
- declare -p user
- declare -p repo
- declare -p tag
- declare -p name
- declare -p descr
-
- case "$what" in
- gh)
- declare -a cmd=()
+ banner "${in_args[@]}"
- ## [TODO] Refactor into a function accepting:
- ## --create
- ## --info
- ## --upload
- cmd+=("$gh_cmd")
- # cmd+=('--verbose')
- cmd+=('release' 'create')
- cmd+=("$tag") # no switch for tag, pass inline.
- # cmd+=('--latest') # auto tag based on origin/master
- # cmd+=('--target') # Use when a branch based release is needed.
-
- cmd+=('--repo' "opencord/$repo")
- cmd+=('--title' "$name")
- # cmd+=('--descripton' "$descr") # not supported
- cmd+=('--discussion-category' "Announcements")
- # cmd+=('--verify-tag') # fatal
+ ## Read from disk is safer than export GITHUB_TOKEN=
+ if [[ -v pac ]] && [[ ${#pac} -gt 0 ]]; then # interactive/debugging
+ [ ! -f "$pac" ] && error "PAC token file $pac does not exist"
+ # func_echo "--token file is $pac"
+ gh auth login "${in_args[@]}" --with-token < "$pac"
- declare -p cmd
+ elif [[ ! -v GITHUB_TOKEN ]]; then
+ error "--token [t] or GITHUB_TOKEN= are required"
- # gh release create [<tag>] [<files>...]
- echo "** ${iam}: RUNNING " "${cmd[@]}"
- "${cmd[@]}"
- ;;
+ else # jenkins
+ func_echo 'Detected ENV{GITHUB_TOKEN}='
+ gh auth login "${in_args[@]}"
+ fi
- *)
- declare -a cmd=()
+ declare -i -g active_login=1 # signal logout
- cmd+=('github-release')
- # cmd+=('--verbose')
- cmd+=('release')
- cmd+=('--user' "$user")
- cmd+=('--repo' "$repo")
- cmd+=('--tag' "$tag")
- cmd+=('--name' "$name")
- cmd+=('--descripton' "$descr")
-
- echo "** ${iam}: RUNNING " "${cmd[@]}"
- "${cmd[@]}"
- ;;
- esac
-
- echo "** ${iam}: ENTER"
return
}
## -----------------------------------------------------------------------
-## Intent:
+## Intent: Destroy credentials/gh session authenticated by do_login
+## -----------------------------------------------------------------------
+## NOTE: my_gh currently unused due to "<<< 'y'"
+## -----------------------------------------------------------------------
+function do_logout()
+{
+ declare -i -g active_login
+ [[ ! -v active_login ]] && return
+
+ declare -a out_args=()
+ [[ $# -gt 0 ]] && out_args+=("$@")
+
+ # bridge to my_gh()
+
+ get_gh_hostname in_args
+
+ banner "${out_args[@]}"
+ gh auth logout "${out_args[@]}" <<< 'Y'
+
+ unset active_login
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Query for repository version strings
+## -----------------------------------------------------------------------
+function get_releases()
+{
+ declare -n ref="$1"; shift
+ local func="${FUNCNAME[0]}"
+
+ banner ""
+ pushd "$scratch" >/dev/null
+
+ # gh api repos/{owner}/{repo}/releases
+ local releases_uri
+ get_gh_releases releases_uri
+ declare -p releases_uri
+
+ ref=()
+ gh api "$releases_uri" "${common[@]}" | jq . > 'release.raw'
+ readarray -t __tmp < <(jq '.[] | "\(.tag_name)"' 'release.raw')
+
+ local release
+ for release in "${__tmp[@]}";
+ do
+ release="${release//\"/}"
+ ref+=("$release")
+ done
+
+ popd >/dev/null
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Display repository query strings.
+## Indirect: verify authentication and API
+## -----------------------------------------------------------------------
+function showReleases()
+{
+ declare -a releases=()
+ get_releases releases
+
+ local release
+ for release in "${releases[@]}";
+ do
+ func_echo "$release"
+ done
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Install the gh command line tool locally
## -----------------------------------------------------------------------
function install_gh_binary()
{
- local iam="${FUNCNAME[0]}"
- echo "** $iam: ENTER"
+ banner
pushd "$scratch"
- echo -e "\n** ${iam}: Retrieve latest gh download URLs"
+ func_echo "Retrieve latest gh download URLs"
local latest="https://github.com/cli/cli/releases/latest"
- local tarball="gh.tar.tgz"
-
- local VER
- VER=$(curl --silent -qI "$latest" \
- | awk -F '/' '/^location/ {print substr($NF, 1, length($NF)-1)}')
- # echo "VER=[$VER]"
-
- echo "** ${iam}: Download latest gh binary"
+ local tarball="gh.tar.tgz"
+
+ readarray -t latest < <(curl --silent -qI "$latest" \
+ | awk -F '/' '/^location/ {print substr($NF, 1, length($NF)-1)}')
+ declare -p latest
+ if [ ${#latest[@]} -ne 1 ]; then
+ error "Unable to determine latest gh package version"
+ fi
+
+ local VER="${latest[0]}"
+
+ func_echo "Download latest gh binary"
local url="https://github.com/cli/cli/releases/download/${VER}/gh_${VER#v}_linux_amd64.tar.gz"
wget --quiet --output-document="$tarball" "$url"
-
- echo "** ${iam}: Unpack tarball"
+
+ func_echo "Unpack tarball"
tar zxf "$tarball"
gh_cmd="$(find "${scratch}" -name 'gh' -print)"
readonly gh_cmd
- echo "** ${iam} Command: ${gh_cmd}"
- echo "** ${iam} Version: $("$gh_cmd" --version)"
+ func_echo "Command: ${gh_cmd}"
+ func_echo "Version: $("$gh_cmd" --version)"
popd
- echo "** $iam: LEAVE"
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Danger Will Robinson
+## -----------------------------------------------------------------------
+function releaseDelete()
+{
+ local version="$1"; shift
+
+ banner "${in_args[@]}"
+ declare -a args=()
+ args+=('--host-repo')
+ args+=('--yes')
+ # args+=('--cleanup-tag')
+
+# ** github-release.sh :: get_argv_repo: VARNAME=opencord/voltctl
+#* Running: /tmp/github-release.R7geZo7Ywo/gh_2.25.1_linux_amd64/bin/gh release delete v4.175.710 --repo 'github.com/opencord/voltctl' --yes --cleanup-tag
+#rror connecting to 'github.com
+#heck your internet connection or https://githubstatus.com
+
+ echo
+ echo "==========================================================================="
+ my_gh 'release' 'delete' "$version" "${args[@]}"
+ echo "==========================================================================="
+ echo
+
+ showReleases
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Copy binaries into temp/release, checksum then publish
+## -----------------------------------------------------------------------
+function release_staging()
+{
+ local release_temp
+ get_release_dir release_temp
+
+ banner ''
+ func_echo "Packaging release files"
+ # pushd "$RELEASE_TEMP"
+ pushd "$release_temp" >/dev/null || error "pushd failed: dir is [$release_temp]"
+
+ readarray -t to_release < <(find . -mindepth 1 -maxdepth 1 -type f -print)
+ func_echo "Files to release: $(declare -p to_release)"
+
+ # Generate and check checksums
+ sha256sum -- * > checksum.SHA256
+ sha256sum -c < checksum.SHA256
+
+ echo
+ func_echo "Checksums(checksum.SHA256):"
+ cat checksum.SHA256
+
+ ## ARGS NEEDED
+ gh_release_create
+
+ popd >/dev/null || error "pushd failed: dir is [$release_temp]"
+
+ return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Display program usage
+## -----------------------------------------------------------------------
+function usage()
+{
+ [[ $# -gt 0 ]] && func_echo "$*"
+
+ cat <<EOH
+Usage: github-release.sh [options] [target] ...
+
+[Github CLI (gh) arguments]
+ --login Perform authentication using a PAC
+ --logout
+ --host [h] Specify github server for connection.
+
+[Options]
+ --token Login debugging, alternative to env var use.
+
+[Modes]
+ --debug Enable script debug mode
+ --verbose Enable script verbose mode
+
+All remaining arguments are passthrough to the gh command.
+EOH
+
+ exit 0
+}
+
+## -----------------------------------------------------------------------
+## Intent: Provide common arguments and access to the gh command.
+## o Cache path to the gh command
+## o Construct a gh command line from given args
+## o Command wrapper can provide defaults (--hostname github.com)
+## -----------------------------------------------------------------------
+## Given:
+## scalar Array variable name (declare -n is a reference)
+## Return:
+## ref gh command line passed back to caller
+## Switches:
+## --host Pass default github hostname
+## --verbose Enable verbose mode#
+## --version Display command version
+## @array Remaining arguments passed as command switches.
+## -----------------------------------------------------------------------
+## See Also:
+## o https://cli.github.com/manual
+## -----------------------------------------------------------------------
+function my_gh()
+{
+ ## ------------------------
+ ## Cache path to gh command
+ ## ------------------------
+ if [[ ! -v gh_cmd ]]; then
+ readarray -t cmds < <(which -a gh)
+ declare -p cmds
+ if [ ${#cmds} -eq 0 ]; then
+ error "Unable to locate the gh command"
+ fi
+ gh_cmd="${cmds[0]}"
+ readonly gh_cmd
+ fi
+
+ declare -a cmd=()
+ cmd+=("$gh_cmd")
+
+ ## ----------------------
+ ## Construct command line
+ ## ----------------------
+ # shellcheck disable=SC2034
+ declare -A action=() # pending operations
+ declare -a args=() # common gh command line args
+
+ while [ $# -gt 0 ]; do
+ local arg="$1"; shift
+ case "$arg" in
+
+ # Modes
+ -*debug) declare -i -g debug=1 ;;
+ -*help) show_help ;;
+ -*verbose) args+=('--verbose') ;;
+
+ -*hostname)
+ get_gh_hostname in_args
+ ;;
+
+ --host-repo)
+ local val
+ get_argv_repo val
+
+ # --repo <[HOST/]OWNER/REPO>
+ args+=('--repo' "'${__githost}/${val}'")
+ ;;
+
+ --repo)
+ local val
+ get_argv_repo val
+ args+=('--repo' "$val")
+ ;;
+
+ --tag)
+ local val
+ get_argv_tag val
+ args+=("'$val'") # No switch, pass inline
+ ;;
+
+ --title)
+ local val
+ get_argv_name val
+ args+=('--title' "'$val'")
+ ;;
+
+ # --draft
+ # --latest
+ *) args+=("$arg") ;;
+ esac
+ done
+
+ cmd+=("${args[@]}")
+ echo "** Running: ${cmd[*]}"
+ "${cmd[@]}"
+ local status=$?
+
+ [[ $status -eq 0 ]] && { true; } || { false; }
+ return
+}
+
+## ---------------------------------------------------------------------------
+## Intent:
+## ---------------------------------------------------------------------------
+function usage()
+{
+ cat <<EOH
+
+Usage: $0
+Usage: make [options] [target] ...
+ --help This mesage
+ --pac Personal Access Token (file)
+
+[DEBUG]
+ --gen-version Generate a random release version string.
+ --git-hostname Git server hostname (default=github.com)
+
+EOH
+ return
+}
+
+## ---------------------------------------------------------------------------
+## Intent: Parse script command line arguments
+## ---------------------------------------------------------------------------
+function parse_args()
+{
+ # declare -n ref="$1"; shift
+
+ [[ -v DEBUG ]] && func_echo "ENTER"
+
+# ref="repos/${__repo_user}/${__repo_name}/releases"
+
+ while [ $# -gt 0 ]; do
+ local arg="$1"; shift
+ case "$arg" in
+ -*gen-version)
+ get_version GIT_VERSION
+ ;;
+
+ -*git-hostname)
+ __githost="$1"; shift
+ ;;
+
+ -*repo-name)
+ __repo_name="$1"; shift
+ ;;
+
+ -*repo-org)
+ __repo_org="$1"; shift
+ ;;
+
+ -*pac)
+ declare -g pac="$1"; shift
+ readonly pac
+ [[ ! -f "$pac" ]] && error "--token= does not exist ($pac)"
+ : # nop/true
+ ;;
+
+ -*help)
+ usage
+ exit 0
+ ;;
+ *) error "Detected unknown argument $arg" ;;
+ esac
+ done
+
return
}
@@ -314,82 +980,34 @@
##----------------##
iam="${0##*/}"
-banner
+full_banner
+parse_args $@
init
install_gh_binary
-# when not running under Jenkins, use current dir as workspace and a blank
-# project name
-WORKSPACE=${WORKSPACE:-.}
-GERRIT_PROJECT=${GERRIT_PROJECT:-}
+do_login
-# Github organization (or user) this project is published on. Project name should
-# be the same on both Gerrit and GitHub
-GITHUB_ORGANIZATION=${GITHUB_ORGANIZATION:-}
+release_path='/dev/null'
+get_release_path release_path
+declare -p release_path
-# glob pattern relative to project dir matching release artifacts
-# ARTIFACT_GLOB=${ARTIFACT_GLOB:-"release/*"} # stat -- release/* not found, literal string (?)
-ARTIFACT_GLOB=${ARTIFACT_GLOB:-"release/."}
+pushd "$release_path" || error "pushd failed: dir is [$release_path]"
-# Temporary staging directory to copy artifacts to
-RELEASE_TEMP="$WORKSPACE/release"
-mkdir -p "$RELEASE_TEMP"
+ # legacy: getGitVersion "$GERRIT_PROJECT" GIT_VERSION
+ getGitVersion GIT_VERSION
+ getReleaseDescription RELEASE_DESCRIPTION
-# Use "release" as the default makefile target, can be a space separated list
-RELEASE_TARGETS=${RELEASE_TARGETS:-release}
+ # build the release, can be multiple space separated targets
+ # -----------------------------------------------------------------------
+ # % go build command-line-arguments:
+ # copying /tmp/go-build4212845548/b001/exe/a.out:
+ # open release/voltctl-1.8.25-linux-amd64: permission denied
+ # missing: docker run mkdir
+ # -----------------------------------------------------------------------
+ # shellcheck disable=SC2086
+ make "$RELEASE_TARGETS" || tyue
-
-# check that we're on a semver released version, or exit
-pushd "$GERRIT_PROJECT"
- GIT_VERSION=$(git tag -l --points-at HEAD)
-
- # match bare versions or v-prefixed golang style version
- if [[ "$GIT_VERSION" =~ ^v?([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]
- then
- echo "git has a SemVer released version tag: '$GIT_VERSION'"
- echo "Building artifacts for GitHub release."
- else
- echo "No SemVer released version tag found, exiting..."
- exit 0
- fi
-popd
-
-# Set and handle GOPATH and PATH
-export GOPATH=${GOPATH:-$WORKSPACE/go}
-export PATH=$PATH:/usr/lib/go-1.12/bin:/usr/local/go/bin:$GOPATH/bin
-
-# To support golang projects that require GOPATH to be set and code checked out there
-# If $DEST_GOPATH is not an empty string:
-# - create GOPATH within WORKSPACE, and destination directory within
-# - set PATH to include $GOPATH/bin and the system go binaries
-# - move project from $WORKSPACE/$GERRIT_PROJECT to new location in $GOPATH
-# - start release process within that directory
-
-DEST_GOPATH=${DEST_GOPATH:-}
-if [ -n "$DEST_GOPATH" ]; then
- mkdir -p "$GOPATH/src/$DEST_GOPATH"
- release_path="$GOPATH/src/$DEST_GOPATH/$GERRIT_PROJECT"
- mv "$WORKSPACE/$GERRIT_PROJECT" "$release_path"
-else
- release_path="$WORKSPACE/$GERRIT_PROJECT"
-fi
-
-if [ ! -f "$release_path/Makefile" ]; then
- echo "Makefile not found at $release_path!"
- exit 1
-else
-
- pushd "$release_path"
-
- # Release description is sanitized version of the log message
- RELEASE_DESCRIPTION="$(git log -1 --pretty=%B | tr -dc "[:alnum:]\n\r\.\[\]\:\-\\\/\`\' ")"
-
- # build the release, can be multiple space separated targets
- # shellcheck disable=SC2086
- make "$RELEASE_TARGETS"
-
- # doDebug # deterine why ARTIFACT_GLOB is empty
- copyToRelease
+ copyToRelease
cat <<EOM
@@ -402,82 +1020,14 @@
** -----------------------------------------------------------------------
EOM
-# git auth login
-# git auth logout
-
- if false; then
- echo "** ${iam} List releases"
- # "gh_cmd" release list [flags]
- github_release_list \
- "$GITHUB_ORGANIZATION"\
- "$GERRIT_PROJECT"
- fi
-
- # Usage: github-release [global options] <verb> [verb options]
- # create release
- echo "** ${iam} Creating Release: $GERRIT_PROJECT - $GIT_VERSION"
- github_release_pre 'gh'\
- "$GITHUB_ORGANIZATION"\
- "$GERRIT_PROJECT"\
- "$GIT_VERSION"\
- "$GERRIT_PROJECT - $GIT_VERSION"\
- "$RELEASE_DESCRIPTION"
-
- echo "** ${iam} Packaging release files"
- pushd "$RELEASE_TEMP"
-
- echo "** ${iam}: Files to release:"
- readarray -t to_release < <(find . -mindepth 1 -maxdepth 1 -type f -print)
- declare -p to_release
-
- # Generate and check checksums
- sha256sum -- * > checksum.SHA256
- sha256sum -c < checksum.SHA256
-
- echo
- echo "** ${iam} Checksums(checksum.SHA256):"
- cat checksum.SHA256
- echo
-
- echo "** ${iam} Upload files being released"
-
- # shellcheck disable=SC2194
- case 'gh' in
- gh)
- declare -a cmd=()
- cmd+=("$gh_cmd")
- cmd+=('release' 'upload')
- cmd+=("$GIT_VERSION")
- cmd+=('--repo' "opencord/${GERRIT_PROJECT}")
- cmd+=("${to_release[@]}")
-
- declare -p cmd
-
- # gh release upload <tag> <files>... [flags]
- "${cmd[@]}"
- ;;
-
- *)
-
- # upload all files to the release
- for rel_file in *
- do
- echo "** ${iam} Uploading file: $rel_file"
- github-release \
- upload \
- --user "$GITHUB_ORGANIZATION" \
- --repo "$GERRIT_PROJECT" \
- --tag "$GIT_VERSION" \
- --name "$rel_file" \
- --file "$rel_file"
- done
- ;;
- esac
-
- popd
- popd
+ showReleases
+ # releaseDelete 'v4.175.710'
+ release_staging
+ popd || error "pushd failed: dir is [$release_path]"
fi
+do_logout
+
# [SEE ALSO]
# -----------------------------------------------------------------------
# https://www.shellcheck.net/wiki/SC2236
diff --git a/jjb/verify/voltctl.yaml b/jjb/verify/voltctl.yaml
index b0e69bc..a0be6f0 100644
--- a/jjb/verify/voltctl.yaml
+++ b/jjb/verify/voltctl.yaml
@@ -30,7 +30,7 @@
- job-group:
name: 'post-submit-voltctl-jobs'
jobs:
- - 'github-release':
+ - 'github-release-voltha':
build-node: 'ubuntu18.04-basebuild-2c-4g'
dependency-jobs: 'version-tag_wildcard'
github-organization: 'opencord'