blob: baf3a47c7cbe191f3ec0e230af415b91119a04fc [file] [log] [blame]
Zack Williams27cd3e52018-09-18 16:44:50 -07001#!/usr/bin/env bash
Joey Armstrong28eddda2023-01-10 03:09:34 -05002# -----------------------------------------------------------------------
3# Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors
Zack Williams27cd3e52018-09-18 16:44:50 -07004#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
Joey Armstrong28eddda2023-01-10 03:09:34 -050016#
Zack Williams27cd3e52018-09-18 16:44:50 -070017# github-release.sh
18# builds (with make) and uploads release artifacts (binaries, etc.) to github
19# given a tag also create checksums files and release notes from the commit
20# message
Joey Armstrong28eddda2023-01-10 03:09:34 -050021# -----------------------------------------------------------------------
Zack Williams27cd3e52018-09-18 16:44:50 -070022
Joey Armstrong2097d3e2023-03-26 10:32:03 -040023set -euo pipefail
24
25##-------------------##
26##---] GLOBALS [---##
27##-------------------##
28declare -g WORKSPACE
29declare -g GERRIT_PROJECT
30declare -g __githost='github.com'
31
32## -----------------------------------------------------------------------
33## Uncomment to activate
34## -----------------------------------------------------------------------
35declare -i -g draft_release=1
Joey Armstrong41923cc2023-01-30 14:38:16 -050036# declare -g TRACE=0 # uncomment to set -x
37
38# shellcheck disable=SC2015
39[[ -v TRACE ]] && { set -x; } || { set +x; } # SC2015 (shellcheck -x)
40
Joey Armstrong2097d3e2023-03-26 10:32:03 -040041declare -a -g ARGV=() # Capture args to minimize globals and arg passing
42[[ $# -gt 0 ]] && ARGV=("$@")
Joey Armstrongd99e3d22023-01-29 12:35:43 -050043
44declare -g scratch # temp workspace for downloads
45declare -g gh_cmd # path to gh command
46
Joey Armstrong2097d3e2023-03-26 10:32:03 -040047declare -g SCRIPT_VERSION='1.2' # git changeset needed
Joey Armstrong26707f02023-01-26 12:41:12 -050048
Joey Armstrong7f382ef2023-01-25 12:00:08 -050049##--------------------##
50##---] INCLUDES [---##
Joey Armstrong1962bcf2023-01-27 13:53:18 -050051##--------------------#
Joey Armstrong2097d3e2023-03-26 10:32:03 -040052
53## -----------------------------------------------------------------------
54## Intent: Register an interrupt handler to display a stack trace on error
55## -----------------------------------------------------------------------
56function errexit()
57{
58 local err=$?
59 set +o xtrace
60 local code="${1:-1}"
61
62 local prefix="${BASH_SOURCE[1]}:${BASH_LINENO[0]}"
63 echo -e "\nOFFENDER: ${prefix}"
64 if [ $# -gt 0 ] && [ "$1" == '--stacktrace-quiet' ]; then
65 code=1
66 else
67 echo "ERROR: '${BASH_COMMAND}' exited with status $err"
68 fi
69
70 # Print out the stack trace described by $function_stack
71 if [ ${#FUNCNAME[@]} -gt 2 ]
72 then
73 echo "Call tree:"
74 for ((i=1;i<${#FUNCNAME[@]}-1;i++))
75 do
76 echo " $i: ${BASH_SOURCE[$i+1]}:${BASH_LINENO[$i]} ${FUNCNAME[$i]}(...)"
77 done
78 fi
79
80 echo "Exiting with status ${code}"
81 echo
82 exit "${code}"
83 # return
84}
85
86# trap ERR to provide an error handler whenever a command exits nonzero
87# this is a more verbose version of set -o errexit
88trap errexit ERR
89
90# setting errtrace allows our ERR trap handler to be propagated to functions,
91# expansions and subshells
92set -o errtrace
Joey Armstrong7f382ef2023-01-25 12:00:08 -050093
94## -----------------------------------------------------------------------
Joey Armstrongd99e3d22023-01-29 12:35:43 -050095## Intent: Cleanup scratch area on exit
96## -----------------------------------------------------------------------
97function sigtrap()
98{
99 ## Prevent mishaps
100 local is_read_only
101 is_read_only="$(declare -p scratch)"
102 if [[ $is_read_only != *"declare -r scratch="* ]]; then
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400103 echo "ERROR: variable scratch is not read-only, cleanup skipped"
104 exit 1
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500105 fi
106
107 if [ -d "$scratch" ]; then
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400108 /bin/rm -fr "$scratch"
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500109 fi
110
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400111 do_logout
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500112 return
113}
114trap sigtrap EXIT
115
116## -----------------------------------------------------------------------
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400117## Intent: Return a release version for queries (interactive debugging)
118## -----------------------------------------------------------------------
119function get_version()
120{
121 declare -n ref="$1"
122
123 banner
124 declare -a rev=()
125 rev+=("$(( RANDOM % 10 + 1 ))")
126 rev+=("$(( RANDOM % 256 + 1 ))")
127 rev+=("$(( 6RANDOM % 10000 + 1 ))")
128 ver="v${rev[0]}.${rev[1]}.${rev[2]}"
129
130 func_echo "version: $ver"
131 ref="$ver"
132 return
133}
134
135## -----------------------------------------------------------------------
136## Intent: Provide defaults for environment variables
137## -----------------------------------------------------------------------
138function initEnvVars()
139{
140 # when not running under Jenkins, use current dir as workspace and a blank
141 # project name
142 declare -g WORKSPACE=${WORKSPACE:-.}
143 declare -g GERRIT_PROJECT=${GERRIT_PROJECT:-}
144
145 # Github organization (or user) this project is published on. Project name should
146 # be the same on both Gerrit and GitHub
147 declare -g GITHUB_ORGANIZATION=${GITHUB_ORGANIZATION:-}
148
149 # glob pattern relative to project dir matching release artifacts
150 # ARTIFACT_GLOB=${ARTIFACT_GLOB:-"release/*"} # stat -- release/* not found, literal string (?)
151 declare -g ARTIFACT_GLOB=${ARTIFACT_GLOB:-"release/."}
152
153 # Use "release" as the default makefile target, can be a space separated list
154 declare -g RELEASE_TARGETS=${RELEASE_TARGETS:-release}
155
156 # Set and handle GOPATH and PATH
157 export GOPATH=${GOPATH:-$WORKSPACE/go}
158 export PATH=$PATH:/usr/lib/go-1.12/bin:/usr/local/go/bin:$GOPATH/bin
159 return
160}
161
162## -----------------------------------------------------------------------
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500163## Intent: Create a scratch area for downloads and transient tools
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400164## temp directory will be automatically removed upon exit.
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500165## -----------------------------------------------------------------------
166function init()
167{
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500168 local pkgbase="${0##*/}" # basename
169 local pkgname="${pkgbase%.*}"
170
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400171 initEnvVars
172
173 ## Create a temp directory for auto-cleanup
174 declare -g scratch
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500175 scratch="$(mktemp -d -t "${pkgname}.XXXXXXXXXX")"
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400176 readonly scratch
177 declare -p scratch
178
179 ## prime the stream
180 local work
181 get_release_dir work
182 declare -p work
183 return
184}
185
186## -----------------------------------------------------------------------
187## Intent: Verbose output for logging
188## -----------------------------------------------------------------------
189function banner()
190{
191 local iam="${0##*/}"
192 cat <<EOB
193
194** -----------------------------------------------------------------------
195** ${iam}::${FUNCNAME[1]}: $*
196** -----------------------------------------------------------------------
197EOB
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500198}
199
200## -----------------------------------------------------------------------
Joey Armstrong7f382ef2023-01-25 12:00:08 -0500201## Intent: Output a log banner to identify the running script/version.
202## -----------------------------------------------------------------------
203## TODO:
204## o SCRIPT_VERSION => git changeset for repo:ci-managment
205## o echo "library version: ${env."library.libName.version"}"
206# -----------------------------------------------------------------------
207# 14:18:38 > git fetch --no-tags --progress -- https://gerrit.opencord.org/ci-management.git +refs/heads/*:refs/remotes/origin/* # timeout=10
208# 14:18:39 Checking out Revision 50f6e0b97f449b32d32ec0e02d59642000351847 (master)
209# -----------------------------------------------------------------------
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400210function full_banner()
Joey Armstrong7f382ef2023-01-25 12:00:08 -0500211{
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400212 local iam="${0##*/}"#
Joey Armstrong7f382ef2023-01-25 12:00:08 -0500213
214cat <<EOH
215
216** -----------------------------------------------------------------------
217** IAM: ${iam} :: ${FUNCNAME[0]}
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400218** ARGV: ${ARGV[@]}
Joey Armstrong7f382ef2023-01-25 12:00:08 -0500219** PWD: $(/bin/pwd)
220** NOW: $(date '+%Y/%m/%d %H:%M:%S')
221** VER: ${SCRIPT_VERSION:-'unknown'}
222** -----------------------------------------------------------------------
223EOH
224
225 return
226}
227
Joey Armstrongaf577ab2022-12-15 14:43:33 -0500228## -----------------------------------------------------------------------
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400229## Intent: Display a message with 'iam' identifier for logging
Joey Armstrong50f6e0b2023-01-24 14:14:08 -0500230## -----------------------------------------------------------------------
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400231function func_echo()
Joey Armstrong1962bcf2023-01-27 13:53:18 -0500232{
233 local iam="${0##*/}"
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400234 echo "** ${iam} :: ${FUNCNAME[1]}: $*"
Joey Armstrong1962bcf2023-01-27 13:53:18 -0500235 return
236}
237
238## -----------------------------------------------------------------------
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400239## Intent: Display an error message then exit with status.
240## -----------------------------------------------------------------------
241function error()
242{
243 local iam="${0##*/}"
244 echo "ERROR ${iam} :: ${FUNCNAME[1]}: $*"
245 exit 1
246}
247
248## -----------------------------------------------------------------------
249## Intent: Verify sandbox/build is versioned for release.
250## -----------------------------------------------------------------------
251function getGitVersion()
252{
253 declare -n varname="$1"; shift
254 local ver
255
256 banner
257 ver="$(git tag -l --points-at HEAD)"
258 declare -p ver
259
260 get_version 'ver'
261 declare -p ver
262
263 # ------------------------------------------------------
264 # match bare versions or v-prefixed golang style version
265 # Critical failure for new/yet-to-be-released repo ?
266 # ------------------------------------------------------
267 if [[ "$ver" =~ ^v?([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]
268 then
269 echo "git has a SemVer released version tag: '$ver'"
270 echo "Building artifacts for GitHub release."
271 else
272 error "No SemVer released version tag found, exiting..."
273 fi
274
275 varname="$ver"
276 func_echo "GIT_VERSION is [$GIT_VERSION] from $(/bin/pwd)"
277 return
278}
279
280## -----------------------------------------------------------------------
281## Intent:
282## Note: Release description is sanitized version of the log message
283## -----------------------------------------------------------------------
284function getReleaseDescription()
285{
286 declare -n varname="$1"; shift
287
288 local msg
289 msg="$(git log -1 --pretty=%B)"
290
291 local val
292 val="$(tr -dc "[:alnum:]\n\r\.\[\]\:\-\\\/\`\' " <<< "$msg")"
293
294 [[ ${#val} -eq 0 ]] && error "Release Description is empty ($msg)"
295 varname="$val"
296 return
297}
298
299## -----------------------------------------------------------------------
300## Intent: Retrieve value of the release temp directory.
301## -----------------------------------------------------------------------
302## Note: Limit use of globals so logic can be isolated in function calls.
303## -----------------------------------------------------------------------
304# declare -g RELEASE_TEMP
305function get_release_dir()
306{
307 declare -n varname=$1; shift
308
309 # Temporary staging directory to copy artifacts to
310 varname="$scratch/release"
311 mkdir -p "$varname"
312 return
313}
314
315## -----------------------------------------------------------------------
316## Intent: Retrieve github server hostname
317## -----------------------------------------------------------------------
318function get_gh_hostname()
319{
320 declare -n varname=$1; shift
321 varname+=('--hostname' "${__githost}")
322 return
323}
324
325## -----------------------------------------------------------------------
326## Intent: Retrieve repository organizaiton name
327## -----------------------------------------------------------------------
328function get_gh_repo_org()
329{
330 declare -n varname=$1; shift
331 declare -g __repo_org
332
333 local org
334 if [[ -v __repo_org ]]; then
335 org="$__repo_org"
336 elif [[ ! -v GITHUB_ORGANIZATION ]]; then
337 error "--repo-org or GITHUB_ORGANIZATION= are required"
338 else
339 org="${GITHUB_ORGANIZATION}"
340 fi
341
342 # shellcheck disable=SC2178
343 varname="$org"
344 return
345}
346
347## -----------------------------------------------------------------------
348## Intent: Retrieve repository organizaiton name
349## -----------------------------------------------------------------------
350function get_gh_repo_name()
351{
352 declare -n varname=$1; shift
353 declare -g __repo_name
354
355 local name
356 if [[ -v __repo_name ]]; then
357 name="$__repo_name"
358 elif [[ ! -v GITHUB_PROJECT ]]; then
359 error "--repo-name or GITHUB_PROJECT= are required"
360 else
361 name="${GITHUB_PROJECT}"
362 fi
363
364 varname="$name"
365 return
366}
367
368## -----------------------------------------------------------------------
369## Intent: Return path for the gh release query
370## -----------------------------------------------------------------------
371function get_gh_releases()
372{
373 declare -n ref="$1"
374
375 local repo_org
376 get_gh_repo_org repo_org
377
378 local repo_name
379 get_gh_repo_name repo_name
380
381 ref="repos/${repo_org}/${repo_name}/releases"
382 func_echo "ref=$ref"
383 return
384}
385
386## -----------------------------------------------------------------------
387## Intent: Retrieve repository path argument
388## -----------------------------------------------------------------------
389function get_argv_repo()
390{
391 declare -n varname=$1; shift
392
393 local repo_org
394 get_gh_repo_org repo_org
395
396 local repo_name
397 get_gh_repo_name repo_name
398
399 varname="${repo_org}/${repo_name}"
400 func_echo "VARNAME=$varname"
401 return
402}
403
404## -----------------------------------------------------------------------
405## Intent: Retrieve release name string "project - version"
406## -----------------------------------------------------------------------
407function get_argv_name()
408{
409 declare -n varname=$1; shift
410
411 local repo_name
412 get_gh_repo_name repo_name
413 varname="${repo_name} - $GIT_VERSION"
414 func_echo "varname=$varname"
415 return
416}
417
418## -----------------------------------------------------------------------
419## Intent: Retrieve tag version
420## -----------------------------------------------------------------------
421function get_argv_tag()
422{
423 declare -n varname=$1; shift
424
425 # cached_argv_tag='v3.41.3204'
426 if [[ ! -v cached_argv_tag ]]; then
427 declare -g cached_argv_tag
428 if [[ -v GIT_VERSION ]]; then # hello jenkins
429 cached_argv_tag="$GIT_VERSION"
430 fi
431 fi
432
433 [[ ${#cached_argv_tag} -eq 0 ]] && error "Unable to determine GIT_VERSION="
434 varname="$cached_argv_tag"
435 func_echo "varname=$varname"
436 return
437}
438
439## -----------------------------------------------------------------------
440## Intent:
441## -----------------------------------------------------------------------
442# To support golang projects that require GOPATH to be set and code checked out there
443# If $DEST_GOPATH is not an empty string:
444# - create GOPATH within WORKSPACE, and destination directory within
445# - set PATH to include $GOPATH/bin and the system go binaries
446# - move project from $WORKSPACE/$GERRIT_PROJECT to new location in $GOPATH
447# - start release process within that directory
448## -----------------------------------------------------------------------
449function get_release_path()
450{
451 declare -n varname=$1; shift
452
453 DEST_GOPATH=${DEST_GOPATH:-}
454 if [ -n "$DEST_GOPATH" ]; then
455 # if [[ -v DEST_GOPATH ]] && [[ -n DEST_GOPATH ]]; then
456 ## [jenkins] Suspect this will taint the golang installation.
457 ## [jenkins] Install succeeds, release fails, next job affected due to corruption.
458 ## [jenkins] Copy golang to temp then augment ?
459 ## [jenkins] Worst case (problematic) backup then restore
460 mkdir -p "$GOPATH/src/$DEST_GOPATH"
461 varname="$GOPATH/src/$DEST_GOPATH/$GERRIT_PROJECT"
462 mv "$WORKSPACE/$GERRIT_PROJECT" "$varname"
463
464 ## [TODO] - support local dev use
465 # elif [[ ! -v WORKSPACE ]] && [[ -d '.git' ]]; then
466 # project=$(git remote -v show | awk -F' ' '{print $2}' | xargs basename)
467 # project=voltctl.git
468
469 else
470 varname="$WORKSPACE/$GERRIT_PROJECT"
471 fi
472
473 if [ ! -f "$varname/Makefile" ]; then
474 :
475 elif [ ! -f "$varname/makefile" ]; then
476 :
477 else
478 error "Makefile not found at $varname!"
479 fi
480
481 return
482}
483
484## -----------------------------------------------------------------------
485## Intent: Display future enhancements
486## -----------------------------------------------------------------------
487function todo()
488{
489 local iam="${0##*/}"
490
491cat <<EOT
492
493** -----------------------------------------------------------------------
494** IAM: ${iam} :: ${FUNCNAME[0]}
495** -----------------------------------------------------------------------
496 o get_release_path()
497 - refactor redundant paths into local vars.
498 - see comments, do we have a one-off failure condition ?
499
500EOT
501
502 return
503}
504
505## -----------------------------------------------------------------------
506## Intent: Copy files from the build directory into the release staging
507## directory for publishing to github releases/ endpoint.
Joey Armstrong26707f02023-01-26 12:41:12 -0500508## -----------------------------------------------------------------------
509function copyToRelease()
510{
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400511 func_echo "ENTER"
Joey Armstrong26707f02023-01-26 12:41:12 -0500512
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400513 local artifact_glob="${ARTIFACT_GLOB%/*}"
514 func_echo "$(declare -p artifact_glob)"
515
516 local work
517 get_release_dir work
518
519 ## Flatten filesystem, should we recurse here to release subdirs ?
520 # cp $(which ls) "$work"
521 # readarray -t arts < <(find "$artifact_glob" -type f)
522 readarray -t arts < <(find "$work" -type f)
523 [[ ${#arts[@]} -eq 0 ]] && error "Artifact dir is empty, check for build failures: $artifact_glob"
524
Joey Armstrong26707f02023-01-26 12:41:12 -0500525 # Copy artifacts into the release temp dir
526 # shellcheck disable=SC2086
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400527 echo "rsync -rv --checksum \"$artifact_glob/.\" \"$work/.\""
528 rsync -rv --checksum "$artifact_glob/." "$work/."
Joey Armstrong1962bcf2023-01-27 13:53:18 -0500529
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400530 func_echo "LEAVE"
Joey Armstrong26707f02023-01-26 12:41:12 -0500531
Joey Armstrong26707f02023-01-26 12:41:12 -0500532 return
533}
534
535## -----------------------------------------------------------------------
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400536## https://docs.github.com/en/rest/releases?apiVersion=2022-11-28
537 # https://cli.github.com/manual/gh_release_create
538 # --target <branch> or commit SHA
539 # --title
540 # --generate-notes
541 # --release-notes (notes file)
542 # --release
543 # release create dist/*.tgz
544 # --discussion-category "General"
Joey Armstrongf085d872023-01-28 17:52:29 -0500545## -----------------------------------------------------------------------
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400546# https://cli.github.com/manual/gh_release_create
547## -----------------------------------------------------------------------
548function gh_release_create()
Joey Armstrong38bfeea2023-02-06 18:01:29 -0500549{
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400550 banner ''
Joey Armstrong38bfeea2023-02-06 18:01:29 -0500551
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400552 local version="$GIT_VERSION"
553# get_version 'version'
554# create_release_by_version "$version"
Joey Armstrong38bfeea2023-02-06 18:01:29 -0500555
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400556 declare -a args=()
557 args+=('--host-repo')
558 args+=('--notes' "'Testing release create -- ignore'")
559 args+=('--title')
560 if [[ -v draft_release ]]; then
561 args+=('--draft')
562 else
563 args+=('--discussion-category' 'Announcements')
564 fi
Joey Armstrong38bfeea2023-02-06 18:01:29 -0500565
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400566 local work
567 get_release_dir work
568
569 # pushd "$work" >/dev/null
570 readarray -t payload < <(find "$work" ! -type d -print)
571 func_echo "gh release create ${version} ${args[@]}" "${payload[@]}"
572 my_gh 'release' 'create' "'$version'" "${args[@]}" "${payload[@]}"
573 # popd >/dev/null
574
Joey Armstrong38bfeea2023-02-06 18:01:29 -0500575 return
576}
577
578## -----------------------------------------------------------------------
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400579## Intent: Authenticate credentials for a github gh session
Joey Armstrong38bfeea2023-02-06 18:01:29 -0500580## -----------------------------------------------------------------------
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400581## NOTE: my_gh currently unused due to --with-token < "$pac"
582## -----------------------------------------------------------------------
583function do_login()
Joey Armstrongf085d872023-01-28 17:52:29 -0500584{
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400585 declare -g pac
586 declare -a in_args=()
587 [[ $# -gt 0 ]] && in_args+=("$@")
Joey Armstrongf085d872023-01-28 17:52:29 -0500588
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400589 # bridge to my_gh()
590 get_gh_hostname in_args
Joey Armstrongf085d872023-01-28 17:52:29 -0500591
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400592 banner "${in_args[@]}"
Joey Armstrongf085d872023-01-28 17:52:29 -0500593
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400594 ## Read from disk is safer than export GITHUB_TOKEN=
595 if [[ -v pac ]] && [[ ${#pac} -gt 0 ]]; then # interactive/debugging
596 [ ! -f "$pac" ] && error "PAC token file $pac does not exist"
597 # func_echo "--token file is $pac"
598 gh auth login "${in_args[@]}" --with-token < "$pac"
Joey Armstrongf085d872023-01-28 17:52:29 -0500599
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400600 elif [[ ! -v GITHUB_TOKEN ]]; then
601 error "--token [t] or GITHUB_TOKEN= are required"
Joey Armstrong41923cc2023-01-30 14:38:16 -0500602
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400603 else # jenkins
604 func_echo 'Detected ENV{GITHUB_TOKEN}='
605 gh auth login "${in_args[@]}"
606 fi
Joey Armstrongf085d872023-01-28 17:52:29 -0500607
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400608 declare -i -g active_login=1 # signal logout
Joey Armstrongf085d872023-01-28 17:52:29 -0500609
Joey Armstrongf085d872023-01-28 17:52:29 -0500610 return
611}
612
613## -----------------------------------------------------------------------
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400614## Intent: Destroy credentials/gh session authenticated by do_login
615## -----------------------------------------------------------------------
616## NOTE: my_gh currently unused due to "<<< 'y'"
617## -----------------------------------------------------------------------
618function do_logout()
619{
620 declare -i -g active_login
621 [[ ! -v active_login ]] && return
622
623 declare -a out_args=()
624 [[ $# -gt 0 ]] && out_args+=("$@")
625
626 # bridge to my_gh()
627
628 get_gh_hostname in_args
629
630 banner "${out_args[@]}"
631 gh auth logout "${out_args[@]}" <<< 'Y'
632
633 unset active_login
634 return
635}
636
637## -----------------------------------------------------------------------
638## Intent: Query for repository version strings
639## -----------------------------------------------------------------------
640function get_releases()
641{
642 declare -n ref="$1"; shift
643 local func="${FUNCNAME[0]}"
644
645 banner ""
646 pushd "$scratch" >/dev/null
647
648 # gh api repos/{owner}/{repo}/releases
649 local releases_uri
650 get_gh_releases releases_uri
651 declare -p releases_uri
652
653 ref=()
654 gh api "$releases_uri" "${common[@]}" | jq . > 'release.raw'
655 readarray -t __tmp < <(jq '.[] | "\(.tag_name)"' 'release.raw')
656
657 local release
658 for release in "${__tmp[@]}";
659 do
660 release="${release//\"/}"
661 ref+=("$release")
662 done
663
664 popd >/dev/null
665 return
666}
667
668## -----------------------------------------------------------------------
669## Intent: Display repository query strings.
670## Indirect: verify authentication and API
671## -----------------------------------------------------------------------
672function showReleases()
673{
674 declare -a releases=()
675 get_releases releases
676
677 local release
678 for release in "${releases[@]}";
679 do
680 func_echo "$release"
681 done
682 return
683}
684
685## -----------------------------------------------------------------------
686## Intent: Install the gh command line tool locally
Joey Armstrong26707f02023-01-26 12:41:12 -0500687## -----------------------------------------------------------------------
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500688function install_gh_binary()
Joey Armstrong26707f02023-01-26 12:41:12 -0500689{
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400690 banner
Joey Armstrong26707f02023-01-26 12:41:12 -0500691
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500692 pushd "$scratch"
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400693 func_echo "Retrieve latest gh download URLs"
Joey Armstrongf085d872023-01-28 17:52:29 -0500694
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500695 local latest="https://github.com/cli/cli/releases/latest"
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400696 local tarball="gh.tar.tgz"
697
698 readarray -t latest < <(curl --silent -qI "$latest" \
699 | awk -F '/' '/^location/ {print substr($NF, 1, length($NF)-1)}')
700 declare -p latest
701 if [ ${#latest[@]} -ne 1 ]; then
702 error "Unable to determine latest gh package version"
703 fi
704
705 local VER="${latest[0]}"
706
707 func_echo "Download latest gh binary"
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500708 local url="https://github.com/cli/cli/releases/download/${VER}/gh_${VER#v}_linux_amd64.tar.gz"
709 wget --quiet --output-document="$tarball" "$url"
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400710
711 func_echo "Unpack tarball"
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500712 tar zxf "$tarball"
713
714 gh_cmd="$(find "${scratch}" -name 'gh' -print)"
715 readonly gh_cmd
716
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400717 func_echo "Command: ${gh_cmd}"
718 func_echo "Version: $("$gh_cmd" --version)"
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500719 popd
720
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400721 return
722}
723
724## -----------------------------------------------------------------------
725## Intent: Danger Will Robinson
726## -----------------------------------------------------------------------
727function releaseDelete()
728{
729 local version="$1"; shift
730
731 banner "${in_args[@]}"
732 declare -a args=()
733 args+=('--host-repo')
734 args+=('--yes')
735 # args+=('--cleanup-tag')
736
737# ** github-release.sh :: get_argv_repo: VARNAME=opencord/voltctl
738#* 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
739#rror connecting to 'github.com
740#heck your internet connection or https://githubstatus.com
741
742 echo
743 echo "==========================================================================="
744 my_gh 'release' 'delete' "$version" "${args[@]}"
745 echo "==========================================================================="
746 echo
747
748 showReleases
749 return
750}
751
752## -----------------------------------------------------------------------
753## Intent: Copy binaries into temp/release, checksum then publish
754## -----------------------------------------------------------------------
755function release_staging()
756{
757 local release_temp
758 get_release_dir release_temp
759
760 banner ''
761 func_echo "Packaging release files"
762 # pushd "$RELEASE_TEMP"
763 pushd "$release_temp" >/dev/null || error "pushd failed: dir is [$release_temp]"
764
765 readarray -t to_release < <(find . -mindepth 1 -maxdepth 1 -type f -print)
766 func_echo "Files to release: $(declare -p to_release)"
767
768 # Generate and check checksums
769 sha256sum -- * > checksum.SHA256
770 sha256sum -c < checksum.SHA256
771
772 echo
773 func_echo "Checksums(checksum.SHA256):"
774 cat checksum.SHA256
775
776 ## ARGS NEEDED
777 gh_release_create
778
779 popd >/dev/null || error "pushd failed: dir is [$release_temp]"
780
781 return
782}
783
784## -----------------------------------------------------------------------
785## Intent: Display program usage
786## -----------------------------------------------------------------------
787function usage()
788{
789 [[ $# -gt 0 ]] && func_echo "$*"
790
791 cat <<EOH
792Usage: github-release.sh [options] [target] ...
793
794[Github CLI (gh) arguments]
795 --login Perform authentication using a PAC
796 --logout
797 --host [h] Specify github server for connection.
798
799[Options]
800 --token Login debugging, alternative to env var use.
801
802[Modes]
803 --debug Enable script debug mode
804 --verbose Enable script verbose mode
805
806All remaining arguments are passthrough to the gh command.
807EOH
808
809 exit 0
810}
811
812## -----------------------------------------------------------------------
813## Intent: Provide common arguments and access to the gh command.
814## o Cache path to the gh command
815## o Construct a gh command line from given args
816## o Command wrapper can provide defaults (--hostname github.com)
817## -----------------------------------------------------------------------
818## Given:
819## scalar Array variable name (declare -n is a reference)
820## Return:
821## ref gh command line passed back to caller
822## Switches:
823## --host Pass default github hostname
824## --verbose Enable verbose mode#
825## --version Display command version
826## @array Remaining arguments passed as command switches.
827## -----------------------------------------------------------------------
828## See Also:
829## o https://cli.github.com/manual
830## -----------------------------------------------------------------------
831function my_gh()
832{
833 ## ------------------------
834 ## Cache path to gh command
835 ## ------------------------
836 if [[ ! -v gh_cmd ]]; then
837 readarray -t cmds < <(which -a gh)
838 declare -p cmds
839 if [ ${#cmds} -eq 0 ]; then
840 error "Unable to locate the gh command"
841 fi
842 gh_cmd="${cmds[0]}"
843 readonly gh_cmd
844 fi
845
846 declare -a cmd=()
847 cmd+=("$gh_cmd")
848
849 ## ----------------------
850 ## Construct command line
851 ## ----------------------
852 # shellcheck disable=SC2034
853 declare -A action=() # pending operations
854 declare -a args=() # common gh command line args
855
856 while [ $# -gt 0 ]; do
857 local arg="$1"; shift
858 case "$arg" in
859
860 # Modes
861 -*debug) declare -i -g debug=1 ;;
862 -*help) show_help ;;
863 -*verbose) args+=('--verbose') ;;
864
865 -*hostname)
866 get_gh_hostname in_args
867 ;;
868
869 --host-repo)
870 local val
871 get_argv_repo val
872
873 # --repo <[HOST/]OWNER/REPO>
874 args+=('--repo' "'${__githost}/${val}'")
875 ;;
876
877 --repo)
878 local val
879 get_argv_repo val
880 args+=('--repo' "$val")
881 ;;
882
883 --tag)
884 local val
885 get_argv_tag val
886 args+=("'$val'") # No switch, pass inline
887 ;;
888
889 --title)
890 local val
891 get_argv_name val
892 args+=('--title' "'$val'")
893 ;;
894
895 # --draft
896 # --latest
897 *) args+=("$arg") ;;
898 esac
899 done
900
901 cmd+=("${args[@]}")
902 echo "** Running: ${cmd[*]}"
903 "${cmd[@]}"
904 local status=$?
905
906 [[ $status -eq 0 ]] && { true; } || { false; }
907 return
908}
909
910## ---------------------------------------------------------------------------
911## Intent:
912## ---------------------------------------------------------------------------
913function usage()
914{
915 cat <<EOH
916
917Usage: $0
918Usage: make [options] [target] ...
919 --help This mesage
920 --pac Personal Access Token (file)
921
922[DEBUG]
923 --gen-version Generate a random release version string.
924 --git-hostname Git server hostname (default=github.com)
925
926EOH
927 return
928}
929
930## ---------------------------------------------------------------------------
931## Intent: Parse script command line arguments
932## ---------------------------------------------------------------------------
933function parse_args()
934{
935 # declare -n ref="$1"; shift
936
937 [[ -v DEBUG ]] && func_echo "ENTER"
938
939# ref="repos/${__repo_user}/${__repo_name}/releases"
940
941 while [ $# -gt 0 ]; do
942 local arg="$1"; shift
943 case "$arg" in
944 -*gen-version)
945 get_version GIT_VERSION
946 ;;
947
948 -*git-hostname)
949 __githost="$1"; shift
950 ;;
951
952 -*repo-name)
953 __repo_name="$1"; shift
954 ;;
955
956 -*repo-org)
957 __repo_org="$1"; shift
958 ;;
959
960 -*pac)
961 declare -g pac="$1"; shift
962 readonly pac
963 [[ ! -f "$pac" ]] && error "--token= does not exist ($pac)"
964 : # nop/true
965 ;;
966
967 -*help)
968 usage
969 exit 0
970 ;;
971 *) error "Detected unknown argument $arg" ;;
972 esac
973 done
974
Joey Armstrong26707f02023-01-26 12:41:12 -0500975 return
976}
977
Joey Armstrongaf577ab2022-12-15 14:43:33 -0500978##----------------##
979##---] MAIN [---##
980##----------------##
Joey Armstrong1962bcf2023-01-27 13:53:18 -0500981iam="${0##*/}"
982
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400983full_banner
984parse_args $@
Joey Armstrongd99e3d22023-01-29 12:35:43 -0500985init
986install_gh_binary
Joey Armstrong7f382ef2023-01-25 12:00:08 -0500987
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400988do_login
Zack Williams27cd3e52018-09-18 16:44:50 -0700989
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400990release_path='/dev/null'
991get_release_path release_path
992declare -p release_path
Zack Williams27cd3e52018-09-18 16:44:50 -0700993
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400994pushd "$release_path" || error "pushd failed: dir is [$release_path]"
Zack Williams27cd3e52018-09-18 16:44:50 -0700995
Joey Armstrong2097d3e2023-03-26 10:32:03 -0400996 # legacy: getGitVersion "$GERRIT_PROJECT" GIT_VERSION
997 getGitVersion GIT_VERSION
998 getReleaseDescription RELEASE_DESCRIPTION
Zack Williams27cd3e52018-09-18 16:44:50 -0700999
Joey Armstrong2097d3e2023-03-26 10:32:03 -04001000 # build the release, can be multiple space separated targets
1001 # -----------------------------------------------------------------------
1002 # % go build command-line-arguments:
1003 # copying /tmp/go-build4212845548/b001/exe/a.out:
1004 # open release/voltctl-1.8.25-linux-amd64: permission denied
1005 # missing: docker run mkdir
1006 # -----------------------------------------------------------------------
1007 # shellcheck disable=SC2086
1008 make "$RELEASE_TARGETS" || tyue
Zack Williams27cd3e52018-09-18 16:44:50 -07001009
Joey Armstrong2097d3e2023-03-26 10:32:03 -04001010 copyToRelease
Joey Armstrong50f6e0b2023-01-24 14:14:08 -05001011
Joey Armstrong26707f02023-01-26 12:41:12 -05001012 cat <<EOM
Joey Armstrong1962bcf2023-01-27 13:53:18 -05001013
1014** -----------------------------------------------------------------------
1015** Create the release:
1016** 1) Create initial github release with download area.
1017** 2) Generate checksum.SHA256 for all released files.
1018** 3) Upload files to complete the release.
1019** 4) Display released info from github.
1020** -----------------------------------------------------------------------
Joey Armstrong26707f02023-01-26 12:41:12 -05001021EOM
1022
Joey Armstrong2097d3e2023-03-26 10:32:03 -04001023 showReleases
1024 # releaseDelete 'v4.175.710'
1025 release_staging
1026 popd || error "pushd failed: dir is [$release_path]"
Zack Williams27cd3e52018-09-18 16:44:50 -07001027fi
Joey Armstrong28eddda2023-01-10 03:09:34 -05001028
Joey Armstrong2097d3e2023-03-26 10:32:03 -04001029do_logout
1030
Joey Armstrong28eddda2023-01-10 03:09:34 -05001031# [SEE ALSO]
1032# -----------------------------------------------------------------------
1033# https://www.shellcheck.net/wiki/SC2236
Joey Armstrong26707f02023-01-26 12:41:12 -05001034# https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#create-a-release
Joey Armstrong28eddda2023-01-10 03:09:34 -05001035# -----------------------------------------------------------------------
Joey Armstrongf085d872023-01-28 17:52:29 -05001036# https://cli.github.com/manual/gh_help_reference
1037# https://cli.github.com/manual/gh_release
1038# -----------------------------------------------------------------------
Joey Armstrong28eddda2023-01-10 03:09:34 -05001039
1040# [EOF]