diff --git a/bin/doc b/bin/doc index ed4a3540..9ff04463 100755 --- a/bin/doc +++ b/bin/doc @@ -677,6 +677,7 @@ Github::upgradeRelease() { } FILTER_LAST_VERSION_CALLBACK=${FILTER_LAST_VERSION_CALLBACK:-extractVersion} \ SOFT_VERSION_CALLBACK="${softVersionCallback}" \ + INSTALL_CALLBACK="${installCallback}" \ Web::upgradeRelease \ "${targetFile}" \ "${releasesUrl}" \ @@ -1544,12 +1545,27 @@ Version::parse() { Web::getReleases() { local releaseListUrl="$1" # Get latest release from GitHub api - Retry::parameterized "${RETRY_MAX_RETRY:-5}" "${RETRY_DELAY_BETWEEN_RETRIES:-15}" "Retrieving release versions list ..." curl \ - -L \ - --connect-timeout "${CURL_CONNECT_TIMEOUT:-5}" \ - --fail \ - --silent \ - "${releaseListUrl}" + if command -v gh &>/dev/null && [[ -n "${GH_TOKEN}" ]]; then + Log::displayDebug "Using gh to retrieve release versions list" + Retry::parameterized "${RETRY_MAX_RETRY:-5}" \ + "${RETRY_DELAY_BETWEEN_RETRIES:-15}" \ + "Retrieving release versions list ..." \ + gh api "${releaseListUrl#https://github.com}" + else + if command -v gh &>/dev/null && [[ "${GH_WARNING_DISPLAYED:-0}" = "0" ]]; then + Log::displayWarning "GH_TOKEN is not set, cannot use gh, using curl to retrieve release versions list" + GH_WARNING_DISPLAYED=1 + fi + Retry::parameterized "${RETRY_MAX_RETRY:-5}" \ + "${RETRY_DELAY_BETWEEN_RETRIES:-15}" \ + "Retrieving release versions list ..." \ + curl \ + -L \ + --connect-timeout "${CURL_CONNECT_TIMEOUT:-5}" \ + --fail \ + --silent \ + "${releaseListUrl}" + fi } @@ -1567,6 +1583,7 @@ Web::getReleases() { # @env PARSE_VERSION_CALLBACK a callback to parse the version of the existing command # @env INSTALL_CALLBACK a callback to install the software downloaded # @env CURL_CONNECT_TIMEOUT number of seconds before giving up host connection +# @env VERSION_PLACEHOLDER a placeholder to replace in downloadReleaseUrl (default: @latestVersion@) Web::upgradeRelease() { local targetFile="$1" local releasesUrl="$2" @@ -1577,25 +1594,28 @@ Web::upgradeRelease() { local filterLastVersionCallback="${FILTER_LAST_VERSION_CALLBACK:-Version::parse}" local softVersionCallback="${SOFT_VERSION_CALLBACK:-Version::getCommandVersionFromPlainText}" local installCallback="${INSTALL_CALLBACK:-}" - local latestVersion - latestVersion="$(Web::getReleases "${releasesUrl}" | ${filterLastVersionCallback})" || { - Log::displayError "latest version not found on ${releasesUrl}" - return 1 - } - Log::displayInfo "Latest version found is ${latestVersion}" local currentVersion="not existing" if [[ -f "${targetFile}" ]]; then currentVersion="$(${softVersionCallback} "${targetFile}" "${softVersionArg}" 2>&1 || true)" fi if [[ -z "${exactVersion}" ]]; then + local latestVersion + latestVersion="$(Web::getReleases "${releasesUrl}" | ${filterLastVersionCallback})" || { + Log::displayError "latest version not found on ${releasesUrl}" + return 1 + } + Log::displayInfo "Latest version found is ${latestVersion}" + exactVersion="${latestVersion}" fi - local url="${downloadReleaseUrl//@latestVersion@/${exactVersion}}" + local url="${downloadReleaseUrl//${VERSION_PLACEHOLDER:-@latestVersion@}/${exactVersion}}" if [[ -n "${exactVersion}" ]] && ! Github::isReleaseVersionExist "${url}"; then Log::displayError "${targetFile} version ${exactVersion} doesn't exist on github" return 2 fi + Log::displayDebug "currentVersion: '${currentVersion}'" + Log::displayDebug "exactVersion: '${exactVersion}'" if [[ "${currentVersion}" = "${exactVersion}" ]]; then Log::displayInfo "${targetFile} version ${exactVersion} already installed" else diff --git a/bin/dockerLint b/bin/dockerLint index 80ea2f8a..6be8cb2c 100755 --- a/bin/dockerLint +++ b/bin/dockerLint @@ -488,6 +488,7 @@ Github::upgradeRelease() { } FILTER_LAST_VERSION_CALLBACK=${FILTER_LAST_VERSION_CALLBACK:-extractVersion} \ SOFT_VERSION_CALLBACK="${softVersionCallback}" \ + INSTALL_CALLBACK="${installCallback}" \ Web::upgradeRelease \ "${targetFile}" \ "${releasesUrl}" \ @@ -612,6 +613,19 @@ Log::displaySuccess() { } +# @description Display message using warning color (yellow) +# @arg $1 message:String the message to display +# @env DISPLAY_DURATION int (default 0) if 1 display elapsed time information between 2 info logs +# @env LOG_CONTEXT String allows to contextualize the log +Log::displayWarning() { + if ((BASH_FRAMEWORK_DISPLAY_LEVEL >= __LEVEL_WARNING)); then + Log::computeDuration + echo -e "${__WARNING_COLOR}WARN - ${LOG_CONTEXT:-}${LOG_LAST_DURATION_STR:-}${1}${__RESET_COLOR}" >&2 + fi + Log::logWarning "$1" +} + + # @description Display message using error color (red) and exit immediately with error status 1 # @arg $1 message:String the message to display # @env DISPLAY_DURATION int (default 0) if 1 display elapsed time information between 2 info logs @@ -704,6 +718,15 @@ Log::logSuccess() { } +# @description log message to file +# @arg $1 message:String the message to display +Log::logWarning() { + if ((BASH_FRAMEWORK_LOG_LEVEL >= __LEVEL_WARNING)); then + Log::logMessage "${2:-WARNING}" "$1" + fi +} + + # @description activate or not Log::display* and Log::log* functions # based on BASH_FRAMEWORK_DISPLAY_LEVEL and BASH_FRAMEWORK_LOG_LEVEL # environment variables loaded by Env::requireLoad @@ -1074,12 +1097,27 @@ Version::parse() { Web::getReleases() { local releaseListUrl="$1" # Get latest release from GitHub api - Retry::parameterized "${RETRY_MAX_RETRY:-5}" "${RETRY_DELAY_BETWEEN_RETRIES:-15}" "Retrieving release versions list ..." curl \ - -L \ - --connect-timeout "${CURL_CONNECT_TIMEOUT:-5}" \ - --fail \ - --silent \ - "${releaseListUrl}" + if command -v gh &>/dev/null && [[ -n "${GH_TOKEN}" ]]; then + Log::displayDebug "Using gh to retrieve release versions list" + Retry::parameterized "${RETRY_MAX_RETRY:-5}" \ + "${RETRY_DELAY_BETWEEN_RETRIES:-15}" \ + "Retrieving release versions list ..." \ + gh api "${releaseListUrl#https://github.com}" + else + if command -v gh &>/dev/null && [[ "${GH_WARNING_DISPLAYED:-0}" = "0" ]]; then + Log::displayWarning "GH_TOKEN is not set, cannot use gh, using curl to retrieve release versions list" + GH_WARNING_DISPLAYED=1 + fi + Retry::parameterized "${RETRY_MAX_RETRY:-5}" \ + "${RETRY_DELAY_BETWEEN_RETRIES:-15}" \ + "Retrieving release versions list ..." \ + curl \ + -L \ + --connect-timeout "${CURL_CONNECT_TIMEOUT:-5}" \ + --fail \ + --silent \ + "${releaseListUrl}" + fi } @@ -1097,6 +1135,7 @@ Web::getReleases() { # @env PARSE_VERSION_CALLBACK a callback to parse the version of the existing command # @env INSTALL_CALLBACK a callback to install the software downloaded # @env CURL_CONNECT_TIMEOUT number of seconds before giving up host connection +# @env VERSION_PLACEHOLDER a placeholder to replace in downloadReleaseUrl (default: @latestVersion@) Web::upgradeRelease() { local targetFile="$1" local releasesUrl="$2" @@ -1107,25 +1146,28 @@ Web::upgradeRelease() { local filterLastVersionCallback="${FILTER_LAST_VERSION_CALLBACK:-Version::parse}" local softVersionCallback="${SOFT_VERSION_CALLBACK:-Version::getCommandVersionFromPlainText}" local installCallback="${INSTALL_CALLBACK:-}" - local latestVersion - latestVersion="$(Web::getReleases "${releasesUrl}" | ${filterLastVersionCallback})" || { - Log::displayError "latest version not found on ${releasesUrl}" - return 1 - } - Log::displayInfo "Latest version found is ${latestVersion}" local currentVersion="not existing" if [[ -f "${targetFile}" ]]; then currentVersion="$(${softVersionCallback} "${targetFile}" "${softVersionArg}" 2>&1 || true)" fi if [[ -z "${exactVersion}" ]]; then + local latestVersion + latestVersion="$(Web::getReleases "${releasesUrl}" | ${filterLastVersionCallback})" || { + Log::displayError "latest version not found on ${releasesUrl}" + return 1 + } + Log::displayInfo "Latest version found is ${latestVersion}" + exactVersion="${latestVersion}" fi - local url="${downloadReleaseUrl//@latestVersion@/${exactVersion}}" + local url="${downloadReleaseUrl//${VERSION_PLACEHOLDER:-@latestVersion@}/${exactVersion}}" if [[ -n "${exactVersion}" ]] && ! Github::isReleaseVersionExist "${url}"; then Log::displayError "${targetFile} version ${exactVersion} doesn't exist on github" return 2 fi + Log::displayDebug "currentVersion: '${currentVersion}'" + Log::displayDebug "exactVersion: '${exactVersion}'" if [[ "${currentVersion}" = "${exactVersion}" ]]; then Log::displayInfo "${targetFile} version ${exactVersion} already installed" else diff --git a/bin/installFacadeExample b/bin/installFacadeExample index c5dc2a84..6373e080 100755 --- a/bin/installFacadeExample +++ b/bin/installFacadeExample @@ -516,39 +516,39 @@ Log::logFatal() { # FUNCTIONS facade_main_installFacadeExamplesh() { -FRAMEWORK_ROOT_DIR="$(cd "${CURRENT_DIR}/.." && pwd -P)" -FRAMEWORK_SRC_DIR="${FRAMEWORK_ROOT_DIR}/src" -FRAMEWORK_BIN_DIR="${FRAMEWORK_ROOT_DIR}/bin" -FRAMEWORK_VENDOR_DIR="${FRAMEWORK_ROOT_DIR}/vendor" -FRAMEWORK_VENDOR_BIN_DIR="${FRAMEWORK_ROOT_DIR}/vendor/bin" -# REQUIRES -Env::requireLoad -Log::requireLoad -UI::requireTheme -Compiler::Facade::requireCommandBinDir - -# @require Compiler::Facade::requireCommandBinDir - -install() { - echo "installation in progress" -} - -local action=$1 -shift || true -case ${action} in - install) - install "$@" - ;; - *) - if Assert::functionExists defaultFacadeAction; then - defaultFacadeAction "$1" "$@" - else - Log::displayError "invalid action requested: ${action}" - exit 1 - fi - ;; -esac -exit 0 + FRAMEWORK_ROOT_DIR="$(cd "${CURRENT_DIR}/.." && pwd -P)" + FRAMEWORK_SRC_DIR="${FRAMEWORK_ROOT_DIR}/src" + FRAMEWORK_BIN_DIR="${FRAMEWORK_ROOT_DIR}/bin" + FRAMEWORK_VENDOR_DIR="${FRAMEWORK_ROOT_DIR}/vendor" + FRAMEWORK_VENDOR_BIN_DIR="${FRAMEWORK_ROOT_DIR}/vendor/bin" + # REQUIRES + Env::requireLoad + Log::requireLoad + UI::requireTheme + Compiler::Facade::requireCommandBinDir + + # @require Compiler::Facade::requireCommandBinDir + + install() { + echo "installation in progress" + } + + local action=$1 + shift || true + case ${action} in + install) + install "$@" + ;; + *) + if Assert::functionExists defaultFacadeAction; then + defaultFacadeAction "$1" "$@" + else + Log::displayError "invalid action requested: ${action}" + exit 1 + fi + ;; + esac + exit 0 } # if file is sourced avoid calling main function diff --git a/bin/installRequirements b/bin/installRequirements index de442b81..16702b3b 100755 --- a/bin/installRequirements +++ b/bin/installRequirements @@ -596,6 +596,7 @@ Github::upgradeRelease() { } FILTER_LAST_VERSION_CALLBACK=${FILTER_LAST_VERSION_CALLBACK:-extractVersion} \ SOFT_VERSION_CALLBACK="${softVersionCallback}" \ + INSTALL_CALLBACK="${installCallback}" \ Web::upgradeRelease \ "${targetFile}" \ "${releasesUrl}" \ @@ -1172,12 +1173,27 @@ Version::parse() { Web::getReleases() { local releaseListUrl="$1" # Get latest release from GitHub api - Retry::parameterized "${RETRY_MAX_RETRY:-5}" "${RETRY_DELAY_BETWEEN_RETRIES:-15}" "Retrieving release versions list ..." curl \ - -L \ - --connect-timeout "${CURL_CONNECT_TIMEOUT:-5}" \ - --fail \ - --silent \ - "${releaseListUrl}" + if command -v gh &>/dev/null && [[ -n "${GH_TOKEN}" ]]; then + Log::displayDebug "Using gh to retrieve release versions list" + Retry::parameterized "${RETRY_MAX_RETRY:-5}" \ + "${RETRY_DELAY_BETWEEN_RETRIES:-15}" \ + "Retrieving release versions list ..." \ + gh api "${releaseListUrl#https://github.com}" + else + if command -v gh &>/dev/null && [[ "${GH_WARNING_DISPLAYED:-0}" = "0" ]]; then + Log::displayWarning "GH_TOKEN is not set, cannot use gh, using curl to retrieve release versions list" + GH_WARNING_DISPLAYED=1 + fi + Retry::parameterized "${RETRY_MAX_RETRY:-5}" \ + "${RETRY_DELAY_BETWEEN_RETRIES:-15}" \ + "Retrieving release versions list ..." \ + curl \ + -L \ + --connect-timeout "${CURL_CONNECT_TIMEOUT:-5}" \ + --fail \ + --silent \ + "${releaseListUrl}" + fi } @@ -1195,6 +1211,7 @@ Web::getReleases() { # @env PARSE_VERSION_CALLBACK a callback to parse the version of the existing command # @env INSTALL_CALLBACK a callback to install the software downloaded # @env CURL_CONNECT_TIMEOUT number of seconds before giving up host connection +# @env VERSION_PLACEHOLDER a placeholder to replace in downloadReleaseUrl (default: @latestVersion@) Web::upgradeRelease() { local targetFile="$1" local releasesUrl="$2" @@ -1205,25 +1222,28 @@ Web::upgradeRelease() { local filterLastVersionCallback="${FILTER_LAST_VERSION_CALLBACK:-Version::parse}" local softVersionCallback="${SOFT_VERSION_CALLBACK:-Version::getCommandVersionFromPlainText}" local installCallback="${INSTALL_CALLBACK:-}" - local latestVersion - latestVersion="$(Web::getReleases "${releasesUrl}" | ${filterLastVersionCallback})" || { - Log::displayError "latest version not found on ${releasesUrl}" - return 1 - } - Log::displayInfo "Latest version found is ${latestVersion}" local currentVersion="not existing" if [[ -f "${targetFile}" ]]; then currentVersion="$(${softVersionCallback} "${targetFile}" "${softVersionArg}" 2>&1 || true)" fi if [[ -z "${exactVersion}" ]]; then + local latestVersion + latestVersion="$(Web::getReleases "${releasesUrl}" | ${filterLastVersionCallback})" || { + Log::displayError "latest version not found on ${releasesUrl}" + return 1 + } + Log::displayInfo "Latest version found is ${latestVersion}" + exactVersion="${latestVersion}" fi - local url="${downloadReleaseUrl//@latestVersion@/${exactVersion}}" + local url="${downloadReleaseUrl//${VERSION_PLACEHOLDER:-@latestVersion@}/${exactVersion}}" if [[ -n "${exactVersion}" ]] && ! Github::isReleaseVersionExist "${url}"; then Log::displayError "${targetFile} version ${exactVersion} doesn't exist on github" return 2 fi + Log::displayDebug "currentVersion: '${currentVersion}'" + Log::displayDebug "exactVersion: '${exactVersion}'" if [[ "${currentVersion}" = "${exactVersion}" ]]; then Log::displayInfo "${targetFile} version ${exactVersion} already installed" else diff --git a/bin/megalinter b/bin/megalinter index 8b984cd4..5c18df67 100755 --- a/bin/megalinter +++ b/bin/megalinter @@ -382,17 +382,31 @@ Github::getLatestRelease() { resultRef="" local resultFile resultFile="$(mktemp -p "${TMPDIR:-/tmp}" -t githubLatestRelease.XXXX)" - # Get latest release from GitHub api - if Retry::default curl \ - -L \ - --connect-timeout "${CURL_CONNECT_TIMEOUT:-5}" \ - -o "${resultFile}" \ - --fail \ - --silent \ - "https://api.github.com/repos/${repo}/releases/latest"; then - # shellcheck disable=SC2034 - resultRef="$(Version::githubApiExtractVersion <"${resultFile}")" - return 0 + local query="repos/${repo}/releases/latest" + + if command -v gh &>/dev/null && [[ -n "${GH_TOKEN}" ]]; then + Log::displayDebug "Using gh to retrieve release versions list" + Retry::parameterized "${RETRY_MAX_RETRY:-5}" \ + "${RETRY_DELAY_BETWEEN_RETRIES:-15}" \ + "Retrieving release versions list ..." \ + gh api "${query}" >"${resultFile}" + else + if command -v gh &>/dev/null && [[ "${GH_WARNING_DISPLAYED:-0}" = "0" ]]; then + Log::displayWarning "GH_TOKEN is not set, cannot use gh, using curl to retrieve release versions list" + GH_WARNING_DISPLAYED=1 + fi + # Get latest release from GitHub api + if Retry::default curl \ + -L \ + --connect-timeout "${CURL_CONNECT_TIMEOUT:-5}" \ + -o "${resultFile}" \ + --fail \ + --silent \ + "https://api.github.com/${query}"; then + # shellcheck disable=SC2034 + resultRef="$(Version::githubApiExtractVersion <"${resultFile}")" + return 0 + fi fi # display curl result in case of failure cat >&2 "${resultFile}" diff --git a/doc/images/activityDiagram.png b/doc/images/activityDiagram.png new file mode 100644 index 00000000..3625aace Binary files /dev/null and b/doc/images/activityDiagram.png differ diff --git a/src/Env/activityDiagram.png b/src/Env/activityDiagram.png index 5413a208..3625aace 100644 Binary files a/src/Env/activityDiagram.png and b/src/Env/activityDiagram.png differ diff --git a/src/Filters/firstField.bats b/src/Filters/firstField.bats index b2da37af..9c4ba0bf 100755 --- a/src/Filters/firstField.bats +++ b/src/Filters/firstField.bats @@ -31,7 +31,7 @@ function Filters::firstField::bash { #@test } function Filters::firstField::bigFile { #@test - tail -1209 "${BATS_TEST_DIRNAME}/testsData/binary" | { + tail -1170 "${BATS_TEST_DIRNAME}/testsData/binary" | { run Filters::firstField assert_success assert_output 'Github::upgradeRelease' diff --git a/src/Filters/testsData/binary b/src/Filters/testsData/binary index 63db94e7..9392aa23 100755 --- a/src/Filters/testsData/binary +++ b/src/Filters/testsData/binary @@ -6,8 +6,6 @@ ############################################################################### # shellcheck disable=SC2288,SC2034 - - # ensure that no user aliases could interfere with # commands used in this script unalias -a || true @@ -94,7 +92,6 @@ cleanOnExit() { } trap cleanOnExit EXIT HUP QUIT ABRT TERM - SCRIPT_NAME=${0##*/} REAL_SCRIPT_FILE="$(readlink -e "$(realpath "${BASH_SOURCE[0]}")")" if [[ -n "${EMBED_CURRENT_DIR}" ]]; then @@ -138,7 +135,6 @@ export __VERBOSE_LEVEL_DEBUG=2 # @description verbose level info export __VERBOSE_LEVEL_TRACE=3 - # @description concatenate each element of an array with a separator # but wrapping text when line length is more than provided argument # The algorithm will try not to cut the array element if it can. @@ -267,7 +263,6 @@ Array::wrap2() { ) | sed -E -e 's/[[:blank:]]+$//' } - # @description check if command specified exists or return 1 # with error and message if not # @@ -290,7 +285,6 @@ Assert::commandExists() { return 0 } - # @description check if tty (interactive mode) is active # @noargs # @exitcode 1 if tty not active @@ -306,7 +300,6 @@ Assert::tty() { tty -s } - # @description get file content if file not expired # @arg $1 file:String the file to get content from # @arg $2 maxDuration:int number of seconds after which the file is considered expired @@ -326,7 +319,6 @@ Cache::getFileContentIfNotExpired() { cat "${file}" } - # @description convert base64 encoded back to target file # if target file is executable prepend dir of target # file to PATH to make binary available everywhere @@ -356,7 +348,6 @@ Compiler::Embed::extractFileFromBase64() { fi } - # @description prepend directories to the PATH environment variable # @arg $@ args:String[] list of directories to prepend # @set PATH update PATH with the directories prepended @@ -369,7 +360,6 @@ Env::pathPrepend() { done } - # @description ensure env files are loaded # @arg $@ list of default files to load at the end # @exitcode 1 if one of env files fails to load @@ -405,7 +395,6 @@ Env::requireLoad() { done } - # @description get number of seconds since last modification of the file # @arg $1 file:String file path # @exitcode 1 if file does not exist @@ -421,7 +410,6 @@ File::elapsedTimeSinceLastModification() { echo -n "${diff}" } - # @description replace token by input(stdin) in given targetFile # @warning special ansi codes will be removed from stdin # @arg $1 token:String the token to replace by stdin @@ -447,7 +435,6 @@ File::replaceTokenByInput() { ) } - # @description remove ansi codes from input or files given as argument # @arg $@ files:String[] the files to filter # @exitcode * if one of the filter command fails @@ -461,7 +448,6 @@ Filters::removeAnsiCodes() { # cspell:enable } - # @description create a temp file using default TMPDIR variable # initialized in _includes/_commonHeader.sh # @env TMPDIR String (default value /tmp) @@ -470,7 +456,6 @@ Framework::createTempFile() { mktemp -p "${TMPDIR:-/tmp}" -t "${1:-}.XXXXXXXXXXXX" } - # @description clone the repository if not done yet, else pull it if no change in it # @arg $1 dir:String directory in which repository is installed or will be cloned # @arg $2 repo:String repository url @@ -520,7 +505,6 @@ Git::cloneOrPullIfNoChanges() { fi } - # @description pull git directory only if no change has been detected # @arg $1 dir:String the git directory to pull # @exitcode 0 on successful pulling @@ -561,7 +545,6 @@ Git::pullIfNoChanges() { ) } - # @description ensure command git is available # @exitcode 1 if git command not available # @stderr diagnostics information is displayed @@ -571,7 +554,6 @@ Git::requireGitCommand() { Assert::commandExists git } - # @description intermediate callback that is used by Github::upgradeRelease # or Github::installRelease # if installCallback is not set, it allows to: @@ -610,7 +592,6 @@ Github::defaultInstall() { fi } - # @description github repository eg: kubernetes-sigs/kind # @arg $1 githubUrl:String eg: https://github.com/kubernetes-sigs/kind/releases/download/@latestVersion@/kind-linux-amd64 # @exitcode 1 if no matching repo found in provided url, 0 otherwise @@ -625,7 +606,6 @@ Github::extractRepoFromGithubUrl() { echo "${result}" } - # @description check if specified release software version exists in github # @arg $1 releaseUrl:String eg: https://github.com/kubernetes-sigs/kind/releases/download/v1.0.0/kind-linux-amd64 # @exitcode 1 on failure @@ -644,7 +624,6 @@ Github::isReleaseVersionExist() { "${releaseUrl}" } - # @description upgrade given binary to latest github release using retry # # downloadReleaseUrl argument : the placeholder @latestVersion@ will be replaced by the latest release version @@ -686,7 +665,6 @@ Github::upgradeRelease() { "${EXACT_VERSION:-}" } - # @description ensure command jq is available # @exitcode 1 if jq command not available # @stderr diagnostics information is displayed @@ -698,7 +676,6 @@ Linux::requireJqCommand() { fi } - # @description ensure command tar is available # @exitcode 1 if tar command not available # @stderr diagnostics information is displayed @@ -706,7 +683,6 @@ Linux::requireTarCommand() { Assert::commandExists tar } - declare -g FIRST_LOG_DATE LOG_LAST_LOG_DATE LOG_LAST_LOG_DATE_INIT LOG_LAST_DURATION_STR FIRST_LOG_DATE="${EPOCHREALTIME/[^0-9]/}" LOG_LAST_LOG_DATE="${FIRST_LOG_DATE}" @@ -745,7 +721,6 @@ Log::computeDuration() { fi } - # @description Display message using debug color (gray) # @arg $1 message:String the message to display # @env DISPLAY_DURATION int (default 0) if 1 display elapsed time information between 2 info logs @@ -758,7 +733,6 @@ Log::displayDebug() { Log::logDebug "$1" } - # @description Display message using error color (red) # @arg $1 message:String the message to display # @env DISPLAY_DURATION int (default 0) if 1 display elapsed time information between 2 info logs @@ -771,7 +745,6 @@ Log::displayError() { Log::logError "$1" } - # @description Display message using info color (bg light blue/fg white) # @arg $1 message:String the message to display # @env DISPLAY_DURATION int (default 0) if 1 display elapsed time information between 2 info logs @@ -785,7 +758,6 @@ Log::displayInfo() { Log::logInfo "$1" "${type}" } - # @description Display message using skip color (yellow) # @arg $1 message:String the message to display # @env DISPLAY_DURATION int (default 0) if 1 display elapsed time information between 2 info logs @@ -798,7 +770,6 @@ Log::displaySkipped() { Log::logSkipped "$1" } - # @description Display message using success color (bg green/fg white) # @arg $1 message:String the message to display # @env DISPLAY_DURATION int (default 0) if 1 display elapsed time information between 2 info logs @@ -811,7 +782,6 @@ Log::displaySuccess() { Log::logSuccess "$1" } - # @description Display message using warning color (yellow) # @arg $1 message:String the message to display # @env DISPLAY_DURATION int (default 0) if 1 display elapsed time information between 2 info logs @@ -824,7 +794,6 @@ Log::displayWarning() { Log::logWarning "$1" } - # @description Display message using error color (red) and exit immediately with error status 1 # @arg $1 message:String the message to display # @env DISPLAY_DURATION int (default 0) if 1 display elapsed time information between 2 info logs @@ -836,7 +805,6 @@ Log::fatal() { exit 1 } - # @description log message to file # @arg $1 message:String the message to display Log::logDebug() { @@ -845,7 +813,6 @@ Log::logDebug() { fi } - # @description log message to file # @arg $1 message:String the message to display Log::logError() { @@ -854,14 +821,12 @@ Log::logError() { fi } - # @description log message to file # @arg $1 message:String the message to display Log::logFatal() { Log::logMessage "${2:-FATAL}" "$1" } - # @description log message to file # @arg $1 message:String the message to display Log::logInfo() { @@ -870,7 +835,6 @@ Log::logInfo() { fi } - # @description Internal: common log message # @example text # [date]|[levelMsg]|message @@ -907,7 +871,6 @@ Log::logMessage() { fi } - # @description log message to file # @arg $1 message:String the message to display Log::logSkipped() { @@ -916,7 +879,6 @@ Log::logSkipped() { fi } - # @description log message to file # @arg $1 message:String the message to display Log::logSuccess() { @@ -925,7 +887,6 @@ Log::logSuccess() { fi } - # @description log message to file # @arg $1 message:String the message to display Log::logWarning() { @@ -934,7 +895,6 @@ Log::logWarning() { fi } - # @description activate or not Log::display* and Log::log* functions # based on BASH_FRAMEWORK_DISPLAY_LEVEL and BASH_FRAMEWORK_LOG_LEVEL # environment variables loaded by Env::requireLoad @@ -950,7 +910,6 @@ Log::logWarning() { Log::requireLoad() { REQUIRE_FUNCTION_LOG_REQUIRE_LOAD_LOADED=1 - if [[ "${REQUIRE_FUNCTION_ENV_REQUIRE_LOAD_LOADED:-0}" != 1 ]]; then echo >&2 "Requirement Env::requireLoad has not been loaded" exit 1 @@ -992,7 +951,6 @@ Log::requireLoad() { fi } - # @description To be called before logging in the log file # @arg $1 file:string log file name # @arg $2 maxLogFilesCount:int maximum number of log files @@ -1015,7 +973,6 @@ Log::rotate() { fi } - # @description Retry a command 5 times with a delay of 15 seconds between each attempt # @arg $@ command:String[] the command to run # @exitcode 0 on success @@ -1026,7 +983,6 @@ Retry::default() { Retry::parameterized "${RETRY_MAX_RETRY:-5}" "${RETRY_DELAY_BETWEEN_RETRIES:-15}" "" "$@" } - # @description Retry a command several times depending on parameters # @arg $1 maxRetries:int $1 max retries # @arg $2 delay:int between attempt @@ -1064,7 +1020,6 @@ Retry::parameterized() { return 0 } - # @description add reference to index file (using docsify embed feature) # @arg $1 indexFile:String # @arg $2 mdRelativeFile:String @@ -1080,7 +1035,6 @@ ShellDoc::appendDocToIndex() { ) >>"${indexFile}" } - # @description fix markdown TOC generated by Markdown all in one vscode extension # to make TOC compatible with docsify # @arg $1 file:String file to fix @@ -1089,19 +1043,18 @@ ShellDoc::appendDocToIndex() { ShellDoc::fixMarkdownToc() { local file="$1" -Linux::requireTarCommand -Compiler::Embed::extractFileFromBase64 \ - "${PERSISTENT_TMPDIR:-/tmp}/647e7865a1d35cf1435bb0aa74a5cdbe/fixMarkdownTocScript" \ - "ewogIGxpbmU9JDAKICBpZiAobWF0Y2gobGluZSwgL14oXHMqLSBcWyhbMC05XStcLikrIFteXV0rXF1cKCMpKFteKV0rKVwpLywgYXJyKSkgewogICAgcHJpbnQgYXJyWzFdICJfIiByZXdyaXRlKGFyclszXSkgIikiCiAgfSBlbHNlIHsKICAgIHByaW50IGxpbmUKICB9Cn0KZnVuY3Rpb24gcmV3cml0ZShzdHIpCnsKICAgIGdzdWIoLy0oLSkrLywgIi0iLCBzdHIpCiAgICByZXR1cm4gc3RyCn0K" \ - "644" + Linux::requireTarCommand + Compiler::Embed::extractFileFromBase64 \ + "${PERSISTENT_TMPDIR:-/tmp}/647e7865a1d35cf1435bb0aa74a5cdbe/fixMarkdownTocScript" \ + "ewogIGxpbmU9JDAKICBpZiAobWF0Y2gobGluZSwgL14oXHMqLSBcWyhbMC05XStcLikrIFteXV0rXF1cKCMpKFteKV0rKVwpLywgYXJyKSkgewogICAgcHJpbnQgYXJyWzFdICJfIiByZXdyaXRlKGFyclszXSkgIikiCiAgfSBlbHNlIHsKICAgIHByaW50IGxpbmUKICB9Cn0KZnVuY3Rpb24gcmV3cml0ZShzdHIpCnsKICAgIGdzdWIoLy0oLSkrLywgIi0iLCBzdHIpCiAgICByZXR1cm4gc3RyCn0K" \ + "644" -declare -gx embed_file_fixMarkdownTocScript="${PERSISTENT_TMPDIR:-/tmp}/647e7865a1d35cf1435bb0aa74a5cdbe/fixMarkdownTocScript" + declare -gx embed_file_fixMarkdownTocScript="${PERSISTENT_TMPDIR:-/tmp}/647e7865a1d35cf1435bb0aa74a5cdbe/fixMarkdownTocScript" # shellcheck disable=SC2154 awk -i inplace -f "${embed_file_fixMarkdownTocScript}" "${file}" } - # @description generates markdown file from template by # replacing @@@command_help@@@ by the help of the command # eg: @@@test_help@@@ will be replaced by the output @@ -1153,7 +1106,6 @@ ShellDoc::generateMdFileFromTemplate() { Log::displayInfo "${nbTokensGenerated} commands' help replaced in $(echo "scale=3; ${endTime} - ${startTime}" | bc)seconds" } - # @description extract shDoc from file # # @arg $1 file:String @@ -1170,7 +1122,6 @@ ShellDoc::generateShellDoc() { ) || true } - # @description generate shell doc file from given directory # # @arg $1 dir:String @@ -1247,7 +1198,6 @@ ShellDoc::generateShellDocDir() { ) } - # @description generate doc + index # @arg $1 fromDir:String # @arg $2 fromDirRelative:String @@ -1301,7 +1251,6 @@ ShellDoc::generateShellDocsFromDir() { done < <(cd "${fromDir}" && find . -type d -name '[^.]*' | "${grepExclude[@]}" | LC_ALL=C sort) } - BASH_FRAMEWORK_SHDOC_INSTALLED_PATH="vendor/.shDocInstalled" BASH_FRAMEWORK_SHDOC_CHECK_TIMEOUT=86400 # 1 day @@ -1335,7 +1284,6 @@ ShellDoc::installRequirementsIfNeeded() { fi } - # @description install hadolint if necessary # @arg $1 targetFile:String # @feature Github::upgradeRelease @@ -1346,7 +1294,6 @@ Softwares::installHadolint() { "https://github.com/hadolint/hadolint/releases/download/v@latestVersion@/hadolint-Linux-x86_64" } - # @description install hadolint if necessary # @arg $1 targetFile:String # @feature Github::upgradeRelease @@ -1372,7 +1319,6 @@ Softwares::installShellcheck() { "https://github.com/koalaman/shellcheck/releases/download/v@latestVersion@/shellcheck-v@latestVersion@.linux.x86_64.tar.xz" } - # @description draw a line with the character passed in parameter repeated depending on terminal width # @arg $1 character:String character to use as separator (default value #) UI::drawLine() { @@ -1388,7 +1334,6 @@ UI::drawLine() { echo } - # @description load color theme # @noargs # @env BASH_FRAMEWORK_THEME String theme to use @@ -1402,7 +1347,6 @@ UI::requireTheme() { fi } - # @description load colors theme constants # @warning if tty not opened, noColor theme will be chosen # @arg $1 theme:String the theme to use (default, noColor) @@ -1483,7 +1427,6 @@ UI::theme() { fi } - # @description extract software version number # @arg $1 command:String the command that will be called with --version parameter # @arg $2 argVersion:String allows to override default --version parameter @@ -1494,7 +1437,6 @@ Version::getCommandVersionFromPlainText() { Version::parse # keep only version numbers } - # @description extract version number from github api # @noargs # @stdin json result of github API @@ -1510,7 +1452,6 @@ Version::githubApiExtractVersion() { jq -r ".tag_name" } - # @description filter to keep only version number from a string # @arg $@ files:String[] the files to filter # @exitcode * if one of the filter command fails @@ -1526,7 +1467,6 @@ Version::parse() { "$@" } - # @description Retrieve the latest version number of a web release # @arg $1 releaseListUrl:String the url from which version list can be retrieved # @stdout log messages about retry @@ -1542,7 +1482,6 @@ Web::getReleases() { "${releaseListUrl}" } - # @description upgrade given binary to latest release using retry # # releasesUrl argument : the placeholder @latestVersion@ will be replaced by the latest release version @@ -1608,7 +1547,6 @@ Web::upgradeRelease() { } # FUNCTIONS - declare -a BASH_FRAMEWORK_ARGV_FILTERED=() beforeParseCallback() { @@ -1854,8 +1792,6 @@ commandOptionParseFinished() { fi } - - # shellcheck disable=SC2034 declare optionContinuousIntegrationMode=0 @@ -1864,8 +1800,6 @@ updateOptionContinuousIntegrationMode() { BASH_FRAMEWORK_ARGV_FILTERED+=("$1") } - - # shellcheck disable=SC2034 declare copyrightBeginYear="2022" # shellcheck disable=SC2034 @@ -1878,7 +1812,6 @@ optionHelpCallback() { exit 0 } - # ------------------------------------------ # Command docCommand # ------------------------------------------ @@ -1948,7 +1881,6 @@ docCommandParse() { local -i options_parse_optionParsedCountOptionQuiet ((options_parse_optionParsedCountOptionQuiet = 0)) || true - # shellcheck disable=SC2034 local -i options_parse_parsedArgIndex=0 while (($# > 0)); do @@ -1962,7 +1894,7 @@ docCommandParse() { # shellcheck disable=SC2034 optionContinuousIntegrationMode="1" - if ((options_parse_optionParsedCountOptionContinuousIntegrationMode >= 1 )); then + if ((options_parse_optionParsedCountOptionContinuousIntegrationMode >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -1978,7 +1910,7 @@ docCommandParse() { # shellcheck disable=SC2034 optionHelp="1" - if ((options_parse_optionParsedCountOptionHelp >= 1 )); then + if ((options_parse_optionParsedCountOptionHelp >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -1994,7 +1926,7 @@ docCommandParse() { # shellcheck disable=SC2034 optionConfig="1" - if ((options_parse_optionParsedCountOptionConfig >= 1 )); then + if ((options_parse_optionParsedCountOptionConfig >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -2011,7 +1943,7 @@ docCommandParse() { return 1 fi - if ((options_parse_optionParsedCountOptionBashFrameworkConfig >= 1 )); then + if ((options_parse_optionParsedCountOptionBashFrameworkConfig >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -2029,7 +1961,7 @@ docCommandParse() { # shellcheck disable=SC2034 optionInfoVerbose="1" - if ((options_parse_optionParsedCountOptionInfoVerbose >= 1 )); then + if ((options_parse_optionParsedCountOptionInfoVerbose >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -2047,7 +1979,7 @@ docCommandParse() { # shellcheck disable=SC2034 optionDebugVerbose="1" - if ((options_parse_optionParsedCountOptionDebugVerbose >= 1 )); then + if ((options_parse_optionParsedCountOptionDebugVerbose >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -2065,7 +1997,7 @@ docCommandParse() { # shellcheck disable=SC2034 optionTraceVerbose="1" - if ((options_parse_optionParsedCountOptionTraceVerbose >= 1 )); then + if ((options_parse_optionParsedCountOptionTraceVerbose >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -2091,7 +2023,7 @@ docCommandParse() { return 1 fi - if ((options_parse_optionParsedCountOptionLogLevel >= 1 )); then + if ((options_parse_optionParsedCountOptionLogLevel >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -2114,7 +2046,7 @@ docCommandParse() { return 1 fi - if ((options_parse_optionParsedCountOptionLogFile >= 1 )); then + if ((options_parse_optionParsedCountOptionLogFile >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -2142,7 +2074,7 @@ docCommandParse() { return 1 fi - if ((options_parse_optionParsedCountOptionDisplayLevel >= 1 )); then + if ((options_parse_optionParsedCountOptionDisplayLevel >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -2162,7 +2094,7 @@ docCommandParse() { # shellcheck disable=SC2034 optionNoColor="1" - if ((options_parse_optionParsedCountOptionNoColor >= 1 )); then + if ((options_parse_optionParsedCountOptionNoColor >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -2188,7 +2120,7 @@ docCommandParse() { return 1 fi - if ((options_parse_optionParsedCountOptionTheme >= 1 )); then + if ((options_parse_optionParsedCountOptionTheme >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -2208,7 +2140,7 @@ docCommandParse() { # shellcheck disable=SC2034 optionVersion="1" - if ((options_parse_optionParsedCountOptionVersion >= 1 )); then + if ((options_parse_optionParsedCountOptionVersion >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -2224,7 +2156,7 @@ docCommandParse() { # shellcheck disable=SC2034 optionQuiet="1" - if ((options_parse_optionParsedCountOptionQuiet >= 1 )); then + if ((options_parse_optionParsedCountOptionQuiet >= 1)); then Log::displayError "Command ${SCRIPT_NAME} - Option ${options_parse_arg} - Maximum number of option occurrences reached(1)" return 1 fi @@ -2284,75 +2216,56 @@ docCommandHelp() { Array::wrap2 ' ' 76 4 " " "Activate continuous integration mode (tmp folder not shared with host)" "" echo - echo echo -e "${__HELP_TITLE_COLOR}GLOBAL OPTIONS:${__RESET_COLOR}" echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" Array::wrap2 ' ' 76 4 " " "Displays this command help" echo - - echo -e " ${__HELP_OPTION_COLOR}--config${__HELP_NORMAL} {single}" Array::wrap2 ' ' 76 4 " " "Displays configuration" echo - - echo -e " ${__HELP_OPTION_COLOR}--bash-framework-config bash-framework-config${__HELP_NORMAL} {single}" Array::wrap2 ' ' 76 4 " " "Use alternate bash framework configuration." echo - - echo -e " ${__HELP_OPTION_COLOR}--verbose${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-v${__HELP_NORMAL} {single}" Array::wrap2 ' ' 76 4 " " "Info level verbose mode (alias of --display-level INFO)" echo - - echo -e " ${__HELP_OPTION_COLOR}-vv${__HELP_NORMAL} {single}" Array::wrap2 ' ' 76 4 " " "Debug level verbose mode (alias of --display-level DEBUG)" echo - - echo -e " ${__HELP_OPTION_COLOR}-vvv${__HELP_NORMAL} {single}" Array::wrap2 ' ' 76 4 " " "Trace level verbose mode (alias of --display-level TRACE)" echo - - echo -e " ${__HELP_OPTION_COLOR}--log-level log-level${__HELP_NORMAL} {single}" Array::wrap2 ' ' 76 4 " " "Set log level" echo - Array::wrap2 ' ' 76 6 " Possible values: " "OFF, " "ERR, " "ERROR, " "WARN, " "WARNING, " "INFO, " "DEBUG, " "TRACE" + Array::wrap2 ' ' 76 6 " Possible values: " "OFF, " "ERR, " "ERROR, " "WARN, " "WARNING, " "INFO, " "DEBUG, " "TRACE" echo - echo -e " ${__HELP_OPTION_COLOR}--log-file log-file${__HELP_NORMAL} {single}" Array::wrap2 ' ' 76 4 " " "Set log file" echo - - echo -e " ${__HELP_OPTION_COLOR}--display-level display-level${__HELP_NORMAL} {single}" Array::wrap2 ' ' 76 4 " " "Set display level" echo - Array::wrap2 ' ' 76 6 " Possible values: " "OFF, " "ERR, " "ERROR, " "WARN, " "WARNING, " "INFO, " "DEBUG, " "TRACE" + Array::wrap2 ' ' 76 6 " Possible values: " "OFF, " "ERR, " "ERROR, " "WARN, " "WARNING, " "INFO, " "DEBUG, " "TRACE" echo - echo -e " ${__HELP_OPTION_COLOR}--no-color${__HELP_NORMAL} {single}" Array::wrap2 ' ' 76 4 " " "Produce monochrome output. alias of --theme noColor." echo - - echo -e " ${__HELP_OPTION_COLOR}--theme theme${__HELP_NORMAL} {single}" Array::wrap2 ' ' 76 4 " " "Choose color theme - default-force means colors will be produced even if command is piped." echo - Array::wrap2 ' ' 76 6 " Possible values: " "default, " "default-force, " "noColor" + Array::wrap2 ' ' 76 6 " Possible values: " "default, " "default-force, " "noColor" echo Array::wrap2 ' ' 76 6 " Default value: " "default" @@ -2362,13 +2275,10 @@ docCommandHelp() { Array::wrap2 ' ' 76 4 " " "Print version information and quit." echo - - echo -e " ${__HELP_OPTION_COLOR}--quiet${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-q${__HELP_NORMAL} {single}" Array::wrap2 ' ' 76 4 " " "Quiet mode, doesn't display any output." echo - # ------------------------------------------ # longDescription section # ------------------------------------------ @@ -2376,7 +2286,7 @@ docCommandHelp() { echo echo -e "${__HELP_TITLE_COLOR}DESCRIPTION:${__RESET_COLOR}" declare -a docCommandLongDescription=( - "INTERNAL TOOL" + "INTERNAL TOOL" ) Array::wrap2 ' ' 76 0 "${docCommandLongDescription[@]}" echo @@ -2410,132 +2320,131 @@ docCommandHelp() { Array::wrap2 ' ' 76 0 "$(copyrightCallback)" } - beforeParseCallback docCommandParse "$@" MAIN_FUNCTION_NAME="main" main() { -COMMAND_BIN_DIR="${FRAMEWORK_ROOT_DIR}/bin" + COMMAND_BIN_DIR="${FRAMEWORK_ROOT_DIR}/bin" -runContainer() { - local image="scrasnups/build:bash-tools-ubuntu-5.3" - local -a dockerRunCmd=( - "/bash/bin/doc" - "${BASH_FRAMEWORK_ARGV_FILTERED[@]}" - ) + runContainer() { + local image="scrasnups/build:bash-tools-ubuntu-5.3" + local -a dockerRunCmd=( + "/bash/bin/doc" + "${BASH_FRAMEWORK_ARGV_FILTERED[@]}" + ) - if ! docker inspect --type=image "${image}" &>/dev/null; then - docker pull "${image}" - fi - # run docker image - local -a localDockerRunArgs=( - --rm - -e KEEP_TEMP_FILES="${KEEP_TEMP_FILES:-0}" - -e BATS_FIX_TEST="${BATS_FIX_TEST:-0}" - -w /bash - -v "${FRAMEWORK_ROOT_DIR}:/bash" - --entrypoint /usr/local/bin/bash - ) - # shellcheck disable=SC2154 - if [[ "${optionContinuousIntegrationMode}" = "0" ]]; then - localDockerRunArgs+=( - -e USER_ID="${USER_ID:-1000}" - -e GROUP_ID="${GROUP_ID:-1000}" - --user "www-data:www-data" - -v "/tmp:/tmp" + if ! docker inspect --type=image "${image}" &>/dev/null; then + docker pull "${image}" + fi + # run docker image + local -a localDockerRunArgs=( + --rm + -e KEEP_TEMP_FILES="${KEEP_TEMP_FILES:-0}" + -e BATS_FIX_TEST="${BATS_FIX_TEST:-0}" + -w /bash + -v "${FRAMEWORK_ROOT_DIR}:/bash" + --entrypoint /usr/local/bin/bash ) - fi + # shellcheck disable=SC2154 + if [[ "${optionContinuousIntegrationMode}" = "0" ]]; then + localDockerRunArgs+=( + -e USER_ID="${USER_ID:-1000}" + -e GROUP_ID="${GROUP_ID:-1000}" + --user "www-data:www-data" + -v "/tmp:/tmp" + ) + fi - # shellcheck disable=SC2154 - if [[ "${optionTraceVerbose}" = "1" ]]; then - set -x - fi - docker run \ - "${localDockerRunArgs[@]}" \ - "${image}" \ - "${dockerRunCmd[@]}" - set +x -} - -generateDoc() { - PAGES_DIR="${FRAMEWORK_ROOT_DIR}/pages" - export FRAMEWORK_ROOT_DIR - - #----------------------------- - # doc generation - #----------------------------- - - Log::displayInfo 'generate Commands.md' - ((TOKEN_NOT_FOUND_COUNT = 0)) || true - ShellDoc::generateMdFileFromTemplate \ - "${FRAMEWORK_ROOT_DIR}/doc/templates/Commands.tmpl.md" \ - "${PAGES_DIR}/Commands.md" \ - "${COMMAND_BIN_DIR}" \ - TOKEN_NOT_FOUND_COUNT \ - '(var|simpleBinary|shdoc|installFacadeExample)$' - - # clean folder before generate - rm -f "${PAGES_DIR}/Index.md" || true - rm -Rf "${PAGES_DIR}/bashDoc" || true - rm -Rf "${PAGES_DIR}/FrameworkIndex.md" || true - - ShellDoc::generateShellDocsFromDir \ - "${FRAMEWORK_SRC_DIR}" \ - "src" \ - "${PAGES_DIR}/bashDoc" \ - "${PAGES_DIR}/FrameworkIndex.md" \ - "<% ${REPOSITORY_URL} %>" \ - '/testsData|/_.*' \ - '(/__all\.sh)$' - cp "${FRAMEWORK_ROOT_DIR}/doc/guides/Docker.md" "${PAGES_DIR}/bashDoc/DockerUsage.md" - - cp "${FRAMEWORK_ROOT_DIR}/README.md" "${PAGES_DIR}" - sed -i -E \ - -e '//,//d' \ - -e 's#https://fchastanet.github.io/bash-tools-framework/#/#' \ - -e 's#^> \*\*_TIP:_\*\* (.*)$#> [!TIP|label:\1]#' \ - "${PAGES_DIR}/README.md" - - cp -R "${FRAMEWORK_ROOT_DIR}/doc" "${PAGES_DIR}" - rm -Rf "${PAGES_DIR}/doc/guides/templates" - - Log::displayInfo 'generate FrameworkFullDoc.md' - cp "${FRAMEWORK_ROOT_DIR}/doc/templates/FrameworkFullDoc.tmpl.md" "${PAGES_DIR}/FrameworkFullDoc.md" - ( - echo - find "${PAGES_DIR}/bashDoc" -type f -name '*.md' -print0 | LC_ALL=C sort -z | xargs -0 cat - ) >>"${PAGES_DIR}/FrameworkFullDoc.md" + # shellcheck disable=SC2154 + if [[ "${optionTraceVerbose}" = "1" ]]; then + set -x + fi + docker run \ + "${localDockerRunArgs[@]}" \ + "${image}" \ + "${dockerRunCmd[@]}" + set +x + } + + generateDoc() { + PAGES_DIR="${FRAMEWORK_ROOT_DIR}/pages" + export FRAMEWORK_ROOT_DIR + + #----------------------------- + # doc generation + #----------------------------- + + Log::displayInfo 'generate Commands.md' + ((TOKEN_NOT_FOUND_COUNT = 0)) || true + ShellDoc::generateMdFileFromTemplate \ + "${FRAMEWORK_ROOT_DIR}/doc/templates/Commands.tmpl.md" \ + "${PAGES_DIR}/Commands.md" \ + "${COMMAND_BIN_DIR}" \ + TOKEN_NOT_FOUND_COUNT \ + '(var|simpleBinary|shdoc|installFacadeExample)$' + + # clean folder before generate + rm -f "${PAGES_DIR}/Index.md" || true + rm -Rf "${PAGES_DIR}/bashDoc" || true + rm -Rf "${PAGES_DIR}/FrameworkIndex.md" || true + + ShellDoc::generateShellDocsFromDir \ + "${FRAMEWORK_SRC_DIR}" \ + "src" \ + "${PAGES_DIR}/bashDoc" \ + "${PAGES_DIR}/FrameworkIndex.md" \ + "<% ${REPOSITORY_URL} %>" \ + '/testsData|/_.*' \ + '(/__all\.sh)$' + cp "${FRAMEWORK_ROOT_DIR}/doc/guides/Docker.md" "${PAGES_DIR}/bashDoc/DockerUsage.md" + + cp "${FRAMEWORK_ROOT_DIR}/README.md" "${PAGES_DIR}" + sed -i -E \ + -e '//,//d' \ + -e 's#https://fchastanet.github.io/bash-tools-framework/#/#' \ + -e 's#^> \*\*_TIP:_\*\* (.*)$#> [!TIP|label:\1]#' \ + "${PAGES_DIR}/README.md" + + cp -R "${FRAMEWORK_ROOT_DIR}/doc" "${PAGES_DIR}" + rm -Rf "${PAGES_DIR}/doc/guides/templates" + + Log::displayInfo 'generate FrameworkFullDoc.md' + cp "${FRAMEWORK_ROOT_DIR}/doc/templates/FrameworkFullDoc.tmpl.md" "${PAGES_DIR}/FrameworkFullDoc.md" + ( + echo + find "${PAGES_DIR}/bashDoc" -type f -name '*.md' -print0 | LC_ALL=C sort -z | xargs -0 cat + ) >>"${PAGES_DIR}/FrameworkFullDoc.md" - while read -r path; do - ShellDoc::fixMarkdownToc "${path}" - done < <(find "${PAGES_DIR}" -type f -name '*.md') + while read -r path; do + ShellDoc::fixMarkdownToc "${path}" + done < <(find "${PAGES_DIR}" -type f -name '*.md') - if ((TOKEN_NOT_FOUND_COUNT > 0)); then - exit 1 - fi -} + if ((TOKEN_NOT_FOUND_COUNT > 0)); then + exit 1 + fi + } -installRequirements() { - Git::requireGitCommand -} + installRequirements() { + Git::requireGitCommand + } -installContainerRequirements() { - Git::requireGitCommand - ShellDoc::installRequirementsIfNeeded - Linux::requireJqCommand - Softwares::installHadolint - Softwares::installShellcheck -} + installContainerRequirements() { + Git::requireGitCommand + ShellDoc::installRequirementsIfNeeded + Linux::requireJqCommand + Softwares::installHadolint + Softwares::installShellcheck + } -if [[ "${IN_BASH_DOCKER:-}" = "You're in docker" ]]; then - installRequirements - generateDoc -else - installContainerRequirements - runContainer -fi + if [[ "${IN_BASH_DOCKER:-}" = "You're in docker" ]]; then + installRequirements + generateDoc + else + installContainerRequirements + runContainer + fi } diff --git a/src/Github/getLatestRelease.sh b/src/Github/getLatestRelease.sh index e9cf369c..0363bcbb 100755 --- a/src/Github/getLatestRelease.sh +++ b/src/Github/getLatestRelease.sh @@ -14,17 +14,31 @@ Github::getLatestRelease() { resultRef="" local resultFile resultFile="$(mktemp -p "${TMPDIR:-/tmp}" -t githubLatestRelease.XXXX)" - # Get latest release from GitHub api - if Retry::default curl \ - -L \ - --connect-timeout "${CURL_CONNECT_TIMEOUT:-5}" \ - -o "${resultFile}" \ - --fail \ - --silent \ - "https://api.github.com/repos/${repo}/releases/latest"; then - # shellcheck disable=SC2034 - resultRef="$(Version::githubApiExtractVersion <"${resultFile}")" - return 0 + local query="repos/${repo}/releases/latest" + + if command -v gh &>/dev/null && [[ -n "${GH_TOKEN}" ]]; then + Log::displayDebug "Using gh to retrieve release versions list" + Retry::parameterized "${RETRY_MAX_RETRY:-5}" \ + "${RETRY_DELAY_BETWEEN_RETRIES:-15}" \ + "Retrieving release versions list ..." \ + gh api "${query}" >"${resultFile}" + else + if command -v gh &>/dev/null && [[ "${GH_WARNING_DISPLAYED:-0}" = "0" ]]; then + Log::displayWarning "GH_TOKEN is not set, cannot use gh, using curl to retrieve release versions list" + GH_WARNING_DISPLAYED=1 + fi + # Get latest release from GitHub api + if Retry::default curl \ + -L \ + --connect-timeout "${CURL_CONNECT_TIMEOUT:-5}" \ + -o "${resultFile}" \ + --fail \ + --silent \ + "https://api.github.com/${query}"; then + # shellcheck disable=SC2034 + resultRef="$(Version::githubApiExtractVersion <"${resultFile}")" + return 0 + fi fi # display curl result in case of failure cat >&2 "${resultFile}" diff --git a/src/Github/installRelease.sh b/src/Github/installRelease.sh index fc091f9a..0b96c71c 100755 --- a/src/Github/installRelease.sh +++ b/src/Github/installRelease.sh @@ -11,6 +11,7 @@ # @arg $6 installCallback:Function called to install the file retrieved on github (default copy as is and set execution bit) # @stdout log messages about retry, install, upgrade # @env CURL_CONNECT_TIMEOUT number of seconds before giving up host connection +# @env VERSION_PLACEHOLDER a placeholder to replace in downloadReleaseUrl (default: @latestVersion@) Github::installRelease() { local targetFile="$1" local releaseUrl="$2" @@ -26,7 +27,10 @@ Github::installRelease() { fi if [[ "${currentVersion}" != "${exactVersion}" ]]; then Log::displayInfo "Installing ${targetFile} from version ${currentVersion} to ${exactVersion}" - url="$(echo "${releaseUrl}" | sed -E "s/@latestVersion@/${exactVersion}/g")" + url="$( + echo "${releaseUrl}" | + sed -E "s/${VERSION_PLACEHOLDER:-@latestVersion@}/${exactVersion}/g" + )" Log::displayInfo "Using url ${url}" newSoftware=$(mktemp -p "${TMPDIR:-/tmp}" -t github.newSoftware.XXXX) Retry::default curl \ diff --git a/src/Github/upgradeRelease.sh b/src/Github/upgradeRelease.sh index 8e6ca305..300ad4bc 100755 --- a/src/Github/upgradeRelease.sh +++ b/src/Github/upgradeRelease.sh @@ -33,6 +33,7 @@ Github::upgradeRelease() { } FILTER_LAST_VERSION_CALLBACK=${FILTER_LAST_VERSION_CALLBACK:-extractVersion} \ SOFT_VERSION_CALLBACK="${softVersionCallback}" \ + INSTALL_CALLBACK="${installCallback}" \ Web::upgradeRelease \ "${targetFile}" \ "${releasesUrl}" \ diff --git a/src/Web/getReleases.sh b/src/Web/getReleases.sh index 760a36f0..cae85da7 100755 --- a/src/Web/getReleases.sh +++ b/src/Web/getReleases.sh @@ -7,10 +7,25 @@ Web::getReleases() { local releaseListUrl="$1" # Get latest release from GitHub api - Retry::parameterized "${RETRY_MAX_RETRY:-5}" "${RETRY_DELAY_BETWEEN_RETRIES:-15}" "Retrieving release versions list ..." curl \ - -L \ - --connect-timeout "${CURL_CONNECT_TIMEOUT:-5}" \ - --fail \ - --silent \ - "${releaseListUrl}" + if command -v gh &>/dev/null && [[ -n "${GH_TOKEN}" ]]; then + Log::displayDebug "Using gh to retrieve release versions list" + Retry::parameterized "${RETRY_MAX_RETRY:-5}" \ + "${RETRY_DELAY_BETWEEN_RETRIES:-15}" \ + "Retrieving release versions list ..." \ + gh api "${releaseListUrl#https://github.com}" + else + if command -v gh &>/dev/null && [[ "${GH_WARNING_DISPLAYED:-0}" = "0" ]]; then + Log::displayWarning "GH_TOKEN is not set, cannot use gh, using curl to retrieve release versions list" + GH_WARNING_DISPLAYED=1 + fi + Retry::parameterized "${RETRY_MAX_RETRY:-5}" \ + "${RETRY_DELAY_BETWEEN_RETRIES:-15}" \ + "Retrieving release versions list ..." \ + curl \ + -L \ + --connect-timeout "${CURL_CONNECT_TIMEOUT:-5}" \ + --fail \ + --silent \ + "${releaseListUrl}" + fi } diff --git a/src/Web/upgradeRelease.sh b/src/Web/upgradeRelease.sh index 43fef5a3..80a2f569 100755 --- a/src/Web/upgradeRelease.sh +++ b/src/Web/upgradeRelease.sh @@ -14,6 +14,7 @@ # @env PARSE_VERSION_CALLBACK a callback to parse the version of the existing command # @env INSTALL_CALLBACK a callback to install the software downloaded # @env CURL_CONNECT_TIMEOUT number of seconds before giving up host connection +# @env VERSION_PLACEHOLDER a placeholder to replace in downloadReleaseUrl (default: @latestVersion@) Web::upgradeRelease() { local targetFile="$1" local releasesUrl="$2" @@ -24,25 +25,28 @@ Web::upgradeRelease() { local filterLastVersionCallback="${FILTER_LAST_VERSION_CALLBACK:-Version::parse}" local softVersionCallback="${SOFT_VERSION_CALLBACK:-Version::getCommandVersionFromPlainText}" local installCallback="${INSTALL_CALLBACK:-}" - local latestVersion - latestVersion="$(Web::getReleases "${releasesUrl}" | ${filterLastVersionCallback})" || { - Log::displayError "latest version not found on ${releasesUrl}" - return 1 - } - Log::displayInfo "Latest version found is ${latestVersion}" local currentVersion="not existing" if [[ -f "${targetFile}" ]]; then currentVersion="$(${softVersionCallback} "${targetFile}" "${softVersionArg}" 2>&1 || true)" fi if [[ -z "${exactVersion}" ]]; then + local latestVersion + latestVersion="$(Web::getReleases "${releasesUrl}" | ${filterLastVersionCallback})" || { + Log::displayError "latest version not found on ${releasesUrl}" + return 1 + } + Log::displayInfo "Latest version found is ${latestVersion}" + exactVersion="${latestVersion}" fi - local url="${downloadReleaseUrl//@latestVersion@/${exactVersion}}" + local url="${downloadReleaseUrl//${VERSION_PLACEHOLDER:-@latestVersion@}/${exactVersion}}" if [[ -n "${exactVersion}" ]] && ! Github::isReleaseVersionExist "${url}"; then Log::displayError "${targetFile} version ${exactVersion} doesn't exist on github" return 2 fi + Log::displayDebug "currentVersion: '${currentVersion}'" + Log::displayDebug "exactVersion: '${exactVersion}'" if [[ "${currentVersion}" = "${exactVersion}" ]]; then Log::displayInfo "${targetFile} version ${exactVersion} already installed" else