🔄 synced file(s) with halotukozak-com/.github #64
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Binary compatibility | |
| on: | |
| push: | |
| branches: [ main ] | |
| pull_request: | |
| branches: [ main ] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| # Report-only: pre-1.0, and the check itself is a prototype. It never fails | |
| # the build — instead, on a PR, it manages a `needs-major` label (binary | |
| # incompatibility means an eventual major bump) so the break is visible and | |
| # trackable without blocking. The label is removed again once a later push | |
| # to the same PR is compatible. | |
| # | |
| # On a PR, the baseline is the current `main` tip (the merge commit's first | |
| # parent), not the last release — otherwise a break introduced by PR n stays | |
| # baked into `main` and every unrelated PR n+1, n+2, ... would keep getting | |
| # relabeled until the next release, even though they changed nothing binary. | |
| # On a plain push (e.g. a merge to main), there's no PR to label, so the | |
| # report falls back to comparing against the last release for the summary. | |
| # | |
| # There's no `needs-minor` (source/TASTy-compat-only breaks) yet: TASTy-MiMa | |
| # can't read Scala 3.9's TASTy format yet (tasty-mima lags the compiler). | |
| # Add it here once that's unblocked. | |
| jobs: | |
| mima: | |
| name: MiMa (binary) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup coursier cache | |
| uses: coursier/cache-action@v8.1 | |
| - uses: VirtusLab/scala-cli-setup@v1 | |
| - name: Check binary compatibility | |
| id: mima | |
| run: | | |
| set -euo pipefail | |
| org=$(grep -oP '(?<=using publish.organization ).*' project.scala | tr -d '"') | |
| name=$(grep -oP '(?<=using publish.name ).*' project.scala | tr -d '"') | |
| scala-cli --power package . --exclude benchmark --library -o "$RUNNER_TEMP/new.jar" --force | |
| shared_cp=$(scala-cli --power compile . --exclude benchmark --print-class-path | tail -1) | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| base_sha=$(git rev-parse HEAD^1) | |
| baseline_label="main@${base_sha:0:7}" | |
| echo "Baseline: $baseline_label (does this PR itself introduce a new binary incompatibility?)" | |
| git worktree add --detach --quiet "$RUNNER_TEMP/old-src" "$base_sha" | |
| scala-cli --power package "$RUNNER_TEMP/old-src" --exclude benchmark --library -o "$RUNNER_TEMP/old.jar" --force | |
| old_jar="$RUNNER_TEMP/old.jar" | |
| else | |
| base_tag=$(git tag -l 'v*' --sort=-v:refname | head -1) | |
| if [ -z "$base_tag" ]; then | |
| echo "No release tag yet — nothing to compare against." >> "$GITHUB_STEP_SUMMARY" | |
| echo "broken=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| base_version=${base_tag#v} | |
| baseline_label="$base_version" | |
| echo "Baseline: $org:${name}_3:$base_version" | |
| printf '' > "$RUNNER_TEMP/empty.scala" | |
| old_cp=$(scala-cli --power compile "$RUNNER_TEMP/empty.scala" --dependency "$org::$name:$base_version" --print-class-path | tail -1) | |
| old_jar=$(printf '%s' "$old_cp" | tr ':' '\n' | grep "/${name}_3/$base_version/") | |
| fi | |
| echo "baseline=$baseline_label" >> "$GITHUB_OUTPUT" | |
| set +e | |
| scala-cli run .mima/bin-compat-check.scala -- "$old_jar" "$RUNNER_TEMP/new.jar" "$shared_cp" | tee "$RUNNER_TEMP/mima-out.txt" | |
| status=$? | |
| set -e | |
| if [ $status -ne 0 ]; then | |
| { | |
| echo "### MiMa found binary incompatibilities vs \`$baseline_label\`" | |
| echo '```' | |
| cat "$RUNNER_TEMP/mima-out.txt" | |
| echo '```' | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| echo "::warning title=Binary compatibility::MiMa found incompatibilities vs $baseline_label — see the job summary" | |
| echo "broken=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "Binary compatible with \`$baseline_label\`." >> "$GITHUB_STEP_SUMMARY" | |
| echo "broken=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Label needs-major on binary incompatibility | |
| if: github.event_name == 'pull_request' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| if [ "${{ steps.mima.outputs.broken }}" = "true" ]; then | |
| gh label create needs-major --repo "${{ github.repository }}" \ | |
| --color B60205 --description "Binary-incompatible change — needs a major version bump" \ | |
| --force >/dev/null | |
| gh pr edit "${{ github.event.pull_request.number }}" --repo "${{ github.repository }}" \ | |
| --add-label needs-major | |
| else | |
| gh pr edit "${{ github.event.pull_request.number }}" --repo "${{ github.repository }}" \ | |
| --remove-label needs-major || true | |
| fi | |
| - name: Post sticky comment with binary compatibility report | |
| if: github.event_name == 'pull_request' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| marker='<!-- mima-report -->' | |
| baseline='${{ steps.mima.outputs.baseline }}' | |
| repo='${{ github.repository }}' | |
| pr=${{ github.event.pull_request.number }} | |
| comment_id=$(gh api "repos/$repo/issues/$pr/comments" --paginate \ | |
| --jq ".[] | select(.body | startswith(\"$marker\")) | .id" | tail -1) | |
| if [ "${{ steps.mima.outputs.broken }}" = "true" ]; then | |
| { | |
| echo "$marker" | |
| echo "### ⚠️ MiMa: binary incompatibility vs \`$baseline\`" | |
| echo | |
| echo "This PR breaks binary compatibility — it will need a major version bump." | |
| echo | |
| echo '<details><summary>Details</summary>' | |
| echo | |
| echo '```' | |
| cat "$RUNNER_TEMP/mima-out.txt" | |
| echo '```' | |
| echo | |
| echo '</details>' | |
| } > "$RUNNER_TEMP/mima-comment.md" | |
| if [ -n "$comment_id" ]; then | |
| gh api --method PATCH "repos/$repo/issues/comments/$comment_id" -F body=@"$RUNNER_TEMP/mima-comment.md" >/dev/null | |
| else | |
| gh api --method POST "repos/$repo/issues/$pr/comments" -F body=@"$RUNNER_TEMP/mima-comment.md" >/dev/null | |
| fi | |
| elif [ -n "$comment_id" ]; then | |
| { | |
| echo "$marker" | |
| echo "### ✅ MiMa: binary compatible with \`$baseline\`" | |
| echo | |
| echo "A later push resolved the binary incompatibility flagged above." | |
| } > "$RUNNER_TEMP/mima-comment.md" | |
| gh api --method PATCH "repos/$repo/issues/comments/$comment_id" -F body=@"$RUNNER_TEMP/mima-comment.md" >/dev/null | |
| fi |