diff options
author | bill-auger <mr.j.spam.me@gmail.com> | 2023-12-24 02:32:07 -0500 |
---|---|---|
committer | bill-auger <mr.j.spam.me@gmail.com> | 2024-03-28 23:13:17 -0400 |
commit | 2478cf7b101ec6769b45b8372c2e7aba8dd8b1d8 (patch) | |
tree | 6d3475d7547d355e20534df920a4a848d8e16dcb | |
parent | fdd119785384d8c0438b6a1bfd822d6933882972 (diff) |
replace REPODEST config with REPO{USER,HOST,PORT,PATH}
-rwxr-xr-x | src/abslibre-tools/librerelease | 112 | ||||
-rw-r--r-- | src/lib/notifications.sh | 6 | ||||
-rw-r--r-- | src/libretools.conf | 34 | ||||
-rw-r--r-- | test/cases/librerelease.bats | 83 |
4 files changed, 170 insertions, 65 deletions
diff --git a/src/abslibre-tools/librerelease b/src/abslibre-tools/librerelease index 560e8d1..70a20b0 100755 --- a/src/abslibre-tools/librerelease +++ b/src/abslibre-tools/librerelease @@ -57,6 +57,16 @@ readonly rsync_flags=( --progress ) +DRY_RUN='' # main() +UPLOAD_ONLY='' # main() +TIER0_HOST='' # main() +TIER0_STAGING='' # main() +TIER0_LOGIN='' # main() +TIER0_PORT='' # main() +SSH_CMD='' # main() +RSYNC_DEST='' # main() + + # Functions #################################################################### list0_files() { @@ -127,7 +137,21 @@ clean_files() ( usage() { print "Usage: %s [OPTIONS]" "${0##*/}" - print 'Upload packages in $WORKDIR/staging to the Parabola server' + prose 'Upload packages staged in %s (per `librestage`) to the configured server, + and publish them to their respective repositories.' \$WORKDIR/staging + echo + prose 'This requires the `gpg` program, configured with your GPG key, + and a staging directory (%s), writable by %s.' \$WORKDIR/staging '$LIBREUSER' + prose '%s is determined at runtime, by %s. + %s is normally the local login of the invoking user, + but may be over-ridden by setting %s in the environment.' \ + '$LIBREUSER' /usr/lib/libretools/conf.sh '$LIBREUSER' '$SUDO_USER' + prose 'By default, %s is assumed to match the hackers.git login + for which %s has login credentials for the repo server. + If %s does not match the hackers.git login, + you must specify %s as the remote login, (eg: in %s)' \ + '$LIBREUSER' '$LIBREUSER' '$LIBREUSER' '$TIER0_LOGIN' \ + \$XDG_CONFIG_HOME/libretools/libretools.conf echo print "Options:" flag '-c' 'Clean; delete packages in $WORKDIR/staging' @@ -167,54 +191,38 @@ main() { return $EXIT_SUCCESS fi - declare -i ret=0 - load_conf makepkg.conf GPGKEY || ret=$? - load_conf libretools.conf WORKDIR REPODEST DBSCRIPTS_CONFIG || ret=$? # and HOOK{PRE,POST}RELEASE, which are optional - [[ $ret = 0 ]] || exit $ret - - local re_url='^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$' - local re_authority='^(([^@]*)@)?([^][@:]*|\[[^]]*\])(:([0-9]*))?$' - local REPODEST_ok=false - if [[ "$REPODEST" =~ $re_url ]]; then - REPODEST_ok=true - - REPODEST_scheme=${BASH_REMATCH[2]} - REPODEST_authority=${BASH_REMATCH[4]} - REPODEST_path=${BASH_REMATCH[5]} - REPODEST_query=${BASH_REMATCH[7]} - REPODEST_fragment=${BASH_REMATCH[9]} - - if [[ "$REPODEST_authority" =~ $re_authority ]]; then - REPODEST_userinfo=${BASH_REMATCH[2]} - REPODEST_host=${BASH_REMATCH[3]} - REPODEST_port=${BASH_REMATCH[5]} - - if [[ "$REPODEST_host" = '['*']' ]]; then - REPODEST_host=${REPODEST_HOST#'['} - REPODEST_host=${REPODEST_HOST#']'} - fi - else - REPODEST_ok=false - fi - - [[ $REPODEST_scheme == ssh ]] || REPODEST_ok=false - [[ -n $REPODEST_host ]] || REPODEST_ok=false - [[ -n $REPODEST_path ]] || REPODEST_ok=false - fi - if ! $REPODEST_ok; then - error 'The format of libretools.conf:REPODEST has changed.' - plain 'Merge the /etc/libretools.conf.pacnew file!' + # source makepkg and libretools configuration files + # the specified config vars will be used in this script, and so are mandatory + # optional config vars used in this script, if specified in libretools.conf: + # TIER0_LOGIN, TIER0_PORT, TIER0_STAGING, HOOKPRERELEASE, HOOKPOSTRELEASE + if ! load_conf makepkg.conf GPGKEY; then + error '$GPGKEY is not configured.' + return $EXIT_NOTCONFIGURED + elif ! load_conf libretools.conf WORKDIR TIER0_HOST DBSCRIPTS_CONFIG; then + config_error_msg WORKDIR TIER0_HOST DBSCRIPTS_CONFIG return $EXIT_NOTCONFIGURED fi - if [[ "$REPODEST_path" = '/~'* ]]; then - if [[ "$REPODEST_path" = '/~/'* ]]; then - REPODEST_path=${REPODEST_path#'/~/'} - else - error 'Unfortunately, `~user` home-directory expansion is not (yet?) supported in libretools.conf:REPODEST' + + # validate/sanitize tier-0 repo URL components + if [[ -n ${TIER0_HOST:-} ]]; then + # normalize or reject tilde operator in staging path + if [[ "$TIER0_STAGING" == '/~/'* ]]; then + TIER0_STAGING=${TIER0_STAGING#'/~/'} + elif [[ "$TIER0_STAGING" == '/~'* ]]; then + error "Unfortunately, tilde expansion ('~' home directory) is not supported in libretools.conf::TIER0_STAGING" return $EXIT_NOTCONFIGURED fi + else + config_error_msg TIER0_HOST ; return $EXIT_NOTCONFIGURED ; fi - REPODEST_userhost="${REPODEST_userinfo:+${REPODEST_userinfo%%:*}@}${REPODEST_host}" + + # construct the SSH and rsync destination parameters + readonly TIER0_HOST + readonly TIER0_STAGING=${TIER0_STAGING:-/home/${TIER0_LOGIN:-$LIBREUSER}/staging} + readonly TIER0_LOGIN=${TIER0_LOGIN:+${TIER0_LOGIN}@} + readonly TIER0_PORT=${TIER0_PORT:+-p $TIER0_PORT} + readonly SSH_CMD=( ssh ${TIER0_PORT} ${TIER0_LOGIN}${TIER0_HOST} ) + readonly RSYNC_DEST=${TIER0_LOGIN}${TIER0_HOST}:${TIER0_STAGING%/}/ "$mode" } @@ -245,12 +253,17 @@ clean() { } release_packages() { - local login_err_msg="connection or login failed" local tier0_port="${REPODEST_port:+-p "$REPODEST_port"}" local tier0_host="${REPODEST_userhost}" - local ssh_cmd="ssh ${tier0_port} ${tier0_host}" # eg: ssh -p 1863 autobuilder@repo.parabola.nu STAGING='staging/' DBSCRIPTS_CONFIG='/etc/dbscripts/config.local.parabola' db-update + local ssh_cmd=( ssh ${tier0_port} ${tier0_host} ) # eg: ssh -p 1863 autobuilder@repo.parabola.nu STAGING='staging/' DBSCRIPTS_CONFIG='/etc/dbscripts/config.local.parabola' db-update local dbupdate_cmd="STAGING=${REPODEST_path@Q} DBSCRIPTS_CONFIG=${DBSCRIPTS_CONFIG@Q} db-update" + # verify connection and login + if ! ${ssh_cmd[0]} -fN ${ssh_cmd[*]:1}; then + error "Connection or login failed." + return $EXIT_FAILURE + fi + ## prepare ## @@ -301,8 +314,8 @@ release_packages() { ## publish ## - msg "Running db-update on repos" - ${ssh_cmd} "${dbupdate_cmd}" + msg "Running db-update on repos" + ${ssh_cmd[*]} "${dbupdate_cmd}" if [[ -n $HOOKPOSTRELEASE ]]; then msg "Running HOOKPOSTRELEASE..." @@ -315,10 +328,11 @@ release_packages() { ## notify pbot of the excellent work we have done ## - notify_pbot "${ssh_cmd}" < $file_list + notify_pbot ${ssh_cmd[*]} < $file_list return $EXIT_SUCCESS } + main "$@" diff --git a/src/lib/notifications.sh b/src/lib/notifications.sh index e29d929..2aa0b0e 100644 --- a/src/lib/notifications.sh +++ b/src/lib/notifications.sh @@ -1,7 +1,7 @@ # process librerelease::$file_list via STDIN -notify_pbot() # ( "ssh_cmd" ) file_list->STDIN +notify_pbot() # ( ssh_cmd*** ) file_list->STDIN { - local ssh_cmd="$1" + local ssh_cmd=( $* ) local repo_user=${REPOUSER:-${LIBREUSER:-somebody}} local select_rx='\.pkg\.tar\.[^\.]+$' local reject_rx='-debug-' @@ -24,6 +24,6 @@ notify_pbot() # ( "ssh_cmd" ) file_list->STDIN if [[ ${ssh_cmd[0]} =~ ^ssh\ ]] && (( ${#releases[@]} )); then msg2 "$(_ "Notifying pbot:")" ; print " ${pbotsay_msg}" ; - ${ssh_cmd} "${pbotsay_cmd}" &> /dev/null || : + ${ssh_cmd[*]} "${pbotsay_cmd}" &> /dev/null || : fi } diff --git a/src/libretools.conf b/src/libretools.conf index 3ff162c..b99a347 100644 --- a/src/libretools.conf +++ b/src/libretools.conf @@ -1,6 +1,7 @@ #!/hint/bash # shellcheck disable=2034 + ################################################################################ # misc # ################################################################################ @@ -21,25 +22,35 @@ DIFFPROG=$(which $([ -z "${DISPLAY:-}" ]||echo kdiff3 meld gvimdiff) vimdiff col ABSLIBRERECV=git://git.parabola.nu/abslibre/abslibre.git ABSLIBRESEND=ssh://git@git.parabola.nu:1863/~git/abslibre/abslibre.git + ################################################################################ # librerelease # ################################################################################ -## Login on the $REPODEST server (normally, your hackers.git login) -# Uncomment this and set it to your $REPODEST login, if your $LIBREUSER differs. -# $REPOUSER may also be set in the environment. -# Alternatively, leave it unset and configure your default login in ~/.ssh/config. -# REPOUSER= - -## Where to upload packages to -REPODEST=ssh://$REPOUSER@repo.parabola.nu:1863/~/staging/ -## Which config file to use with db-update (on the $REPODEST server) +## Login on the $TIER0_HOST server (normally, your hackers.git login) +# Un-comment this and set it to your $TIER0_HOST login, if your $LIBREUSER differs. +# $TIER0_LOGIN may also be set in the environment. +# TIER0_LOGIN= + +## The host, port, and remote staging directory for uploading packages via SSH +# `librerelease` will fail if $TIER0_HOST is unset or if any of these are invalid. +# $TIER0_PORT and $TIER0_STAGING are optional. If not configured, +# the SSH port ($TIER0_PORT) will be the SSH system default; +# and the remote staging location ($TIER0_STAGING) will be ~$TIER0_LOGIN/staging/. +# Mind $TIER0_STAGING especially. `librerelease -C` deletes this entire directory. +# Do not use tilde ('~') in $TIER0_STAGING. Specify an absolute path instead. +TIER0_HOST=repo.parabola.nu +TIER0_PORT=1863 +TIER0_STAGING= + +## Config file on the $REPOHOST server for `db-update` DBSCRIPTS_CONFIG=/etc/dbscripts/config.local.parabola -## These are run before and after uploading packages -HOOKPRERELEASE='ssh -fN ${REPODEST_port:+-p "$REPODEST_port"} "${REPODEST_userhost}"' +## Pre- and Post- hooks (BASH commands to run before or after uploading packages) +HOOKPRERELEASE= HOOKPOSTRELEASE="sudo librechroot clean-repo" + ################################################################################ # dagpkg # ################################################################################ @@ -61,6 +72,7 @@ FULLBUILDCMD="sudo libremakepkg" # successfully. When run, it is given a repository name as a single argument. HOOKLOCALRELEASE="librestage" + ################################################################################ # toru # ################################################################################ diff --git a/test/cases/librerelease.bats b/test/cases/librerelease.bats index a984d73..245a6dc 100644 --- a/test/cases/librerelease.bats +++ b/test/cases/librerelease.bats @@ -30,7 +30,9 @@ setup() { # Configure libretools cat >> "$XDG_CONFIG_HOME/libretools/libretools.conf" <<-eot - REPODEST=ssh://${USER@Q}@127.0.0.1:${ssh_port@Q}/${tmpdir@Q}/srv-staging/ + TIER0_HOST=127.0.0.1 + TIER0_PORT=$ssh_port + TIER0_STAGING=${tmpdir@Q}/srv-staging/ DBSCRIPTS_CONFIG=/etc/dbscripts/config.local.phony HOOKPRERELEASE=: HOOKPOSTRELEASE=: @@ -74,7 +76,7 @@ teardown() { diff "$tmpdir/list-correct" "$tmpdir/list" } -@test "librerelease fails if gpgkey not set" { +@test "librerelease fails if GPGKEY not set" { unset GPGKEY local workdir="$tmpdir/workdir" @@ -92,6 +94,24 @@ teardown() { grep GPGKEY "$tmpdir/stderr" } +@test "librerelease fails if TIER0_HOST not set" { + unset TIER0_HOST + + local workdir="$tmpdir/workdir" + mkdir -p "$workdir/staging/repo1" "$workdir/staging/repo2/sub" + touch \ + "$workdir/staging/repo1/file1" \ + "$workdir/staging/repo1/file2" \ + "$workdir/staging/repo2/file with spaces" \ + "$workdir/staging/repo2/sub/subfolder" + + LC_ALL=C librerelease -l >"$tmpdir/stdout" 2>"$tmpdir/stderr" || status=$? + + [[ $status != 0 ]] + empty "$tmpdir/stdout" + grep TIER0_HOST "$tmpdir/stderr" +} + @test "librerelease fails if DBSCRIPTS_CONFIG is not set" { cat >> "$XDG_CONFIG_HOME/libretools/libretools.conf" <<-eot DBSCRIPTS_CONFIG='' @@ -224,3 +244,62 @@ teardown() { diff -u "$tmpdir/pwd.txt" "$tmpdir/postrelease.txt" grep 'just published' "$tmpdir/pbot.txt" } + +@test "librerelease logs in as TIER0_LOGIN" { + # Add a stub db-update pbot-say so that when we ssh to localhost it has + # something to run. + install -Dm755 /dev/stdin "$tmpdir/bin/db-update" <<-eot + #!/bin/bash + { + printf '%s\n' "\$DBSCRIPTS_CONFIG" + readlink -f -- "\$STAGING" + find "\$STAGING" -printf '%P\n' | LC_COLLATE=C sort + } > ${tmpdir@Q}/log.txt + eot + install -Dm755 /dev/stdin "$tmpdir/bin/pbot-say" <<-eot + #!/bin/bash + echo "\$*" >${tmpdir@Q}/pbot.txt + eot + PATH=$tmpdir/bin:$PATH + + # Log which directories the hooks are run in. + cat >> "$XDG_CONFIG_HOME/libretools/libretools.conf" <<-eot + HOOKPRERELEASE='pwd > ${tmpdir@Q}/prerelease.txt' + HOOKPOSTRELEASE='pwd > ${tmpdir@Q}/postrelease.txt' + eot + + # Make some files to stage + local workdir="$tmpdir/workdir" + mkdir -p "$workdir/staging/repo1" "$workdir/staging/repo2/sub" + touch \ + "$workdir/staging/repo1/file1" \ + "$workdir/staging/repo1/file2" \ + "$workdir/staging/repo2/file with spaces" \ + "$workdir/staging/repo2/sub/subfolder" + + # Run + TIER0_LOGIN=tier0-user librerelease + + # Make sure everything went OK + pwd > "$tmpdir/pwd.txt" + cat > "$tmpdir/log-correct.txt" <<-eot + /etc/dbscripts/config.local.phony + $(readlink -f -- "$tmpdir/srv-staging") + + repo1 + repo1/file1 + repo1/file1.sig + repo1/file2 + repo1/file2.sig + repo2 + repo2/file with spaces + repo2/file with spaces.sig + repo2/sub + repo2/sub/subfolder + repo2/sub/subfolder.sig + eot + diff -u "$tmpdir/log-correct.txt" "$tmpdir/log.txt" + diff -u "$tmpdir/pwd.txt" "$tmpdir/prerelease.txt" + diff -u "$tmpdir/pwd.txt" "$tmpdir/postrelease.txt" + grep 'tier0-user just published' "$tmpdir/pbot.txt" +} |