Skip to content

Commit b399f53

Browse files
committed
feat: track api-diff baseline via Renovate and store diffs in docs/apidiffs
Derive the api-diff baseline from the latest published release instead of a hardcoded version, and commit per-module diffs so API changes are visible in review. - Move the baseline to the <api.diff.baseline.version> pom property (the single source of truth) and let Renovate bump it: a custom regex manager tracks the latest published io.prometheus:prometheus-metrics-core on Maven Central, on the renovate/api-diff-baseline branch. - generate-api-diff-baseline.yml regenerates docs/apidiffs on that branch and pushes the result back (mirrors generate-protobuf.yml). - mise run api-diff now syncs japicmp reports into docs/apidiffs via .github/scripts/sync-api-diffs.sh (volatile preamble stripped so files only churn on real API changes); the api-diff workflow fails if they are stale. - Mark docs/apidiffs as generated so flint skips it. Closes #2170 Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
1 parent 62ce9dc commit b399f53

33 files changed

Lines changed: 2022 additions & 7 deletions

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
CHANGELOG.md linguist-generated
22
**/src/main/generated/** linguist-generated
3+
docs/apidiffs/** linguist-generated
34
docs/** linguist-documentation

.github/renovate-tracked-deps.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
"mise"
2727
]
2828
},
29+
".github/workflows/generate-api-diff-baseline.yml": {
30+
"regex": [
31+
"mise"
32+
]
33+
},
2934
".github/workflows/generate-protobuf.yml": {
3035
"regex": [
3136
"mise"
@@ -176,6 +181,11 @@
176181
"maven-wrapper": [
177182
"maven-wrapper"
178183
]
184+
},
185+
"pom.xml": {
186+
"regex": [
187+
"io.prometheus:prometheus-metrics-core"
188+
]
179189
}
180190
}
181191
}

.github/renovate.json5

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,20 @@
3737
matchDepNames: ["com.google.protobuf:protobuf-java", "protoc"],
3838
groupName: "protobuf",
3939
separateMajorMinor: false,
40+
},
41+
{
42+
description: "Isolate the api-diff baseline on renovate/api-diff-baseline so generate-api-diff-baseline can regenerate docs/apidiffs; merge manually after a close/reopen re-runs CI",
43+
matchFileNames: ["pom.xml"],
44+
matchPackageNames: ["io.prometheus:prometheus-metrics-core"],
45+
groupName: "api-diff-baseline",
46+
automerge: false,
47+
},
48+
{
49+
"description": "Flint autofix: align extractVersion for protoc",
50+
"extractVersion": "^(?<version>.+)\\.0\\.0$",
51+
"matchDepNames": [
52+
"protoc"
53+
]
4054
}
4155
],
4256
customManagers: [
@@ -48,5 +62,13 @@
4862
"# renovate: datasource=(?<datasource>[a-z-]+?)(?: depName=(?<depName>.+?))?(?: packageName=(?<packageName>.+?))?(?: versioning=(?<versioning>[a-z-]+?))?\\s.+?_VERSION\\s*=\\s*\"?(?<currentValue>[^@\"]+?)(?:@(?<currentDigest>sha256:[a-f0-9]+))?\"?\\s"
4963
]
5064
},
65+
{
66+
"customType": "regex",
67+
"description": "update the api-diff baseline to the latest published release",
68+
"managerFilePatterns": ["/^pom\\.xml$/"],
69+
"matchStrings": [
70+
"<!-- renovate: datasource=(?<datasource>[a-z-]+?) packageName=(?<packageName>.+?) -->\\s*<api\\.diff\\.baseline\\.version>(?<currentValue>[^<]+)</api\\.diff\\.baseline\\.version>"
71+
]
72+
},
5173
],
5274
}

.github/scripts/sync-api-diffs.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env bash
2+
# Refresh docs/apidiffs/ from the japicmp reports produced by `mvn verify -P api-diff`.
3+
#
4+
# Each StableApi module gets one committed <module>.diff describing how its
5+
# published API surface differs from the baseline release
6+
# (<api.diff.baseline.version> in pom.xml). Committing these makes every API
7+
# change visible in the pull request diff. The CI check fails when the
8+
# regenerated files differ from what is committed.
9+
#
10+
# The two-line japicmp preamble (the "Comparing ...SNAPSHOT.jar against
11+
# ...<baseline>.jar" line and the constant ignore-missing-classes warning) is
12+
# stripped so the files only churn on real API changes, not on every version or
13+
# snapshot bump.
14+
set -euo pipefail
15+
16+
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
17+
out_dir="$repo_root/docs/apidiffs"
18+
19+
shopt -s nullglob globstar
20+
21+
reports=("$repo_root"/**/target/japicmp/api-diff.diff)
22+
if [ "${#reports[@]}" -eq 0 ]; then
23+
echo "No japicmp reports found. Run 'mvn verify -P api-diff' first." >&2
24+
exit 1
25+
fi
26+
27+
rm -rf "$out_dir"
28+
mkdir -p "$out_dir"
29+
30+
for report in "${reports[@]}"; do
31+
# report path: <repo>/<module path>/target/japicmp/api-diff.diff
32+
module="$(basename "$(dirname "$(dirname "$(dirname "$report")")")")"
33+
grep -vE '^(Comparing source compatibility of|WARNING: You are using the option)' \
34+
"$report" >"$out_dir/$module.diff"
35+
done
36+
37+
echo "Wrote ${#reports[@]} API diff report(s) to docs/apidiffs/."

.github/workflows/api-diff.yml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ on:
1212
workflow_dispatch:
1313
inputs:
1414
baseline_version:
15-
description: Version to compare the PR artifacts against
15+
description: >-
16+
Override the baseline version to compare against.
17+
Defaults to <api.diff.baseline.version> in pom.xml.
1618
required: false
17-
default: "1.5.1"
19+
default: ""
1820

1921
permissions:
2022
contents: read
@@ -23,7 +25,9 @@ jobs:
2325
api-diff:
2426
runs-on: ubuntu-24.04
2527
env:
26-
API_DIFF_BASELINE_VERSION: ${{ inputs.baseline_version || '1.5.1' }}
28+
# Empty unless overridden via workflow_dispatch; the api-diff task then
29+
# falls back to <api.diff.baseline.version> in pom.xml.
30+
API_DIFF_BASELINE_VERSION: ${{ inputs.baseline_version }}
2731
BREAKING_API_CHANGE_ACCEPTED: >-
2832
${{ contains(github.event.pull_request.labels.*.name, 'breaking-api-change-accepted') }}
2933
@@ -42,6 +46,13 @@ jobs:
4246
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
4347
- name: Run japicmp API diff
4448
run: mise run api-diff
49+
- name: Check docs/apidiffs is up to date
50+
run: |
51+
if ! git diff --exit-code -- docs/apidiffs; then
52+
echo "::error::Published API surface changed but docs/apidiffs is stale."
53+
echo "Run 'mise run api-diff' locally and commit the updated docs/apidiffs."
54+
exit 1
55+
fi
4556
- name: Fail on incompatible published API changes
4657
run: |
4758
python3 - <<'PY'
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
name: Generate API Diff Baseline
3+
4+
# When Renovate bumps <api.diff.baseline.version> (on the renovate/api-diff-baseline
5+
# branch), regenerate docs/apidiffs against the new baseline and push the result
6+
# back onto the PR. Renovate only proposes versions already published to Maven
7+
# Central, so japicmp can always resolve the new baseline.
8+
#
9+
# Mirrors generate-protobuf.yml: a read-only `generate` job produces a patch
10+
# artifact and a privileged `publish` job pushes it back.
11+
12+
on:
13+
push:
14+
branches:
15+
- "renovate/api-diff-baseline"
16+
17+
permissions: {}
18+
19+
jobs:
20+
generate:
21+
runs-on: ubuntu-24.04
22+
permissions:
23+
contents: read # checkout + read-only `git fetch origin main` for the verify step
24+
steps:
25+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
26+
with:
27+
ref: ${{ github.ref }}
28+
persist-credentials: false
29+
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1
30+
with:
31+
version: v2026.5.18
32+
sha256: cfac593469d028d7ae5fe36e37bd7c59118b5238e92d8a876209578464f24a84
33+
- name: Cache local Maven repository
34+
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
35+
with:
36+
path: ~/.m2/repository
37+
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
38+
restore-keys: |
39+
${{ runner.os }}-maven-
40+
- name: Verify the baseline version was updated
41+
run: |
42+
git fetch origin main
43+
if ! git diff origin/main -- pom.xml | grep -q 'api.diff.baseline.version'; then
44+
echo "::error::api.diff.baseline.version not updated in pom.xml"
45+
exit 1
46+
fi
47+
- name: Regenerate docs/apidiffs
48+
run: mise run api-diff
49+
- name: Validate and export docs/apidiffs as a patch
50+
run: |
51+
UNEXPECTED=$(git diff --name-only | grep -v '^docs/apidiffs/' || true)
52+
if [[ -n "$UNEXPECTED" ]]; then
53+
echo "::error::Unexpected files changed:"
54+
echo "$UNEXPECTED"
55+
exit 1
56+
fi
57+
git diff > /tmp/api-diff-baseline.patch
58+
- name: Upload generated patch
59+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
60+
with:
61+
name: api-diff-baseline-patch
62+
path: /tmp/api-diff-baseline.patch
63+
retention-days: 5
64+
65+
publish:
66+
runs-on: ubuntu-24.04
67+
needs: generate
68+
permissions:
69+
contents: write # push regenerated docs/apidiffs back to the renovate branch
70+
steps:
71+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
72+
with:
73+
ref: ${{ github.ref }}
74+
# zizmor: ignore[artipacked] -- needs credentials to push
75+
persist-credentials: true
76+
- name: Download generated patch
77+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
78+
with:
79+
name: api-diff-baseline-patch
80+
path: /tmp/patch
81+
- name: Commit and push regenerated docs/apidiffs
82+
run: |
83+
PATCH=/tmp/patch/api-diff-baseline.patch
84+
if [[ ! -s "$PATCH" ]]; then
85+
echo "No regenerated changes to commit"
86+
exit 0
87+
fi
88+
git apply "$PATCH"
89+
# Note: GITHUB_TOKEN pushes don't trigger CI re-runs.
90+
# Close and reopen the PR to trigger CI after this commit.
91+
git config user.name "github-actions[bot]"
92+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
93+
git add docs/apidiffs
94+
git commit -m "chore: regenerate docs/apidiffs"
95+
git push

docs/apidiffs/prometheus-metrics-annotations.diff

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)