scripts/github/check.glpi-agent.update

380 lines
13 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/sh
#
# Purpose {{{
# This script will try to get last version of glpi-agent .deb file
# https://github.com/glpi-project/glpi-agent/releases
# 1. Get current version from APT repo (by default).
# 1.b Or use version from manually installed package (with --file option).
# 2. Get latest version from github repository.
# 3. Compare current and new versions.
# 4. Download the .deb file for this new version.
# 5. Create a temp file (to monitor) if an upgrade is available.
# }}}
## How-to use {{{
### 1. Needs releasetags script, in the same directory
### cf. https://git.101010.fr/gardouille-dotfiles/scripts/src/branch/master/github/releasetags
# wget https://git.101010.fr/gardouille-dotfiles/scripts/raw/branch/master/github/releasetags
### 2. Create a cron job, eg:
#00 20 * * * root /opt/repos/gardouille.scripts/github/check.glpi-agent.update
### 2-1 Create a cron job to compare the version available in a Debian repository:
#00 20 * * * root /opt/repos/gardouille.scripts/github/check.glpi-agent.update --repo
### 3. Monitor the temp file: /tmp/.github.glpi-agent.upgrade
# Or enable MAILTO in cronjob and edit the script to print a message.
# Or send a mail.
# …
# }}}
# Flags {{{
## Exit on error
set -o errexit
## Exit on unset var
### Use "${VARNAME-}" to test a var that may not have been set
set -o nounset
## Pipeline command is treated as failed
### Not available in POSIX sh https://github.com/koalaman/shellcheck/wiki/SC3040
#set -o pipefail
## Help with debugging
### Call the script by prefixing it with "TRACE=1 ./script.sh"
if [ "${TRACE-0}" -eq 1 ]; then set -o xtrace; fi
# }}}
# Vars {{{
PROGNAME=$(basename "${0}"); readonly PROGNAME
PROGDIR=$(readlink --canonicalize-missing $(dirname "${0}")); readonly PROGDIR
ARGS="${*}"; readonly ARGS
readonly NBARGS="${#}"
[ -z "${DEBUG-}" ] && DEBUG=1
## Export DEBUG for sub-script
export DEBUG
## Default values for some vars
readonly PACKAGE_NAME_DEFAULT="glpi-agent"
readonly CHECK_MODE_DEFAULT="repository"
## Colors
readonly PURPLE='\033[1;35m'
readonly RED='\033[0;31m'
readonly RESET='\033[0m'
readonly COLOR_DEBUG="${PURPLE}"
# }}}
usage() { # {{{
cat <<- HELP
usage: $PROGNAME [-d|-h|-f|-r]
Try to get last version of ${PACKAGE_NAME_DEFAULT} .deb file.
EXAMPLES:
- Check ${PACKAGE_NAME_DEFAULT} version (from APT repository or manually installed file).
${PROGNAME}
OPTIONS:
-d,--debug
Enable debug messages.
-h,--help
Print this help message.
-f,--file,--p,--package
Use manually installed package.
-r,--repo,--repository
Use ${PACKAGE_NAME_DEFAULT} version from APT repository.
HELP
}
# }}}
debug_message() { # {{{
local_debug_message="${1}"
## Print message if DEBUG is enable (=0)
[ "${DEBUG}" -eq "0" ] && printf '\e[1;35m%-6b\e[m\n' "DEBUG ${PROGNAME}: ${local_debug_message}"
unset local_debug_message
return 0
}
# }}}
error_message() { # {{{
local_error_message="${1}"
local_error_code="${2}"
## Print message
printf '%b\n' "ERROR ${PROGNAME}: ${RED}${local_error_message}${RESET}" >&2
unset local_error_message
exit "${local_error_code:=66}"
}
# }}}
is_var_empty() { # {{{
local_var_empty="${1}"
debug_prefix="${2:-}"
## Return False by default
return_var_empty="1"
debug_message "${debug_prefix}is_var_empty Test var value (${1})."
[ -z "${local_var_empty}" ] && return_var_empty="0"
unset debug_prefix
unset local_var_empty
return "${return_var_empty}"
}
# }}}
define_vars() { # {{{
debug_message "-- define_vars BEGIN"
## If repo_url wasn't defined {{{
is_var_empty "${repo_url-}" "|| " \
&& repo_url="https://github.com/glpi-project/glpi-agent" \
&& debug_message "| define_vars Use value (${RED}${repo_url}${COLOR_DEBUG}) for repo_url variable."
## }}}
## If package_name wasn't defined (argument) {{{
## Use default value
is_var_empty "${package_name-}" "|| " \
&& debug_message "| define_vars Use default value (${RED}${PACKAGE_NAME_DEFAULT}${COLOR_DEBUG}) for package_name variable." \
&& package_name="${PACKAGE_NAME_DEFAULT}"
## }}}
## Get new_version_major from application repository {{{
new_version_major=$("${PROGDIR}"/releasetags "${repo_url}" | grep --invert-match --extended-regexp -- '(dev|rc)' | head --lines=1 | sed 's/v//g')
if is_var_empty "${new_version_major-}" "|| "; then
error_message "define_vars Invalid value for ${package_name} new version (${new_version_major})." 1
else
debug_message "| define_vars Get value (${RED}${new_version_major}${COLOR_DEBUG}) for new_version_major variable."
fi
## }}}
## Get new_version_revision from official installer script {{{
## Because Github release version don't integer revision number…
## Download installer script
installer_script_file="/tmp/glpi-agent-${new_version_major}-linux-installer.pl"
installer_script_url="https://github.com/glpi-project/glpi-agent/releases/download/${new_version_major}/glpi-agent-${new_version_major}-linux-installer.pl"
wget --quiet "${installer_script_url}" --output-document="${installer_script_file}"
## Parse file to find any revision number
new_version_revision=$(grep --text "^my \$DEBREVISION" -- "${installer_script_file}" | cut --delimiter=\" --fields=2)
## Define new_version according to revision number
if is_var_empty "${new_version_revision-}" "|| "; then
debug_message "| define_vars No revision for this package."
new_version="${new_version_major}"
else
debug_message "| define_vars There is a revision (${new_version_revision}) for this package."
new_version="${new_version_major}-${new_version_revision}"
fi
debug_message "| define_vars Set (${RED}${new_version}${COLOR_DEBUG}) for new_version variable."
## }}}
## If new_package_filename wasn't defined {{{
is_var_empty "${new_package_filename-}" "|| " \
&& new_package_filename="${package_name}_${new_version}_all.deb" \
&& debug_message "| define_vars Use value (${RED}${new_package_filename}${COLOR_DEBUG}) for new_package_filename variable."
## }}}
## If new_package_url wasn't defined {{{
is_var_empty "${new_package_url-}" "|| " \
&& new_package_url="${repo_url}/releases/download/${new_version_major}/${new_package_filename}" \
&& debug_message "| define_vars Use value (${RED}${new_package_url}${COLOR_DEBUG}) for new_package_url variable."
## }}}
## If new_version_file wasn't defined {{{
is_var_empty "${new_version_file-}" "|| " \
&& new_version_file="/tmp/.github.${package_name}.upgrade" \
&& debug_message "| define_vars Use value (${RED}${new_version_file}${COLOR_DEBUG}) for new_version_file variable."
## }}}
## If tmp_package_path wasn't defined {{{
is_var_empty "${tmp_package_path-}" "|| " \
&& tmp_package_path="/tmp/.${new_package_filename}" \
&& debug_message "| define_vars Use value (${RED}${tmp_package_path}${COLOR_DEBUG}) for tmp_package_path variable."
## }}}
## If new_package_path wasn't defined {{{
is_var_empty "${new_package_path-}" "|| " \
&& new_package_path="/tmp/${new_package_filename}" \
&& debug_message "| define_vars Use value (${RED}${new_package_path}${COLOR_DEBUG}) for new_package_path variable."
## }}}
## If check_mode wasn't defined (argument) {{{
## Use default value
is_var_empty "${check_mode-}" "|| " \
&& debug_message "| define_vars Use default value (${RED}${CHECK_MODE_DEFAULT}${COLOR_DEBUG}) for check_mode variable." \
&& check_mode="${CHECK_MODE_DEFAULT}"
## }}}
## Get current_version according to the check_mode {{{
case "${check_mode}" in
"repo"|"repository" ) ## Check current version from repository
current_version=$(apt-cache policy -- "${package_name}" | awk '/Candidate:/ {print $2}' | sed 's/.:\(.*\)/\1/')
;;
"file" ) ## Check current version from installed .deb file
current_version=$(dpkg --list -- "${package_name}" | awk -v pattern="${package_name}" '$0~pattern {print $3}' | sed 's/.:\(.*\)-.*/\1/')
;;
* ) ## unknow mode
error_message "define_vars Invalid check mode: ${check_mode}. See help message with -h." 2
;;
esac
## If current_version is empty
is_var_empty "${current_version}" "|| " \
&& error_message "define_vars Error with current_version variable (${current_version}) for package (${package_name})." 2
## }}}
debug_message "-- define_vars END"
}
# }}}
is_version_greater_than() { # {{{
first_value="${1}"
value_to_compare="${2}"
debug_prefix="${3:-}"
## Return False by default
return_is_version_greater_than="1"
debug_message "${debug_prefix}is_version_greater_than \
Is first value (${first_value}) greater than the second value (${value_to_compare})."
if printf '%s\n' "${first_value}" "${value_to_compare}" | sort --check=quiet --version-sort; then
debug_message "${debug_prefix}is_version_greater_than ${first_value} <= ${value_to_compare} ."
return_is_version_greater_than="1"
else
debug_message "${debug_prefix}is_version_greater_than ${first_value} > ${value_to_compare} ."
return_is_version_greater_than="0"
fi
unset first_value
unset value_to_compare
unset debug_prefix
return "${return_is_version_greater_than}"
}
# }}}
main() { # {{{
debug_message "--- MAIN BEGIN"
## Define all vars
define_vars
## Uncomment variable(s) to simulate different behaviour
#current_version="14-1"
#new_version="22-1"
debug_message "-- Test version BEGIN"
## If new_version is greater than current_version {{{
if is_version_greater_than "${new_version}" "${current_version}" "|| "; then
debug_message "| Current version (${current_version}) is older than new one \
(${new_version})."
### If it doesn't already exists, download the new package {{{
if [ ! -f "${new_package_path}" ]; then
debug_message "| Download .deb file from ${package_name} repository on Github to: ${new_package_path} ."
wget --quiet "${new_package_url}" --output-document="${new_package_path}"
fi
### }}}
## }}}
## If current version is uptodate {{{
else
debug_message "| Current version (${current_version}) seems uptodate \
or newer than available version (${new_version})."
### Ensure to remove any temp file and useless .deb files
rm --force -- "${new_version_file}" "${new_package_path}" "${tmp_package_path}" "${installer_script_file}"
### Exit
debug_message "-- Test version END"
debug_message "--- MAIN END"
exit 0
fi
## }}}
debug_message "-- Test version END"
## Verify downloaded package {{{
debug_message "-- Verify downloaded package BEGIN"
## If the downloaded package has a size greater than zero {{{
if [ -s "${new_package_path}" ]; then
debug_message "| Downloaded package looks good."
### Create a temp file to monitor
touch -- "${new_version_file}"
printf '\e[1;35m%-6s\e[m\n' "An upgrade is available for ${package_name} terminal (current: ${current_version}): ${new_version}." >> "${new_version_file}"
## }}}
## If the size is null {{{
else
debug_message "| Empty file, don't need to go further."
### Ensure to remove the file to monitor
rm --force -- "${new_version_file}" "${installer_script_file}"
### Keep a record of the downloaded package because as a new release might come soon
mv --force -- "${new_package_path}" "${tmp_package_path}"
fi
## }}}
debug_message "-- Verify downloaded package END"
# }}}
debug_message "--- MAIN END"
# Exit
exit 0
}
# }}}
# Manage arguments # {{{
# This code can't be in a function due to argument management
if [ ! "${NBARGS}" -eq "0" ]; then
manage_arg="0"
## If the first argument ask for help (h|help|-h|-help|-*h|-*help) {{{
if printf -- '%s' "${1-}" | grep --quiet --extended-regexp -- "^-*h(elp)?$"; then
usage
exit 0
fi
## }}}
## If the first argument is not an option
if ! printf -- '%s' "${1}" | grep --quiet --extended-regexp -- "^-+";
then
## Print help message and exit
printf '%b\n' "${RED}Invalid option: ${1}${RESET}"
printf '%b\n' "---"
usage
exit 1
fi
# Parse all options (start with a "-") one by one
while printf -- '%s' "${1-}" | grep --quiet --extended-regexp -- "^-+"; do
case "${1}" in
-d|--debug ) ## debug
DEBUG=0
debug_message "--- Manage argument BEGIN"
;;
-f|--file|--files|-p|--package ) ## Define check_mode to file mode
## Define var
readonly check_mode="file"
;;
--repo|--repository ) ## Define check_mode to repo mode
## Define var
readonly check_mode="repo"
;;
* ) ## unknow option
printf '%b\n' "${RED}Invalid option: ${1}${RESET}"
printf '%b\n' "---"
usage
exit 1
;;
esac
debug_message "| ${RED}${1}${COLOR_DEBUG} option managed."
## Move to the next argument
shift
manage_arg=$((manage_arg+1))
done
debug_message "| ${RED}${manage_arg}${COLOR_DEBUG} argument(s) successfully managed."
else
debug_message "| No arguments/options to manage."
fi
debug_message "--- Manage argument END"
# }}}
main
# This should never be reach
exit 255