name: Public API Diff
on:
pull_request:
permissions:
pull-requests: write
jobs:
public-api-diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Install Rust nightly
uses: dtolnay/rust-toolchain@nightly
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- uses: taiki-e/cache-cargo-install-action@v3
with:
tool: cargo-public-api
- name: Generate API diff
env:
BASE_REF: ${{ github.event.pull_request.base.ref }}
run: |
set -euo pipefail
BASE="origin/${BASE_REF}"
mkdir -p /tmp/api
echo "::group::API at HEAD"
cargo public-api --simplified 2>/dev/null | sort -u > /tmp/api/head.txt || true
echo "::endgroup::"
echo "::group::API at ${BASE}"
git worktree add /tmp/base "$BASE" --detach
( cd /tmp/base && cargo public-api --simplified 2>/dev/null | sort -u ) > /tmp/api/base.txt || true
git worktree remove /tmp/base --force
echo "::endgroup::"
{
echo '<!-- public-api-diff -->'
echo '## Public API Changes'
echo ''
diff_output=$(
git diff --no-index -U0 --word-diff /tmp/api/base.txt /tmp/api/head.txt 2>/dev/null \
| grep -v -E '^(diff --git |index |--- |\+\+\+ |@@)' \
| sed 's/&/\&/g; s/</\</g; s/>/\>/g' \
| sed 's/{+/<ins>/g; s/+}/<\/ins>/g; s/\[-/<del>/g; s/-\]/<\/del>/g'
) || true
if [ -n "$diff_output" ]; then
echo '<pre>'
echo "$diff_output"
echo '</pre>'
else
echo 'No public API changes.'
fi
} > /tmp/api-diff-comment.md
- name: Find existing comment
uses: peter-evans/find-comment@v4
id: fc
with:
issue-number: ${{ github.event.pull_request.number }}
body-includes: '<!-- public-api-diff -->'
- name: Create or update comment
uses: peter-evans/create-or-update-comment@v5
with:
issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.fc.outputs.comment-id }}
body-path: /tmp/api-diff-comment.md
edit-mode: replace