Skip to content

Commit 4d82098

Browse files
zeitlingerCopilot
andauthored
add Benchmark update & cleanup mise tasks (#1664)
Signed-off-by: Gregor Zeitlinger <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent c9cfa60 commit 4d82098

19 files changed

+574
-154
lines changed

.editorconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ max_line_length = 110
1616
[*.py]
1717
# checked by black
1818
indent_size = 4
19+
max_line_length = 120

.github/workflows/release.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ jobs:
2424
with:
2525
persist-credentials: false
2626

27-
- name: Set Up JDK
28-
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5
27+
- uses: jdx/mise-action@be3be2260bc02bc3fbf94c5e2fed8b7964baf074 # v3.4.0
2928
with:
30-
java-version: 21
31-
distribution: temurin
29+
version: v2025.11.1
30+
sha256: d4bec11aeb5b13180c596b70abf59716acda20131dbc3df8b9146f97cecf645c
31+
cache: false
3232

33-
- name: Build with Maven
34-
run: ./scripts/build-release.sh
33+
- name: Build release version
34+
run: mise run build-release
3535
env:
3636
TAG: ${{ github.ref_name }}
3737

.github/workflows/test-release-build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ jobs:
2727
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
2828
restore-keys: |
2929
${{ runner.os }}-maven-
30-
- name: Run the Maven verify phase
31-
run: ./scripts/build-release.sh
30+
- name: Build release version
31+
run: mise run build-release
3232
env:
33-
# don't ues the current snapshot version, to test a more realistic release
33+
# don't use the current snapshot version, to test a more realistic release
3434
TAG: ${{ github.run_number }}

.mise/tasks/build-release.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env bash
2+
3+
#MISE description="Build release package"
4+
#USAGE arg "<tag>" env="TAG" default="1.5.0-SNAPSHOT"
5+
6+
set -euo pipefail
7+
8+
# shellcheck disable=SC2154 # is set by mise
9+
VERSION=${usage_tag#v}
10+
11+
mise run set-version "$VERSION"
12+
mvn -B package -P 'release,!default' -Dmaven.test.skip=true

.mise/tasks/lint-bom.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/env python3
2+
3+
# [MISE] description="Make sure the BOM has all necessary modules"
4+
5+
import difflib
6+
import re
7+
import sys
8+
from fnmatch import fnmatch
9+
from pathlib import Path
10+
from typing import List
11+
12+
ROOT = Path(__file__).resolve().parents[2] # repo root (.. from .mise/tasks)
13+
IGNORE_DIRS = {"prometheus-metrics-parent"}
14+
MODULE_PREFIX = "prometheus-metrics"
15+
BOM_POM = ROOT / "prometheus-metrics-bom" / "pom.xml"
16+
17+
18+
def first_artifact_id(pom_file: Path) -> str:
19+
"""Return the second <artifactId> value from the given pom.xml (matches original script).
20+
21+
The original shell function greps all <artifactId> lines and returns the second one
22+
(head -n 2 | tail -n 1). We replicate that behavior exactly.
23+
"""
24+
if not pom_file.is_file():
25+
raise FileNotFoundError(f"File {pom_file} does not exist.")
26+
27+
text = pom_file.read_text(encoding="utf-8")
28+
matches = re.findall(r"<artifactId>\s*(.*?)\s*</artifactId>", text)
29+
if len(matches) < 2:
30+
return ""
31+
return matches[1].strip()
32+
33+
34+
def add_dir(dir_path: Path, want: List[str]):
35+
if not dir_path.is_dir():
36+
raise FileNotFoundError(f"Directory {dir_path} does not exist.")
37+
38+
if any(dir_path.name == ig for ig in IGNORE_DIRS):
39+
print(f"Skipping {dir_path}")
40+
return
41+
42+
pom = dir_path / "pom.xml"
43+
if not pom.is_file():
44+
raise FileNotFoundError(f"File {pom} does not exist.")
45+
46+
artifact_id = first_artifact_id(pom)
47+
if not artifact_id:
48+
raise RuntimeError(f"No artifactId found in {pom}")
49+
50+
print(f"Found artifactId '{artifact_id}' in {pom}")
51+
want.append(artifact_id)
52+
53+
54+
def collect_want(root: Path) -> List[str]:
55+
want: List[str] = []
56+
# top-level prometheus-metrics*
57+
for entry in sorted(root.iterdir()):
58+
if entry.is_dir() and fnmatch(entry.name, f"{MODULE_PREFIX}*"):
59+
add_dir(entry, want)
60+
61+
# prometheus-metrics-tracer/prometheus-metrics*
62+
tracer_dir = root / "prometheus-metrics-tracer"
63+
if tracer_dir.is_dir():
64+
for entry in sorted(tracer_dir.iterdir()):
65+
if entry.is_dir() and fnmatch(entry.name, f"{MODULE_PREFIX}*"):
66+
add_dir(entry, want)
67+
68+
# deduplicate and sort
69+
want_unique = sorted(set(want))
70+
return want_unique
71+
72+
73+
def collect_have(bom_pom: Path) -> List[str]:
74+
if not bom_pom.is_file():
75+
raise FileNotFoundError(f"BOM file {bom_pom} does not exist.")
76+
77+
text = bom_pom.read_text(encoding="utf-8")
78+
# find artifactId values that start with MODULE_PREFIX
79+
matches = re.findall(
80+
r"<artifactId>\s*(%s[^<\s]*)\s*</artifactId>" % re.escape(MODULE_PREFIX), text
81+
)
82+
return sorted(matches)
83+
84+
85+
def main() -> int:
86+
try:
87+
want = collect_want(ROOT)
88+
have = collect_have(BOM_POM)
89+
90+
want_text = "\n".join(want)
91+
have_text = "\n".join(have)
92+
93+
if want_text != have_text:
94+
print(
95+
"The BOM file prometheus-metrics-bom/bom.xml does not match the current directory contents."
96+
)
97+
print("Expected:")
98+
print(want_text)
99+
print("Found:")
100+
print(have_text)
101+
print()
102+
diff = difflib.unified_diff(
103+
have_text.splitlines(keepends=True),
104+
want_text.splitlines(keepends=True),
105+
fromfile="found",
106+
tofile="expected",
107+
)
108+
sys.stdout.writelines(diff)
109+
return 1
110+
else:
111+
print("BOM file is up to date.")
112+
return 0
113+
114+
except Exception as e:
115+
print(e, file=sys.stderr)
116+
return 1
117+
118+
119+
if __name__ == "__main__":
120+
sys.exit(main())

scripts/set-release-version-github-pages.sh renamed to .mise/tasks/set-release-version-github-pages.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/usr/bin/env bash
22

3+
#MISE description="Set release version in GitHub Pages quickstart.md"
4+
35
set -euox pipefail
46

57
version=$(git tag -l | grep 'v' | sort | tail -1 | sed 's/v//')

.mise/tasks/set-version.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env bash
2+
3+
#MISE description="Update version in all pom.xml files"
4+
#USAGE arg "<version>" help="new version"
5+
6+
set -euo pipefail
7+
8+
# replace all occurrences '<version>1.5.0-SNAPSHOT</version>' with
9+
# '<version>$usage_version</version>' in all pom.xml files in the current directory and
10+
# subdirectories
11+
12+
# shellcheck disable=SC2154 # is set by mise
13+
find . -name 'pom.xml' -exec \
14+
sed -i "s/<version>1.5.0-SNAPSHOT<\/version>/<version>$usage_version<\/version>/g" {} +
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#!/usr/bin/env bash
22

3-
set -euo pipefail
3+
#MISE description="Run GitHub Super Linter on the repository"
44

5-
pushd "$(dirname "$0")/.."
5+
set -euo pipefail
66

77
docker pull ghcr.io/super-linter/super-linter:latest
88

@@ -12,5 +12,3 @@ docker run --rm \
1212
--env-file ".github/super-linter.env" \
1313
-v "$(pwd)":/tmp/lint \
1414
ghcr.io/super-linter/super-linter:latest
15-
16-
popd
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import os
2+
import re
3+
import sys
4+
import tempfile
5+
import unittest
6+
7+
from update_benchmarks import update_pre_blocks_under_module
8+
9+
# Ensure the tasks directory is importable when running the test directly
10+
here = os.path.dirname(__file__)
11+
if here not in sys.path:
12+
sys.path.insert(0, here)
13+
14+
15+
class TestRunBenchmarksFiltering(unittest.TestCase):
16+
def setUp(self):
17+
# sample JMH table with mixed-class lines
18+
self.table = (
19+
"Benchmark Mode Cnt Score Error Units\n"
20+
"CounterBenchmark.codahaleIncNoLabels thrpt 57881.585 ops/s\n"
21+
"HistogramBenchmark.prometheusNative thrpt 2385.134 ops/s\n"
22+
"TextFormatUtilBenchmark.prometheusWriteToNull thrpt 885331.328 ops/s\n"
23+
"CounterBenchmark.prometheusInc thrpt 54090.469 ops/s\n"
24+
)
25+
26+
# create temp dir to act as module path
27+
self.tmpdir = tempfile.TemporaryDirectory()
28+
self.module_path = self.tmpdir.name
29+
30+
# Create three files with a javadoc <pre> block that contains mixed results
31+
self.files = {}
32+
javadoc_pre = (
33+
"/**\n"
34+
" * Example javadoc\n"
35+
" * <pre>\n"
36+
" * Benchmark Mode Cnt Score Error Units\n"
37+
" * CounterBenchmark.codahaleIncNoLabels thrpt 57881.585 ops/s\n"
38+
" * HistogramBenchmark.prometheusNative thrpt 2385.134 ops/s\n"
39+
" * TextFormatUtilBenchmark.prometheusWriteToNull thrpt 885331.328 ops/s\n"
40+
" * CounterBenchmark.prometheusInc thrpt 54090.469 ops/s\n"
41+
" * </pre>\n"
42+
" */\n"
43+
)
44+
45+
for cls in (
46+
"CounterBenchmark",
47+
"HistogramBenchmark",
48+
"TextFormatUtilBenchmark",
49+
):
50+
fname = os.path.join(self.module_path, f"{cls}.java")
51+
with open(fname, "w", encoding="utf-8") as f:
52+
f.write(javadoc_pre)
53+
f.write(f"public class {cls} {{}}\n")
54+
self.files[cls] = fname
55+
56+
def tearDown(self):
57+
self.tmpdir.cleanup()
58+
59+
def _read_pre_contents(self, path):
60+
with open(path, "r", encoding="utf-8") as f:
61+
content = f.read()
62+
m = re.search(r"<pre>\n([\s\S]*?)</pre>", content)
63+
return m.group(1) if m else ""
64+
65+
def test_update_only_inserts_matching_class_lines(self):
66+
updated = update_pre_blocks_under_module(self.module_path, self.table)
67+
# All three files should be updated
68+
self.assertEqual(
69+
set(os.path.basename(p) for p in updated),
70+
{
71+
os.path.basename(self.files["CounterBenchmark"]),
72+
os.path.basename(self.files["HistogramBenchmark"]),
73+
os.path.basename(self.files["TextFormatUtilBenchmark"]),
74+
},
75+
)
76+
77+
# Verify CounterBenchmark file contains only CounterBenchmark lines
78+
cb_pre = self._read_pre_contents(self.files["CounterBenchmark"])
79+
self.assertIn("CounterBenchmark.codahaleIncNoLabels", cb_pre)
80+
self.assertIn("CounterBenchmark.prometheusInc", cb_pre)
81+
self.assertNotIn("HistogramBenchmark.prometheusNative", cb_pre)
82+
self.assertNotIn("TextFormatUtilBenchmark.prometheusWriteToNull", cb_pre)
83+
84+
# Verify HistogramBenchmark contains only its line
85+
hb_pre = self._read_pre_contents(self.files["HistogramBenchmark"])
86+
self.assertIn("HistogramBenchmark.prometheusNative", hb_pre)
87+
self.assertNotIn("CounterBenchmark.codahaleIncNoLabels", hb_pre)
88+
self.assertNotIn("TextFormatUtilBenchmark.prometheusWriteToNull", hb_pre)
89+
90+
# Verify TextFormatUtilBenchmark contains only its line
91+
tf_pre = self._read_pre_contents(self.files["TextFormatUtilBenchmark"])
92+
self.assertIn("TextFormatUtilBenchmark.prometheusWriteToNull", tf_pre)
93+
self.assertNotIn("CounterBenchmark.prometheusInc", tf_pre)
94+
self.assertNotIn("HistogramBenchmark.prometheusNative", tf_pre)
95+
96+
97+
if __name__ == "__main__":
98+
unittest.main()

0 commit comments

Comments
 (0)