diff --git a/.gitlab-ci/distros_support.py b/.gitlab-ci/distros_support.py new file mode 100755 index 000000000..7963440a6 --- /dev/null +++ b/.gitlab-ci/distros_support.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 + +import datetime +import os +import sys + +try: + import yaml +except ImportError: + print("Error: missing pyyaml. Install with `pip install pyyaml`.", file=sys.stderr) + quit(code=1) + + +# These are the distros that we currently check, ordered by priority to be chosen as Tier 1 +ci_distros = ("fedora", "centos", "debian", "ubuntu", "alpine") + + +def _parse_date(date_str) -> datetime.date: + return datetime.datetime.strptime(date_str, "%Y-%m-%d").date() + + +def _is_supported(val_str, today) -> bool: + val_str = val_str.lower() + if val_str in ("yes", "true"): + return True + elif val_str in ("no", "false"): + return False + else: + support_date = _parse_date(val_str) + return today <= support_date + + +def _nm_version_is_newer(nm_ver, nm_ver_from): + if nm_ver == "main": + return nm_ver_from != "main" # main is newer than anything except main itself + elif nm_ver_from == "main": + return False + nm_ver = nm_ver.split(".") + nm_ver_from = nm_ver_from.split(".") + if int(nm_ver[0]) > int(nm_ver_from[0]): + return True + elif nm_ver[0] == nm_ver_from[0] and int(nm_ver[1]) > int(nm_ver_from[1]): + return True + return False + + +if len(sys.argv) != 2: + print(f"Usage: {sys.argv[0]} ") + quit(code=1) + +nm_version = sys.argv[1] +today = datetime.date.today() +with open(os.path.dirname(__file__) + "/distros-info.yml") as f: + distros_info = yaml.load(f, Loader=yaml.BaseLoader) + +# Warn about EOL'd distros to remove them +for distro, versions in distros_info.items(): + for info in versions: + if _is_supported(info["support"], today): + continue + if "extended-support" in info and _is_supported( + info["extended-support"], today + ): + continue + print( + f"Warn: {distro} {info['version']} reached EOL, consider deleting this entry", + file=sys.stderr, + ) + +# Print distros that uses this nm_version +print(f"# List of distros using NM {nm_version}") +print("---") +for distro, versions in distros_info.items(): + for info in versions: + if nm_version == info["nm"] and _is_supported(info["support"], today): + try: + support_end_date = _parse_date(info["support"]) + print( + f"- {distro} {info['version']}, supported until {info['support']}" + ) + except ValueError: + print(f"- {distro} {info['version']}, supported") + +# Collect info about what distros should be Tier 2 and 3 +tier2 = {} +tier3 = {} +for distro, versions in distros_info.items(): + if distro not in ci_distros: + continue + for info in versions: + if not _is_supported(info["support"], today): + continue + if nm_version == info["nm"]: + tier2.setdefault(distro, []).append(info["version"]) + elif _nm_version_is_newer(nm_version, info["nm"]): + tier3.setdefault(distro, []).append(info["version"]) + +# Select a Tier1 distro +tier1_distro, tier1_version = "", "" +for distro in ci_distros: + for tier in (tier2, tier3): + if distro in tier: + # Exception: we want to use fedora:latest instead of fedora:rawhide because + # we don't want lot of build failures in Tier 1, which is run for every MR. + # We just ignore fedora:rawhide for Tier 1. + if distro == "fedora" and tier[distro][0] == "rawhide": + if len(tier[distro]) == 1: + continue + idx = 1 + else: + idx = 0 + + tier1_distro = distro + tier1_version = tier[distro].pop(idx) + if not tier[distro]: + del tier[distro] + break + if tier1_distro: + break + +if not tier1_distro or not tier1_version: + print("Warn: no suitable distro for Tier 1 found", file=sys.stderr) + + +# Print the config.yml needed for the corresponding stable branch +branch = "main" if nm_version == "main" else "nm-" + nm_version.replace(".", "-") +print("\n# .gitlab-ci/config.yml for branch '{}'".format(branch)) +print( + """--- +# This file contains the configuration for the gitlab ci. +# +# To recreate the .gitlab-ci.yml file, run +# ci-fairy generate-template +# +# The ci-fairy tool is part of +# https://gitlab.freedesktop.org/freedesktop/ci-templates +# + +# Some distros are fairly similar, and we reuse similar scripts. +# The base type maps the distro name to their base. +base_types: + fedora: fedora + centos: fedora + debian: debian + ubuntu: debian + alpine: alpine + +# The list of all distributions we want to create job for. +distributions: + # TIER 1: CI run for all MRs. + # The first tier:1 in the list is used to build the pages and check-{tree,patch}.""" +) +print(" - name: {}".format(tier1_distro)) +print(" tier: 1") +print(" versions:") +print(" - '{}'".format(tier1_version)) + +print( + """ + # TIER 2: distribution versions that will or might use the current NM version. + # Run when doing a release.""" +) +for distro, versions in tier2.items(): + print(" - name: {}".format(distro)) + print(" tier: 2") + print(" versions:") + for version in versions: + print(" - '{}'".format(version)) + +print( + """ + # TIER 3: distribution versions not in EOL but don't use the current NM version. + # Run when doing a release, but a failure won't be blocking for the release.""" +) +for distro, versions in tier3.items(): + print(" - name: {}".format(distro)) + print(" tier: 3") + print(" versions:") + for version in versions: + print(" - '{}'".format(version))