diff --git a/.github/renovate-tracked-deps.json b/.github/renovate-tracked-deps.json index b29b53789..d101f7abf 100644 --- a/.github/renovate-tracked-deps.json +++ b/.github/renovate-tracked-deps.json @@ -34,6 +34,11 @@ "mise" ] }, + ".github/workflows/micrometer-compatibility.yml": { + "regex": [ + "mise" + ] + }, ".github/workflows/native-tests.yml": { "regex": [ "mise" diff --git a/.github/workflows/micrometer-compatibility.yml b/.github/workflows/micrometer-compatibility.yml new file mode 100644 index 000000000..e044d5b2a --- /dev/null +++ b/.github/workflows/micrometer-compatibility.yml @@ -0,0 +1,43 @@ +--- +name: Micrometer Compatibility + +on: + pull_request: + workflow_dispatch: + inputs: + micrometer-repository: + description: Micrometer repository to test, in owner/name form + required: false + default: micrometer-metrics/micrometer + micrometer-ref: + description: Micrometer branch, tag, or commit to test + required: false + default: main + +permissions: {} + +jobs: + micrometer-compatibility: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1 + with: + version: v2026.4.23 + sha256: 4a650daf1c6db2bb9c32a4d4f6d2389051906f85792d97b04ad10b9f6e212372 + - name: Cache local Maven repository + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: Run Micrometer compatibility tests + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + export MICROMETER_REPOSITORY="${{ github.event.inputs.micrometer-repository }}" + export MICROMETER_REF="${{ github.event.inputs.micrometer-ref }}" + fi + mise run micrometer:test diff --git a/.mise/lib/micrometer_compat.py b/.mise/lib/micrometer_compat.py new file mode 100644 index 000000000..74bbb69a2 --- /dev/null +++ b/.mise/lib/micrometer_compat.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 + +from __future__ import annotations + +import os +import subprocess +from pathlib import Path +from typing import Optional +import xml.etree.ElementTree as ET + + +DEFAULT_MICROMETER_DIR = Path( + os.environ.get("MICROMETER_DIR", "/tmp/micrometer-compat") +) +DEFAULT_MICROMETER_REPOSITORY = os.environ.get( + "MICROMETER_REPOSITORY", "micrometer-metrics/micrometer" +) +DEFAULT_MICROMETER_REMOTE = os.environ.get("MICROMETER_REMOTE", "origin") +DEFAULT_MICROMETER_REF = os.environ.get("MICROMETER_REF", "main") +DEFAULT_INIT_SCRIPT = Path( + os.environ.get("MICROMETER_INIT_SCRIPT", "/tmp/micrometer-prom-local.init.gradle") +) +DEFAULT_PROM_VERSION = os.environ.get("PROM_VERSION") + + +def run_cmd(cmd: list[str], cwd: Optional[Path] = None) -> None: + subprocess.run(cmd, cwd=cwd, check=True) + + +def micrometer_repository_url(repository: str) -> str: + return f"https://github.com/{repository}.git" + + +def check_clean_worktree(micrometer_dir: Path) -> None: + result = subprocess.run( + ["git", "status", "--short"], + cwd=micrometer_dir, + check=True, + capture_output=True, + text=True, + ) + if result.stdout.strip(): + raise RuntimeError( + f"{micrometer_dir} has uncommitted changes; use a clean clone or set MICROMETER_DIR" + ) + + +def get_prom_version(root_dir: Path = Path.cwd()) -> str: + configured_version = DEFAULT_PROM_VERSION + if configured_version: + return configured_version + pom = ET.parse(root_dir / "pom.xml") + root = pom.getroot() + version = root.findtext("./{*}version") + if not version: + version = root.findtext("./{*}parent/{*}version") + if not version: + raise RuntimeError("could not determine Prometheus version from pom.xml") + return version + + +def write_init_script( + init_script: Path = DEFAULT_INIT_SCRIPT, prom_version: Optional[str] = None +) -> None: + if prom_version is None: + prom_version = get_prom_version() + init_script.write_text( + f"""allprojects {{ + repositories {{ + mavenLocal() + mavenCentral() + gradlePluginPortal() + }} + configurations.configureEach {{ + resolutionStrategy.eachDependency {{ details -> + if (details.requested.group == 'io.prometheus') {{ + details.useVersion('{prom_version}') + details.because('Use local prom_client_java artifacts for downstream compatibility testing') + }} + }} + }} +}} +""", + encoding="utf-8", + ) + + +def prepare_repo( + micrometer_dir: Path = DEFAULT_MICROMETER_DIR, + repository: str = DEFAULT_MICROMETER_REPOSITORY, + remote: str = DEFAULT_MICROMETER_REMOTE, + ref: str = DEFAULT_MICROMETER_REF, +) -> None: + repository_url = micrometer_repository_url(repository) + if (micrometer_dir / ".git").is_dir(): + check_clean_worktree(micrometer_dir) + run_cmd( + ["git", "remote", "set-url", remote, repository_url], cwd=micrometer_dir + ) + run_cmd(["git", "fetch", remote, ref], cwd=micrometer_dir) + else: + run_cmd( + [ + "git", + "clone", + repository_url, + str(micrometer_dir), + ] + ) + run_cmd(["git", "fetch", remote, ref], cwd=micrometer_dir) + run_cmd( + ["git", "checkout", "-B", "codex-micrometer-compat", "FETCH_HEAD"], + cwd=micrometer_dir, + ) + + +def install_local_artifacts(root_dir: Path = Path.cwd()) -> None: + run_cmd( + [ + "./mvnw", + "install", + "-DskipTests", + "-Dcoverage.skip=true", + "-Dcheckstyle.skip=true", + "-Dwarnings=-nowarn", + ], + cwd=root_dir, + ) + + +def run_gradle_test( + test_selector: Optional[str] = None, + micrometer_dir: Path = DEFAULT_MICROMETER_DIR, + init_script: Path = DEFAULT_INIT_SCRIPT, +) -> None: + cmd = [ + "./gradlew", + "--no-daemon", + "-I", + str(init_script), + ":micrometer-registry-prometheus:test", + ] + if test_selector: + cmd.extend(["--tests", test_selector]) + run_cmd(cmd, cwd=micrometer_dir) diff --git a/.mise/tasks/micrometer/prepare.py b/.mise/tasks/micrometer/prepare.py new file mode 100755 index 000000000..ba13acf69 --- /dev/null +++ b/.mise/tasks/micrometer/prepare.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 + +# [MISE] description="Install local artifacts and check out a target Micrometer ref" +# [MISE] alias="micrometer:prepare" + +import sys + + +sys.path.insert(0, ".mise/lib") + + +def main() -> int: + from micrometer_compat import ( + install_local_artifacts, + prepare_repo, + write_init_script, + ) + + install_local_artifacts() + prepare_repo() + write_init_script() + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/.mise/tasks/micrometer/test-class.py b/.mise/tasks/micrometer/test-class.py new file mode 100755 index 000000000..89ae436de --- /dev/null +++ b/.mise/tasks/micrometer/test-class.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +# [MISE] description="Run Micrometer PrometheusMeterRegistryTest against a target Micrometer ref" +# [MISE] alias="micrometer:test-class" + +import sys + + +sys.path.insert(0, ".mise/lib") + + +def main() -> int: + from micrometer_compat import ( + install_local_artifacts, + prepare_repo, + run_gradle_test, + write_init_script, + ) + + install_local_artifacts() + prepare_repo() + write_init_script() + run_gradle_test("io.micrometer.prometheusmetrics.PrometheusMeterRegistryTest") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/.mise/tasks/micrometer/test.py b/.mise/tasks/micrometer/test.py new file mode 100755 index 000000000..40316f569 --- /dev/null +++ b/.mise/tasks/micrometer/test.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +# [MISE] description="Run Micrometer Prometheus registry tests against a target Micrometer ref" +# [MISE] alias="micrometer:test" + +import sys + + +sys.path.insert(0, ".mise/lib") + + +def main() -> int: + from micrometer_compat import ( + install_local_artifacts, + prepare_repo, + run_gradle_test, + write_init_script, + ) + + install_local_artifacts() + prepare_repo() + write_init_script() + run_gradle_test() + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/mise.toml b/mise.toml index a6ac6c257..8d5dad428 100644 --- a/mise.toml +++ b/mise.toml @@ -24,6 +24,8 @@ taplo = "0.10.0" [env] FLINT_CONFIG_DIR = ".github/config" +MICROMETER_REPOSITORY = "zeitlinger/micrometer" +MICROMETER_REF = "72851a5924941adc414c13b05848d3e4567c6722" # renovate: datasource=github-releases depName=grafana/docker-otel-lgtm LGTM_VERSION = "0.25.0"