diff --git a/check_forgejo_upgrade b/check_forgejo_upgrade index 50b4638..f99f7e3 100755 --- a/check_forgejo_upgrade +++ b/check_forgejo_upgrade @@ -23,6 +23,7 @@ import logging import re import subprocess # nosec import sys +import traceback import requests @@ -50,12 +51,30 @@ parser.add_argument( parser.add_argument( "-t", "--timeout", type=int, help="Specify timeout for HTTP requests (default: 20)", default=20 ) +parser.add_argument( + "-m", + "--major-release", + type=int, + help=( + "Optional major release number to filter available versions, for instance, specified 10 " + "to filter on 10.X.Y versions" + ), +) options = parser.parse_args() logging.basicConfig(level=logging.DEBUG if options.debug else logging.WARNING) -CURRENT = None + +def get_version_id(version): + """Compute version ID from version name""" + return sum( + int(value) * (10 ** (idx * 4)) + for idx, value in enumerate(reversed(re.sub(r"[^0-9\.]", "", version).split("."))) + ) + + +CURRENT_NAME = None cmd = [options.path, "--version"] logging.debug("Command use to retrieve current version of Forgejo: %s", " ".join(cmd)) @@ -66,12 +85,12 @@ try: logging.debug("Output:\n%s", OUTPUT) m = re.search(r"version ([^ ]+)(\+gitea-| built)", OUTPUT.decode("utf8", errors="ignore")) if m: - CURRENT = m.group(1) + CURRENT_NAME = m.group(1) except Exception as err: # pylint: disable=broad-except EXCEPTION = err -logging.debug("Current version: %s", CURRENT) +logging.debug("Current version: %s", CURRENT_NAME) -if not CURRENT: +if not CURRENT_NAME: print("UNKNOWN - Fail to retrieve current Forgejo") print(f'Command: {" ".join(cmd)}') print("Output:") @@ -80,10 +99,13 @@ if not CURRENT: print(EXCEPTION if EXCEPTION else "") sys.exit(3) -CURRENT = CURRENT.replace("+", "-") -logging.debug("Cleaned current version: %s", CURRENT) +CURRENT_NAME = CURRENT_NAME.replace("+", "-") +CURRENT_ID = get_version_id(CURRENT_NAME) +logging.debug("Cleaned current version: %s (ID=%s)", CURRENT_NAME, CURRENT_ID) +CURRENT = None LATEST = None +LATEST_ID = None LATEST_NAME = None try: logging.debug("Get releases from %s...", options.url) @@ -91,36 +113,55 @@ try: data = r.json() logging.debug("Data retrieve:\n%s", data) for item in data: + version_id = get_version_id(item["name"]) + if version_id == CURRENT_ID: + logging.debug("Current release %s found: %s", CURRENT_NAME, CURRENT) + CURRENT = item if not options.pre_release and item["prerelease"]: logging.debug("Ignore pre-release %s", item["name"]) continue if not options.draft and item["draft"]: logging.debug("Ignore draft release %s", item["name"]) continue + if options.major_release and not re.match(f"v?{options.major_release}.", item["name"]): + logging.debug( + "Ignore release %s (not a %d.X.Y release)", item["name"], options.major_release + ) + continue + logging.debug("Version %s found (ID=%s)", item["name"], version_id) + if LATEST_ID and LATEST_ID > version_id: + continue LATEST = item + LATEST_ID = version_id LATEST_NAME = re.sub("^v", "", item["name"]) - break except Exception: # pylint: disable=broad-except # nosec - pass - -if not LATEST: - print("UNKNOWN - Fail to retrieve latest Forgejo release from the project RSS feed") - print(f"Current version: {CURRENT}") + print("UNKNOWN - An exception occurred retrieving latest Forgejo release from the project API") + traceback.print_last() sys.exit(3) -logging.debug("Latest version is %s", LATEST_NAME) +if not LATEST: + print("UNKNOWN - Fail to retrieve latest Forgejo release from the project API") + print(f"Current version: {CURRENT_NAME}") + sys.exit(3) -if LATEST_NAME == CURRENT: - print( - f"OK - The latest release of Forgejo is currently used " - f"({LATEST_NAME}, published on {LATEST['published_at']})" - ) +logging.debug("Latest version is %s (ID: %s)", LATEST_NAME, LATEST_ID) + +if LATEST_ID <= CURRENT_ID: + print(f"OK - Forgejo is up to date ({CURRENT_NAME})") + if LATEST_ID != CURRENT_ID: + print(f"Latest release available: {LATEST_NAME} (published on {LATEST['published_at']})") + else: + print(f"Published on {LATEST['published_at']}") sys.exit(0) print( - "WARNING - The version of Forgejo currently used is not the latest " - f"({CURRENT} vs {LATEST_NAME}), published on {LATEST['published_at']})" + f"WARNING - An update of Forgejo is available " + f"({LATEST_NAME}, published on {LATEST['published_at']})" ) +if CURRENT: + print(f"Current version: {CURRENT_NAME} (published on {CURRENT['published_at']})") +else: + print(f"Current version: {CURRENT_NAME}") print(LATEST["body"]) -print(f"URL: {LATEST['html_url']}") +print(f"Download URL: {LATEST['html_url']}") sys.exit(1)