Skip to content
5 changes: 5 additions & 0 deletions .github/renovate-tracked-deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
"mise"
]
},
".github/workflows/micrometer-compatibility.yml": {
"regex": [
"mise"
]
},
".github/workflows/native-tests.yml": {
"regex": [
"mise"
Expand Down
43 changes: 43 additions & 0 deletions .github/workflows/micrometer-compatibility.yml
Original file line number Diff line number Diff line change
@@ -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
145 changes: 145 additions & 0 deletions .mise/lib/micrometer_compat.py
Original file line number Diff line number Diff line change
@@ -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)
26 changes: 26 additions & 0 deletions .mise/tasks/micrometer/prepare.py
Original file line number Diff line number Diff line change
@@ -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())
28 changes: 28 additions & 0 deletions .mise/tasks/micrometer/test-class.py
Original file line number Diff line number Diff line change
@@ -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())
28 changes: 28 additions & 0 deletions .mise/tasks/micrometer/test.py
Original file line number Diff line number Diff line change
@@ -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())
4 changes: 4 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ taplo = "0.10.0"

[env]
FLINT_CONFIG_DIR = ".github/config"
# Use a custom Micrometer fork+commit until the downstream adapter fix lands upstream.
# This keeps the compatibility test stable while still exercising the prom-side regression.
MICROMETER_REPOSITORY = "zeitlinger/micrometer"
MICROMETER_REF = "72851a5924941adc414c13b05848d3e4567c6722"
# renovate: datasource=github-releases depName=grafana/docker-otel-lgtm
LGTM_VERSION = "0.25.0"

Expand Down