Skip to content

Commit 62ce9dc

Browse files
zeitlingerdhoard
andauthored
test: validate JMX Exporter compatibility (#2167)
Draft validation PR for the unmodified JMX Exporter compatibility story. This intentionally does **not** depend on #2114. Vanilla JMX Exporter does not use the typed descriptor API, so this PR validates the patch-compatible path independently of typed descriptors. This validates upstream `prometheus/jmx_exporter@main` against current `client_java` by installing local `io.prometheus` artifacts and running the JMX Exporter collector/common/javaagent/standalone Maven tests against them. Local validation: - `mise run jmx-exporter:test` - `mise run lint:fix` - `mise run lint` - `actionlint .github/workflows/jmx-exporter-compatibility.yml` --------- Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com> Co-authored-by: Doug Hoard <dhoard@users.noreply.github.com>
1 parent 510cbdc commit 62ce9dc

12 files changed

Lines changed: 285 additions & 37 deletions

File tree

.github/renovate-tracked-deps.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
"mise"
4242
]
4343
},
44+
".github/workflows/jmx-exporter-compatibility.yml": {
45+
"regex": [
46+
"mise"
47+
]
48+
},
4449
".github/workflows/lint.yml": {
4550
"regex": [
4651
"mise"
@@ -71,6 +76,16 @@
7176
"mise"
7277
]
7378
},
79+
".mise/envs/jmx-exporter/mise.toml": {
80+
"mise": [
81+
"java"
82+
]
83+
},
84+
".mise/envs/micrometer/mise.toml": {
85+
"mise": [
86+
"java"
87+
]
88+
},
7489
".mise/envs/native/mise.toml": {
7590
"mise": [
7691
"java"
@@ -145,6 +160,11 @@
145160
"taplo",
146161
"typos",
147162
"zizmor"
163+
],
164+
"regex": [
165+
"grafana/docker-otel-lgtm",
166+
"micrometer-metrics/micrometer",
167+
"prometheus/jmx_exporter"
148168
]
149169
},
150170
"mvnw": {

.github/renovate.json5

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,16 @@
3737
matchDepNames: ["com.google.protobuf:protobuf-java", "protoc"],
3838
groupName: "protobuf",
3939
separateMajorMinor: false,
40-
},
40+
}
41+
],
42+
customManagers: [
43+
{
44+
"customType": "regex",
45+
"description": "update _VERSION variables in mise.toml",
46+
"managerFilePatterns": ["/^mise\\.toml$/"],
47+
"matchStrings": [
48+
"# renovate: datasource=(?<datasource>[a-z-]+?)(?: depName=(?<depName>.+?))?(?: packageName=(?<packageName>.+?))?(?: versioning=(?<versioning>[a-z-]+?))?\\s.+?_VERSION\\s*=\\s*\"?(?<currentValue>[^@\"]+?)(?:@(?<currentDigest>sha256:[a-f0-9]+))?\"?\\s"
49+
]
50+
},
4151
],
42-
customManagers: [],
4352
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
name: JMX Exporter Compatibility
3+
4+
on:
5+
pull_request:
6+
workflow_dispatch:
7+
inputs:
8+
repository:
9+
description: JMX Exporter repository to test, in owner/name form
10+
required: false
11+
default: prometheus/jmx_exporter
12+
ref:
13+
description: JMX Exporter branch, tag, or commit to test
14+
required: true
15+
16+
permissions: {}
17+
18+
jobs:
19+
jmx-exporter-compatibility:
20+
runs-on: ubuntu-24.04
21+
steps:
22+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
23+
with:
24+
persist-credentials: false
25+
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1
26+
with:
27+
version: v2026.5.18
28+
sha256: cfac593469d028d7ae5fe36e37bd7c59118b5238e92d8a876209578464f24a84
29+
working_directory: .mise/envs/jmx-exporter
30+
- name: Cache local Maven repository
31+
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
32+
with:
33+
path: ~/.m2/repository
34+
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
35+
- name: Run JMX Exporter compatibility tests
36+
working-directory: .mise/envs/jmx-exporter
37+
env:
38+
JMX_EXPORTER_REPOSITORY: ${{ inputs.repository || 'prometheus/jmx_exporter' }}
39+
JMX_EXPORTER_REF: ${{ inputs.ref }}
40+
run: mise compat-test

.github/workflows/micrometer-compatibility.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ on:
1111
default: micrometer-metrics/micrometer
1212
micrometer-ref:
1313
description: Micrometer branch, tag, or commit to test
14-
required: false
15-
default: main
14+
required: true
1615

1716
permissions: {}
1817

@@ -27,13 +26,15 @@ jobs:
2726
with:
2827
version: v2026.5.18
2928
sha256: cfac593469d028d7ae5fe36e37bd7c59118b5238e92d8a876209578464f24a84
29+
working_directory: .mise/envs/micrometer
3030
- name: Cache local Maven repository
3131
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
3232
with:
3333
path: ~/.m2/repository
3434
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
3535
- name: Run Micrometer compatibility tests
36+
working-directory: .mise/envs/micrometer
3637
env:
37-
MICROMETER_REPOSITORY: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.micrometer-repository || 'micrometer-metrics/micrometer' }}
38-
MICROMETER_REF: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.micrometer-ref || 'main' }}
39-
run: mise run micrometer:test
38+
MICROMETER_REPOSITORY: ${{ inputs.micrometer-repository || 'micrometer-metrics/micrometer' }}
39+
MICROMETER_REF: ${{ inputs.micrometer-ref }}
40+
run: mise compat-test

.mise/envs/jmx-exporter/mise.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# The pinned JMX Exporter release does not build on the primary JDK (Java 25):
2+
# its spotless google-java-format predates JDK 25 support. Build it under an LTS
3+
# JDK the release supports instead.
4+
[tools]
5+
java = "temurin-21.0.11+10.0.LTS"
6+
7+
[tasks.compat-test]
8+
description = "Run JMX Exporter compatibility tests under a supported JDK"
9+
dir = "../../.."
10+
run = "python3 .mise/tasks/jmx-exporter/test.py"

.mise/envs/micrometer/mise.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# The pinned Micrometer release does not build on the primary JDK (Java 25):
2+
# its bundled Kotlin compiler predates JDK 25 support. Build it under an LTS JDK
3+
# the release supports instead.
4+
[tools]
5+
java = "temurin-21.0.11+10.0.LTS"
6+
7+
[tasks.compat-test]
8+
description = "Run Micrometer compatibility tests under a supported JDK"
9+
dir = "../../.."
10+
run = "python3 .mise/tasks/micrometer/test.py"

.mise/lib/jmx_exporter_compat.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#!/usr/bin/env python3
2+
3+
from __future__ import annotations
4+
5+
import os
6+
import subprocess
7+
import xml.etree.ElementTree as ET
8+
from pathlib import Path
9+
from typing import Optional
10+
11+
12+
DEFAULT_JMX_EXPORTER_DIR = Path(
13+
os.environ.get("JMX_EXPORTER_DIR", "/tmp/jmx-exporter-compat")
14+
)
15+
DEFAULT_JMX_EXPORTER_REPOSITORY = os.environ.get(
16+
"JMX_EXPORTER_REPOSITORY", "prometheus/jmx_exporter"
17+
)
18+
DEFAULT_JMX_EXPORTER_REMOTE = os.environ.get("JMX_EXPORTER_REMOTE", "origin")
19+
DEFAULT_JMX_EXPORTER_REF = (
20+
os.environ.get("JMX_EXPORTER_REF")
21+
or os.environ.get("DEFAULT_JMX_EXPORTER_VERSION")
22+
or "main"
23+
)
24+
DEFAULT_MAVEN_MODULES = os.environ.get(
25+
"JMX_EXPORTER_MAVEN_MODULES",
26+
"jmx_prometheus_common,jmx_prometheus_javaagent,jmx_prometheus_standalone",
27+
)
28+
DEFAULT_PROM_VERSION = os.environ.get("PROM_VERSION")
29+
30+
31+
def run_cmd(cmd: list[str], cwd: Optional[Path] = None) -> None:
32+
subprocess.run(cmd, cwd=cwd, check=True)
33+
34+
35+
def jmx_exporter_repository_url(repository: str) -> str:
36+
return f"https://github.com/{repository}.git"
37+
38+
39+
def check_clean_worktree(jmx_exporter_dir: Path) -> None:
40+
result = subprocess.run(
41+
["git", "status", "--short"],
42+
cwd=jmx_exporter_dir,
43+
check=True,
44+
capture_output=True,
45+
text=True,
46+
)
47+
if result.stdout.strip():
48+
raise RuntimeError(
49+
f"{jmx_exporter_dir} has uncommitted changes; use a clean clone or set "
50+
"JMX_EXPORTER_DIR"
51+
)
52+
53+
54+
def get_prom_version(root_dir: Path = Path.cwd()) -> str:
55+
configured_version = DEFAULT_PROM_VERSION
56+
if configured_version:
57+
return configured_version
58+
pom = ET.parse(root_dir / "pom.xml")
59+
root = pom.getroot()
60+
version = root.findtext("./{*}version")
61+
if not version:
62+
version = root.findtext("./{*}parent/{*}version")
63+
if not version:
64+
raise RuntimeError("could not determine Prometheus version from pom.xml")
65+
return version
66+
67+
68+
def prepare_repo(
69+
jmx_exporter_dir: Path = DEFAULT_JMX_EXPORTER_DIR,
70+
repository: str = DEFAULT_JMX_EXPORTER_REPOSITORY,
71+
remote: str = DEFAULT_JMX_EXPORTER_REMOTE,
72+
ref: str = DEFAULT_JMX_EXPORTER_REF,
73+
) -> None:
74+
repository_url = jmx_exporter_repository_url(repository)
75+
if (jmx_exporter_dir / ".git").is_dir():
76+
check_clean_worktree(jmx_exporter_dir)
77+
run_cmd(
78+
["git", "remote", "set-url", remote, repository_url],
79+
cwd=jmx_exporter_dir,
80+
)
81+
run_cmd(["git", "fetch", remote, ref], cwd=jmx_exporter_dir)
82+
else:
83+
run_cmd(["git", "clone", repository_url, str(jmx_exporter_dir)])
84+
run_cmd(["git", "fetch", remote, ref], cwd=jmx_exporter_dir)
85+
run_cmd(
86+
["git", "checkout", "-B", "jmx-exporter-compat", "FETCH_HEAD"],
87+
cwd=jmx_exporter_dir,
88+
)
89+
90+
91+
def install_local_artifacts(root_dir: Path = Path.cwd()) -> None:
92+
run_cmd(
93+
[
94+
"./mvnw",
95+
"install",
96+
# Skip test compilation too (not just execution): downstream needs only
97+
# our main artifacts, and our test sources target a newer release than
98+
# the compatibility JDK supports.
99+
"-Dmaven.test.skip=true",
100+
"-Dcoverage.skip=true",
101+
"-Dcheckstyle.skip=true",
102+
"-Dwarnings=-nowarn",
103+
],
104+
cwd=root_dir,
105+
)
106+
107+
108+
def run_maven_test(
109+
test_selector: Optional[str] = None,
110+
jmx_exporter_dir: Path = DEFAULT_JMX_EXPORTER_DIR,
111+
maven_modules: str = DEFAULT_MAVEN_MODULES,
112+
prom_version: Optional[str] = None,
113+
) -> None:
114+
if prom_version is None:
115+
prom_version = get_prom_version()
116+
cmd = [
117+
"./mvnw",
118+
"-B",
119+
"-pl",
120+
maven_modules,
121+
"-am",
122+
f"-Dprometheus.metrics.version={prom_version}",
123+
"-Djacoco.skip=true",
124+
]
125+
if test_selector:
126+
cmd.append(f"-Dtest={test_selector}")
127+
cmd.append("test")
128+
run_cmd(cmd, cwd=jmx_exporter_dir)

.mise/lib/micrometer_compat.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616
"MICROMETER_REPOSITORY", "micrometer-metrics/micrometer"
1717
)
1818
DEFAULT_MICROMETER_REMOTE = os.environ.get("MICROMETER_REMOTE", "origin")
19-
DEFAULT_MICROMETER_REF = os.environ.get("MICROMETER_REF", "main")
19+
DEFAULT_MICROMETER_REF = (
20+
os.environ.get("MICROMETER_REF")
21+
or os.environ.get("DEFAULT_MICROMETER_VERSION")
22+
or "main"
23+
)
2024
DEFAULT_INIT_SCRIPT = Path(
2125
os.environ.get("MICROMETER_INIT_SCRIPT", "/tmp/micrometer-prom-local.init.gradle")
2226
)
@@ -121,7 +125,10 @@ def install_local_artifacts(root_dir: Path = Path.cwd()) -> None:
121125
[
122126
"./mvnw",
123127
"install",
124-
"-DskipTests",
128+
# Skip test compilation too (not just execution): downstream needs only
129+
# our main artifacts, and our test sources target a newer release than
130+
# the compatibility JDK supports.
131+
"-Dmaven.test.skip=true",
125132
"-Dcoverage.skip=true",
126133
"-Dcheckstyle.skip=true",
127134
"-Dwarnings=-nowarn",
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env python3
2+
3+
# [MISE] description="Install local artifacts and check out a target JMX Exporter ref"
4+
# [MISE] alias="jmx-exporter:prepare"
5+
6+
import sys
7+
8+
9+
sys.path.insert(0, ".mise/lib")
10+
11+
12+
def main() -> int:
13+
from jmx_exporter_compat import install_local_artifacts, prepare_repo
14+
15+
install_local_artifacts()
16+
prepare_repo()
17+
return 0
18+
19+
20+
if __name__ == "__main__":
21+
raise SystemExit(main())

.mise/tasks/jmx-exporter/test.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env python3
2+
3+
# [MISE] description="Run JMX Exporter tests against a target ref"
4+
# [MISE] alias="jmx-exporter:test"
5+
6+
import sys
7+
8+
9+
sys.path.insert(0, ".mise/lib")
10+
11+
12+
def main() -> int:
13+
from jmx_exporter_compat import (
14+
install_local_artifacts,
15+
prepare_repo,
16+
run_maven_test,
17+
)
18+
19+
install_local_artifacts()
20+
prepare_repo()
21+
run_maven_test()
22+
return 0
23+
24+
25+
if __name__ == "__main__":
26+
raise SystemExit(main())

0 commit comments

Comments
 (0)