Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/renovate-tracked-deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
"mise"
]
},
".github/workflows/micrometer-compatibility.yml": {
"regex": [
"mise"
]
},
".github/workflows/lint.yml": {
"regex": [
"mise"
Expand Down Expand Up @@ -125,6 +130,7 @@
"hugo",
"java",
"lychee",
"maven",
"node",
"npm:renovate",
"protoc",
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 Opt-In Compatibility

on:
pull_request:
workflow_dispatch:
inputs:
micrometer-repository:
description: Micrometer repository to test, in owner/name form
required: false
default: zeitlinger/micrometer
micrometer-ref:
description: Micrometer branch, tag, or commit to test
required: false
default: feat/prometheus-client-opt-in

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.5.5
sha256: 3aaab5c05a8a94a93b42b4f581779bbd5c44ddb251e7f3639fc671ec5c6aab8a
- 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
149 changes: 149 additions & 0 deletions .mise/lib/micrometer_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#!/usr/bin/env python3

from __future__ import annotations

import os
import subprocess
import xml.etree.ElementTree as ET
from pathlib import Path
from typing import Optional


DEFAULT_MICROMETER_DIR = Path(
os.environ.get("MICROMETER_DIR", "/tmp/micrometer-compat")
)
DEFAULT_MICROMETER_REPOSITORY = os.environ.get(
"MICROMETER_REPOSITORY", "zeitlinger/micrometer"
)
DEFAULT_MICROMETER_REMOTE = os.environ.get("MICROMETER_REMOTE", "origin")
DEFAULT_MICROMETER_REF = os.environ.get(
"MICROMETER_REF", "feat/prometheus-client-opt-in"
)
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())
1 change: 1 addition & 0 deletions mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"go:github.com/grafana/oats" = "0.6.1"
hugo = "0.161.1"
java = "temurin-25.0.3+9.0.LTS"
maven = "3.9.15"
node = "24.15.0"
protoc = "34.1"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ public Builder dataPoint(CounterDataPointSnapshot dataPoint) {
return this;
}

@Override
protected MetricMetadata buildMetadata() {
if (name == null) {
throw new IllegalArgumentException("Missing required field: name is null");
}
return MetricMetadataSupport.counterMetadata(name, help, unit);
}

@Override
public CounterSnapshot build() {
return new CounterSnapshot(buildMetadata(), dataPoints);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ public Builder unit(@Nullable Unit unit) {
throw new IllegalArgumentException("Info metric cannot have a unit.");
}

@Override
protected MetricMetadata buildMetadata() {
if (name == null) {
throw new IllegalArgumentException("Missing required field: name is null");
}
return MetricMetadataSupport.infoMetadata(name, help);
}

@Override
public InfoSnapshot build() {
return new InfoSnapshot(buildMetadata(), dataPoints);
Expand Down
Loading