diff --git a/static/compatibilities.yaml b/static/compatibilities.yaml index 83e0613f5d..b325147ad8 100644 --- a/static/compatibilities.yaml +++ b/static/compatibilities.yaml @@ -26265,6 +26265,55 @@ addons: chart_version: 0.1.0-alpha.4 images: ['timberio/vector:0.16.1-distroless-libc'] name: vector +- icon: https://raw.githubusercontent.com/volcano-sh/charts/master/docs/images/volcano-logo.png + git_url: https://github.com/volcano-sh/volcano + release_url: https://github.com/volcano-sh/volcano/releases/tag/v{vsn} + helm_repository_url: https://volcano-sh.github.io/helm-charts + readme_url: https://github.com/volcano-sh/volcano#kubernetes-compatibility + versions: + - version: 1.15.0 + kube: ['1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27', + '1.26', '1.25', '1.24'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.15.0 + - version: 1.14.3 + kube: ['1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27', '1.26', + '1.25', '1.24', '1.23'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.14.3 + - version: 1.13.3 + kube: ['1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27', '1.26', '1.25', + '1.24', '1.23'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.13.3 + - version: 1.12.4 + kube: ['1.32', '1.31', '1.30', '1.29', '1.28', '1.27', '1.26', '1.25', '1.24', + '1.23', '1.22', '1.21'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.12.4 + - version: 1.11.2 + kube: ['1.31', '1.30', '1.29', '1.28', '1.27', '1.26', '1.25', '1.24', '1.23', + '1.22', '1.21'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.11.2 + - version: 1.10.2 + kube: ['1.30', '1.29', '1.28', '1.27', '1.26', '1.25', '1.24', '1.23', '1.22', + '1.21'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.10.2 + name: volcano - git_url: https://github.com/VictoriaMetrics/operator release_url: https://github.com/VictoriaMetrics/operator/releases/tag/v{vsn} helm_repository_url: https://victoriametrics.github.io/helm-charts diff --git a/static/compatibilities/manifest.yaml b/static/compatibilities/manifest.yaml index 6d325d796f..519d1432fa 100644 --- a/static/compatibilities/manifest.yaml +++ b/static/compatibilities/manifest.yaml @@ -38,6 +38,7 @@ names: - argo-cd - argo-workflows - vector +- volcano - victoria-metrics-operator - gpu-operator - harbor diff --git a/static/compatibilities/volcano.yaml b/static/compatibilities/volcano.yaml new file mode 100644 index 0000000000..285be6def3 --- /dev/null +++ b/static/compatibilities/volcano.yaml @@ -0,0 +1,47 @@ +icon: https://raw.githubusercontent.com/volcano-sh/charts/master/docs/images/volcano-logo.png +git_url: https://github.com/volcano-sh/volcano +release_url: https://github.com/volcano-sh/volcano/releases/tag/v{vsn} +helm_repository_url: https://volcano-sh.github.io/helm-charts +readme_url: https://github.com/volcano-sh/volcano#kubernetes-compatibility +versions: +- version: 1.15.0 + kube: ['1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27', '1.26', + '1.25', '1.24'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.15.0 +- version: 1.14.3 + kube: ['1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27', '1.26', '1.25', + '1.24', '1.23'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.14.3 +- version: 1.13.3 + kube: ['1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27', '1.26', '1.25', '1.24', + '1.23'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.13.3 +- version: 1.12.4 + kube: ['1.32', '1.31', '1.30', '1.29', '1.28', '1.27', '1.26', '1.25', '1.24', '1.23', + '1.22', '1.21'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.12.4 +- version: 1.11.2 + kube: ['1.31', '1.30', '1.29', '1.28', '1.27', '1.26', '1.25', '1.24', '1.23', '1.22', + '1.21'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.11.2 +- version: 1.10.2 + kube: ['1.30', '1.29', '1.28', '1.27', '1.26', '1.25', '1.24', '1.23', '1.22', '1.21'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.10.2 diff --git a/utils/compatibility/scrapers/volcano.py b/utils/compatibility/scrapers/volcano.py new file mode 100644 index 0000000000..7037f68654 --- /dev/null +++ b/utils/compatibility/scrapers/volcano.py @@ -0,0 +1,127 @@ +from __future__ import annotations + +import re +from collections import OrderedDict + +from semantic_version import Version +from utils import ( + fetch_page, + get_chart_versions, + print_error, + update_chart_versions, + update_compatibility_info, + validate_semver, +) + +app_name = "volcano" +compatibility_url = ( + "https://raw.githubusercontent.com/volcano-sh/volcano/master/README.md" +) + + +def split_table_row(line: str) -> list[str]: + return [cell.strip() for cell in line.strip().strip("|").split("|")] + + +def latest_app_versions_by_minor( + chart_versions: dict[str, str], +) -> dict[tuple[int, int], str]: + latest: dict[tuple[int, int], tuple[Version, str]] = {} + + for app_version in chart_versions: + version = validate_semver(app_version) + if not version: + continue + + key = (version.major, version.minor) + current = latest.get(key) + if not current or version > current[0]: + latest[key] = (version, str(version)) + + return {key: version for key, (_, version) in latest.items()} + + +def extract_table_data( + markdown: str, chart_versions: dict[str, str] +) -> list[OrderedDict[str, object]]: + lines = markdown.splitlines() + header_index = next( + ( + index + for index, line in enumerate(lines) + if line.startswith("|") and "Kubernetes 1." in line + ), + None, + ) + if header_index is None: + return [] + + kube_versions = [] + for cell in split_table_row(lines[header_index])[1:]: + match = re.search(r"Kubernetes\s+v?(\d+\.\d+)", cell) + kube_versions.append(match.group(1) if match else None) + + latest_versions = latest_app_versions_by_minor(chart_versions) + rows = [] + for line in lines[header_index + 2 :]: + if not line.startswith("|"): + break + + cells = split_table_row(line) + version_match = re.fullmatch( + r"Volcano\s+v?(\d+)\.(\d+)", cells[0], re.IGNORECASE + ) + if not version_match: + continue + + major, minor = (int(value) for value in version_match.groups()) + app_version = latest_versions.get((major, minor)) + if not app_version: + continue + + compatible_kube_versions = [ + kube_version + for kube_version, marker in zip(kube_versions, cells[1:]) + if kube_version and marker == "✓" + ] + if not compatible_kube_versions: + continue + + rows.append( + OrderedDict( + [ + ("version", app_version), + ("kube", compatible_kube_versions), + ("requirements", []), + ("incompatibilities", []), + ] + ) + ) + + return rows + + +def scrape() -> None: + page_content = fetch_page(compatibility_url) + if not page_content: + return + + try: + markdown = page_content.decode("utf-8") + except UnicodeDecodeError as exc: + print_error(f"Failed to decode the Volcano compatibility table: {exc}") + return + + chart_versions = get_chart_versions(app_name) + if not chart_versions: + return + + rows = extract_table_data(markdown, chart_versions) + if not rows: + print_error("No compatibility information found for Volcano.") + return + + update_compatibility_info( + f"../../static/compatibilities/{app_name}.yaml", rows + ) + update_chart_versions(app_name) diff --git a/utils/compatibility/tests/test_volcano.py b/utils/compatibility/tests/test_volcano.py new file mode 100644 index 0000000000..1395fc7813 --- /dev/null +++ b/utils/compatibility/tests/test_volcano.py @@ -0,0 +1,63 @@ +import sys +import unittest +from pathlib import Path + +COMPATIBILITY_DIR = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(COMPATIBILITY_DIR)) +sys.modules.pop("utils", None) + +from scrapers.volcano import ( # noqa: E402 + extract_table_data, + latest_app_versions_by_minor, +) + + +class VolcanoScraperTest(unittest.TestCase): + def test_latest_app_versions_by_minor_ignores_prereleases(self): + versions = latest_app_versions_by_minor( + { + "1.15.0-alpha.0": "1.15.0-alpha.0", + "1.15.0": "1.15.0", + "1.15.1": "1.15.2", + "1.14.3": "1.14.3", + } + ) + + self.assertEqual( + versions, + { + (1, 15): "1.15.1", + (1, 14): "1.14.3", + }, + ) + + def test_extracts_only_exact_compatibility_cells(self): + markdown = """\ +| | Kubernetes 1.36 | Kubernetes 1.35 | Kubernetes 1.34 | +|---|---|---|---| +| Volcano v1.15 | - | ✓ | + | +""" + + rows = extract_table_data( + markdown, + { + "1.15.0": "1.15.0", + "1.15.1": "1.15.1", + }, + ) + + self.assertEqual( + rows, + [ + { + "version": "1.15.1", + "kube": ["1.35"], + "requirements": [], + "incompatibilities": [], + } + ], + ) + + +if __name__ == "__main__": + unittest.main()