Skip to content

Commit ea28bfe

Browse files
halotukozakclaude
andcommitted
mima(-mill).yml: compare PRs against main, not the last release
Comparing every PR against the last release tag meant a break merged in PR n stayed baked into main, so every unrelated PR n+1, n+2, ... kept getting relabeled needs-major until the next release. Build the baseline from main's tip (the merge commit's first parent) instead, so only the PR that actually introduces a new incompatibility gets labeled. Push events to main still fall back to the last release for the job summary, since there's no PR to label there. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AtPhpS4Ru3mHKuwGFDemwd
1 parent 6c55a1a commit ea28bfe

2 files changed

Lines changed: 67 additions & 33 deletions

File tree

shared/mima-mill.yml

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ permissions:
1414
# Never fails the build — instead, on a PR, it manages a `needs-major` label
1515
# when there's a real *backward* binary incompatibility, and removes it
1616
# again once a later push is compatible.
17+
#
18+
# On a PR, the baseline is the current `main` tip (the merge commit's first
19+
# parent), not the last release — otherwise a break introduced by PR n stays
20+
# baked into `main` and every unrelated PR n+1, n+2, ... would keep getting
21+
# relabeled until the next release, even though they changed nothing binary.
22+
# On a plain push, there's no PR to label, so the report falls back to
23+
# comparing against the last release for the summary.
1724
jobs:
1825
mima:
1926
name: MiMa (binary)
@@ -30,29 +37,39 @@ jobs:
3037
- name: Setup coursier cache
3138
uses: coursier/cache-action@v8.1
3239
- uses: VirtusLab/scala-cli-setup@v1
33-
- name: Check binary compatibility against the last release
40+
- name: Check binary compatibility
3441
id: mima
3542
run: |
3643
set -euo pipefail
3744
38-
base_tag=$(git tag -l 'v*' --sort=-v:refname | head -1)
39-
if [ -z "$base_tag" ]; then
40-
echo "No release tag yet — nothing to compare against." >> "$GITHUB_STEP_SUMMARY"
41-
echo "broken=false" >> "$GITHUB_OUTPUT"
42-
exit 0
43-
fi
44-
base_version=${base_tag#v}
4545
org=com.halotukozak
4646
name=${{ github.event.repository.name }}
47-
echo "Baseline: $org:${name}_3:$base_version"
4847
4948
new_jar=$(./mill --disable-ticker show jvm.jar | tail -1 | sed -E 's/^"[a-z]*ref:v[0-9]+:[0-9a-f]+://; s/"$//')
50-
51-
printf '' > "$RUNNER_TEMP/empty.scala"
52-
old_cp=$(scala-cli --power compile "$RUNNER_TEMP/empty.scala" --dependency "$org::$name:$base_version" --print-class-path | tail -1)
53-
old_jar=$(printf '%s' "$old_cp" | tr ':' '\n' | grep "/${name}_3/$base_version/")
5449
mill_cp=$(./mill --disable-ticker show jvm.compileClasspath | jq -r '.[]' | sed -E 's/^[a-z]*ref:v[0-9]+:[0-9a-f]+://')
55-
shared_cp="$old_cp:$mill_cp"
50+
51+
if [ "${{ github.event_name }}" = "pull_request" ]; then
52+
base_sha=$(git rev-parse HEAD^1)
53+
baseline_label="main@${base_sha:0:7}"
54+
echo "Baseline: $baseline_label (does this PR itself introduce a new binary incompatibility?)"
55+
git worktree add --detach --quiet "$RUNNER_TEMP/old-src" "$base_sha"
56+
old_jar=$(cd "$RUNNER_TEMP/old-src" && ./mill --disable-ticker show jvm.jar | tail -1 | sed -E 's/^"[a-z]*ref:v[0-9]+:[0-9a-f]+://; s/"$//')
57+
shared_cp="$mill_cp"
58+
else
59+
base_tag=$(git tag -l 'v*' --sort=-v:refname | head -1)
60+
if [ -z "$base_tag" ]; then
61+
echo "No release tag yet — nothing to compare against." >> "$GITHUB_STEP_SUMMARY"
62+
echo "broken=false" >> "$GITHUB_OUTPUT"
63+
exit 0
64+
fi
65+
base_version=${base_tag#v}
66+
baseline_label="$base_version"
67+
echo "Baseline: $org:${name}_3:$base_version"
68+
printf '' > "$RUNNER_TEMP/empty.scala"
69+
old_cp=$(scala-cli --power compile "$RUNNER_TEMP/empty.scala" --dependency "$org::$name:$base_version" --print-class-path | tail -1)
70+
old_jar=$(printf '%s' "$old_cp" | tr ':' '\n' | grep "/${name}_3/$base_version/")
71+
shared_cp="$old_cp:$mill_cp"
72+
fi
5673
5774
set +e
5875
scala-cli run .mima/bin-compat-check.scala -- "$old_jar" "$new_jar" "$shared_cp" | tee "$RUNNER_TEMP/mima-out.txt"
@@ -61,15 +78,15 @@ jobs:
6178
6279
if [ $status -ne 0 ]; then
6380
{
64-
echo "### MiMa found binary incompatibilities vs \`$base_version\`"
81+
echo "### MiMa found binary incompatibilities vs \`$baseline_label\`"
6582
echo '```'
6683
cat "$RUNNER_TEMP/mima-out.txt"
6784
echo '```'
6885
} >> "$GITHUB_STEP_SUMMARY"
69-
echo "::warning title=Binary compatibility::MiMa found incompatibilities vs $base_version — see the job summary"
86+
echo "::warning title=Binary compatibility::MiMa found incompatibilities vs $baseline_label — see the job summary"
7087
echo "broken=true" >> "$GITHUB_OUTPUT"
7188
else
72-
echo "Binary compatible with \`$base_version\`." >> "$GITHUB_STEP_SUMMARY"
89+
echo "Binary compatible with \`$baseline_label\`." >> "$GITHUB_STEP_SUMMARY"
7390
echo "broken=false" >> "$GITHUB_OUTPUT"
7491
fi
7592

shared/mima.yml

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ permissions:
1616
# trackable without blocking. The label is removed again once a later push
1717
# to the same PR is compatible.
1818
#
19+
# On a PR, the baseline is the current `main` tip (the merge commit's first
20+
# parent), not the last release — otherwise a break introduced by PR n stays
21+
# baked into `main` and every unrelated PR n+1, n+2, ... would keep getting
22+
# relabeled until the next release, even though they changed nothing binary.
23+
# On a plain push (e.g. a merge to main), there's no PR to label, so the
24+
# report falls back to comparing against the last release for the summary.
25+
#
1926
# There's no `needs-minor` (source/TASTy-compat-only breaks) yet: TASTy-MiMa
2027
# can't read Scala 3.9's TASTy format yet (tasty-mima lags the compiler).
2128
# Add it here once that's unblocked.
@@ -30,45 +37,55 @@ jobs:
3037
- name: Setup coursier cache
3138
uses: coursier/cache-action@v8.1
3239
- uses: VirtusLab/scala-cli-setup@v1
33-
- name: Check binary compatibility against the last release
40+
- name: Check binary compatibility
3441
id: mima
3542
run: |
3643
set -euo pipefail
3744
38-
base_tag=$(git tag -l 'v*' --sort=-v:refname | head -1)
39-
if [ -z "$base_tag" ]; then
40-
echo "No release tag yet — nothing to compare against." >> "$GITHUB_STEP_SUMMARY"
41-
echo "broken=false" >> "$GITHUB_OUTPUT"
42-
exit 0
43-
fi
44-
base_version=${base_tag#v}
4545
org=$(grep -oP '(?<=using publish.organization ).*' project.scala | tr -d '"')
4646
name=$(grep -oP '(?<=using publish.name ).*' project.scala | tr -d '"')
47-
echo "Baseline: $org:${name}_3:$base_version"
4847
4948
scala-cli --power package . --library -o "$RUNNER_TEMP/new.jar" --force
50-
51-
printf '' > "$RUNNER_TEMP/empty.scala"
52-
old_cp=$(scala-cli --power compile "$RUNNER_TEMP/empty.scala" --dependency "$org::$name:$base_version" --print-class-path | tail -1)
53-
old_jar=$(printf '%s' "$old_cp" | tr ':' '\n' | grep "/${name}_3/$base_version/")
5449
shared_cp=$(scala-cli --power compile . --print-class-path | tail -1)
5550
51+
if [ "${{ github.event_name }}" = "pull_request" ]; then
52+
base_sha=$(git rev-parse HEAD^1)
53+
baseline_label="main@${base_sha:0:7}"
54+
echo "Baseline: $baseline_label (does this PR itself introduce a new binary incompatibility?)"
55+
git worktree add --detach --quiet "$RUNNER_TEMP/old-src" "$base_sha"
56+
scala-cli --power package "$RUNNER_TEMP/old-src" --library -o "$RUNNER_TEMP/old.jar" --force
57+
old_jar="$RUNNER_TEMP/old.jar"
58+
else
59+
base_tag=$(git tag -l 'v*' --sort=-v:refname | head -1)
60+
if [ -z "$base_tag" ]; then
61+
echo "No release tag yet — nothing to compare against." >> "$GITHUB_STEP_SUMMARY"
62+
echo "broken=false" >> "$GITHUB_OUTPUT"
63+
exit 0
64+
fi
65+
base_version=${base_tag#v}
66+
baseline_label="$base_version"
67+
echo "Baseline: $org:${name}_3:$base_version"
68+
printf '' > "$RUNNER_TEMP/empty.scala"
69+
old_cp=$(scala-cli --power compile "$RUNNER_TEMP/empty.scala" --dependency "$org::$name:$base_version" --print-class-path | tail -1)
70+
old_jar=$(printf '%s' "$old_cp" | tr ':' '\n' | grep "/${name}_3/$base_version/")
71+
fi
72+
5673
set +e
5774
scala-cli run .mima/bin-compat-check.scala -- "$old_jar" "$RUNNER_TEMP/new.jar" "$shared_cp" | tee "$RUNNER_TEMP/mima-out.txt"
5875
status=$?
5976
set -e
6077
6178
if [ $status -ne 0 ]; then
6279
{
63-
echo "### MiMa found binary incompatibilities vs \`$base_version\`"
80+
echo "### MiMa found binary incompatibilities vs \`$baseline_label\`"
6481
echo '```'
6582
cat "$RUNNER_TEMP/mima-out.txt"
6683
echo '```'
6784
} >> "$GITHUB_STEP_SUMMARY"
68-
echo "::warning title=Binary compatibility::MiMa found incompatibilities vs $base_version — see the job summary"
85+
echo "::warning title=Binary compatibility::MiMa found incompatibilities vs $baseline_label — see the job summary"
6986
echo "broken=true" >> "$GITHUB_OUTPUT"
7087
else
71-
echo "Binary compatible with \`$base_version\`." >> "$GITHUB_STEP_SUMMARY"
88+
echo "Binary compatible with \`$baseline_label\`." >> "$GITHUB_STEP_SUMMARY"
7289
echo "broken=false" >> "$GITHUB_OUTPUT"
7390
fi
7491

0 commit comments

Comments
 (0)