|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# Licensed to the Apache Software Foundation (ASF) under one |
| 3 | +# or more contributor license agreements. See the NOTICE file |
| 4 | +# distributed with this work for additional information |
| 5 | +# regarding copyright ownership. The ASF licenses this file |
| 6 | +# to you under the Apache License, Version 2.0 (the |
| 7 | +# "License"); you may not use this file except in compliance |
| 8 | +# with the License. You may obtain a copy of the License at |
| 9 | +# |
| 10 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | +# |
| 12 | +# Unless required by applicable law or agreed to in writing, |
| 13 | +# software distributed under the License is distributed on an |
| 14 | +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | +# KIND, either express or implied. See the License for the |
| 16 | +# specific language governing permissions and limitations |
| 17 | +# under the License. |
| 18 | +""" |
| 19 | +Verify the Java SDK JDK version is consistent across all files that declare it. |
| 20 | +
|
| 21 | +The authoritative version lives in five places that must stay in sync: |
| 22 | +
|
| 23 | +- .github/workflows/ci-amd.yml |
| 24 | + -> env.JAVA_VERSION |
| 25 | +- .github/workflows/ci-arm.yml |
| 26 | + -> env.JAVA_VERSION |
| 27 | +- .github/workflows/codeql-analysis.yml |
| 28 | + -> steps[].with.java-version |
| 29 | +- java-sdk/buildSrc/src/main/kotlin/airflow-jvm-conventions.gradle.kts |
| 30 | + -> java.toolchain.languageVersion.set(JavaLanguageVersion.of(<n>)) |
| 31 | + -> java.sourceCompatibility = JavaVersion.VERSION_<n> |
| 32 | + -> kotlin.compilerOptions.jvmTarget = JvmTarget.JVM_<n> |
| 33 | +- scripts/docker/install_jdk.sh |
| 34 | + -> TEMURIN_VERSION="<n>" |
| 35 | +""" |
| 36 | + |
| 37 | +from __future__ import annotations |
| 38 | + |
| 39 | +import dataclasses |
| 40 | +import pathlib |
| 41 | +import re |
| 42 | +import sys |
| 43 | + |
| 44 | + |
| 45 | +@dataclasses.dataclass |
| 46 | +class VersionSite: |
| 47 | + """A single location that declares the Java version.""" |
| 48 | + |
| 49 | + label: str |
| 50 | + path: pathlib.Path |
| 51 | + pattern: re.Pattern[str] |
| 52 | + |
| 53 | + def extract(self) -> str | None: |
| 54 | + """Find version string with regex.""" |
| 55 | + if m := self.pattern.search(self.path.read_text()): |
| 56 | + return m.group(1) |
| 57 | + return None |
| 58 | + |
| 59 | + |
| 60 | +REPO_ROOT = pathlib.Path(__file__).resolve().parents[3] |
| 61 | + |
| 62 | +WORKFLOWS = REPO_ROOT.joinpath(".github", "workflows") |
| 63 | +SDK_CONVENTION = REPO_ROOT.joinpath("java-sdk/buildSrc/src/main/kotlin/airflow-jvm-conventions.gradle.kts") |
| 64 | + |
| 65 | +SITES = [ |
| 66 | + VersionSite( |
| 67 | + label=".github/workflows/ci-amd.yml (env.JAVA_VERSION)", |
| 68 | + path=WORKFLOWS.joinpath("ci-amd.yml"), |
| 69 | + pattern=re.compile(r"^\s+JAVA_VERSION:\s+'(\d+)'", re.MULTILINE), |
| 70 | + ), |
| 71 | + VersionSite( |
| 72 | + label=".github/workflows/ci-arm.yml (env.JAVA_VERSION)", |
| 73 | + path=WORKFLOWS.joinpath("ci-arm.yml"), |
| 74 | + pattern=re.compile(r"^\s+JAVA_VERSION:\s+'(\d+)'", re.MULTILINE), |
| 75 | + ), |
| 76 | + VersionSite( |
| 77 | + label=".github/workflows/codeql-analysis.yml (steps[].with.java-version)", |
| 78 | + path=WORKFLOWS.joinpath("codeql-analysis.yml"), |
| 79 | + pattern=re.compile(r"^\s+java-version:\s+'(\d+)'", re.MULTILINE), |
| 80 | + ), |
| 81 | + VersionSite( |
| 82 | + label="java-sdk/buildSrc/.../airflow-jvm-conventions.gradle.kts (JavaLanguageVersion.of(...))", |
| 83 | + path=SDK_CONVENTION, |
| 84 | + pattern=re.compile(r"JavaLanguageVersion\.of\((\d+)\)"), |
| 85 | + ), |
| 86 | + VersionSite( |
| 87 | + label="java-sdk/buildSrc/.../airflow-jvm-conventions.gradle.kts (JavaVersion.VERSION_...)", |
| 88 | + path=SDK_CONVENTION, |
| 89 | + pattern=re.compile(r"JavaVersion\.VERSION_(\d+)"), |
| 90 | + ), |
| 91 | + VersionSite( |
| 92 | + label="java-sdk/buildSrc/.../airflow-jvm-conventions.gradle.kts (JvmTarget.JVM_...)", |
| 93 | + path=SDK_CONVENTION, |
| 94 | + pattern=re.compile(r"JvmTarget\.JVM_(\d+)"), |
| 95 | + ), |
| 96 | + VersionSite( |
| 97 | + label="scripts/docker/install_jdk.sh (TEMURIN_VERSION)", |
| 98 | + path=REPO_ROOT.joinpath("scripts", "docker", "install_jdk.sh"), |
| 99 | + pattern=re.compile(r'^readonly TEMURIN_VERSION="(\d+)"', re.MULTILINE), |
| 100 | + ), |
| 101 | +] |
| 102 | + |
| 103 | + |
| 104 | +def main() -> int: |
| 105 | + results = [(site, site.extract()) for site in SITES] |
| 106 | + |
| 107 | + if not_found := [(site, v) for site, v in results if v is None]: |
| 108 | + for site, _ in not_found: |
| 109 | + print(f"ERROR: Java version pattern not found in {site.path.relative_to(REPO_ROOT)}") |
| 110 | + print(f" Pattern: {site.pattern.pattern!r}") |
| 111 | + return len(not_found) |
| 112 | + |
| 113 | + versions = {v for _, v in results} |
| 114 | + if len(versions) == 1: |
| 115 | + (version,) = versions |
| 116 | + print(f"OK: Java SDK version is consistently {version} across all {len(SITES)} locations.") |
| 117 | + return 0 |
| 118 | + |
| 119 | + print("ERROR: Java SDK version is inconsistent across files:") |
| 120 | + print() |
| 121 | + col = max(len(site.label) for site, _ in results) |
| 122 | + for site, version in results: |
| 123 | + print(f" {site.label:<{col}} {version}") |
| 124 | + print() |
| 125 | + print("Update all locations to the same version, or adjust the patterns in") |
| 126 | + print(f" {pathlib.Path(__file__).relative_to(REPO_ROOT)}") |
| 127 | + print("if the pattern no longer matches.") |
| 128 | + return 1 |
| 129 | + |
| 130 | + |
| 131 | +if __name__ == "__main__": |
| 132 | + sys.exit(main()) |
0 commit comments