Skip to content

Commit b29ec6f

Browse files
PedramNavidclaude
andauthored
Add notebook diff workflow for PR comments (anthropics#277)
* feat: add GitHub Action to post notebook diffs in PR comments - Automatically detects changed .ipynb files in PRs - Generates nbdime diffs for each changed notebook - Posts formatted comment with collapsible diff sections - Handles multiple notebooks and new files gracefully 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix: use --system flag for uv pip install in workflow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix: use uvx to run nbdiff without installation Using uvx --from nbdime nbdiff creates an ephemeral environment and avoids issues with system Python being externally managed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * feat: add nbdiff flags to ignore non-content changes Adds flags to focus diff on actual content: - --ignore-attachments: Skip attachment changes - --ignore-metadata: Skip metadata changes - --ignore-identifiers: Skip cell ID changes - --ignore-details: Skip execution counts, etc. This makes the diff more readable and focused on code/markdown changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix: use correct nbdiff ignore flag syntax Use short flags (-A -M -I -D) instead of long form flags that don't exist. - -A: ignore attachments - -M: ignore metadata - -I: ignore identifiers (cell IDs) - -D: ignore details (execution counts, etc.) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Claude <[email protected]>
1 parent fe63970 commit b29ec6f

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
name: Notebook Diff Comment
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- '**/*.ipynb'
7+
8+
permissions:
9+
contents: read
10+
pull-requests: write
11+
12+
jobs:
13+
post-notebook-diff:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0 # Need full history to diff against base
20+
21+
- name: Install uv
22+
uses: astral-sh/setup-uv@v4
23+
with:
24+
enable-cache: true
25+
26+
- name: Set up Python 3.11
27+
run: uv python install 3.11
28+
29+
- name: Get changed notebooks
30+
id: changed-notebooks
31+
run: |
32+
# Get the base branch (usually main)
33+
BASE_SHA=${{ github.event.pull_request.base.sha }}
34+
HEAD_SHA=${{ github.event.pull_request.head.sha }}
35+
36+
# Find all changed .ipynb files
37+
CHANGED_NOTEBOOKS=$(git diff --name-only $BASE_SHA $HEAD_SHA | grep '\.ipynb$' || true)
38+
39+
if [ -z "$CHANGED_NOTEBOOKS" ]; then
40+
echo "No notebooks changed"
41+
echo "has_changes=false" >> $GITHUB_OUTPUT
42+
else
43+
echo "Changed notebooks:"
44+
echo "$CHANGED_NOTEBOOKS"
45+
echo "has_changes=true" >> $GITHUB_OUTPUT
46+
# Save to file for next step
47+
echo "$CHANGED_NOTEBOOKS" > changed_notebooks.txt
48+
fi
49+
50+
- name: Generate notebook diffs
51+
if: steps.changed-notebooks.outputs.has_changes == 'true'
52+
run: |
53+
BASE_SHA=${{ github.event.pull_request.base.sha }}
54+
HEAD_SHA=${{ github.event.pull_request.head.sha }}
55+
56+
# Create output file
57+
echo "# Notebook Changes" > diff_comment.md
58+
echo "" >> diff_comment.md
59+
echo "This PR modifies the following notebooks:" >> diff_comment.md
60+
echo "" >> diff_comment.md
61+
62+
# Process each changed notebook
63+
while IFS= read -r notebook; do
64+
if [ -z "$notebook" ]; then
65+
continue
66+
fi
67+
68+
echo "Processing: $notebook"
69+
echo "## 📓 \`$notebook\`" >> diff_comment.md
70+
echo "" >> diff_comment.md
71+
echo "<details>" >> diff_comment.md
72+
echo "<summary>View diff</summary>" >> diff_comment.md
73+
echo "" >> diff_comment.md
74+
echo '```diff' >> diff_comment.md
75+
76+
# Generate diff (suppress errors if file doesn't exist in base)
77+
# Ignore metadata, attachments, IDs, and other non-content changes
78+
uvx --from nbdime nbdiff --no-color -A -M -I -D \
79+
$BASE_SHA $HEAD_SHA "$notebook" 2>/dev/null >> diff_comment.md || echo "New file" >> diff_comment.md
80+
81+
echo '```' >> diff_comment.md
82+
echo "" >> diff_comment.md
83+
echo "</details>" >> diff_comment.md
84+
echo "" >> diff_comment.md
85+
done < changed_notebooks.txt
86+
87+
echo "---" >> diff_comment.md
88+
echo "" >> diff_comment.md
89+
echo "*Generated by nbdime*" >> diff_comment.md
90+
91+
- name: Post comment to PR
92+
if: steps.changed-notebooks.outputs.has_changes == 'true'
93+
env:
94+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
95+
run: |
96+
# Post the comment
97+
gh pr comment ${{ github.event.pull_request.number }} --body-file diff_comment.md

0 commit comments

Comments
 (0)