From 031dba3a9b8fe231c8570280b70c6f0ce81f18ad Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 Aug 2025 04:38:49 +0000
Subject: [PATCH 01/11] Initial plan
From ee9960433e1a6c53e7cfc0eab63e97b9ef69fc7d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 Aug 2025 04:46:41 +0000
Subject: [PATCH 02/11] Add PR mode functionality to check-warnings action
Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com>
---
.github/actions/check-warnings/README.md | 43 ++++++
.github/actions/check-warnings/action.yml | 135 ++++++++++++++++--
.github/workflows/test-warning-check.yml | 82 ++++++++++-
test/check-warnings/lecture-clean.html | 16 +++
test/check-warnings/lecture-clean.md | 3 +
.../check-warnings/lecture-with-warnings.html | 17 +++
test/check-warnings/lecture-with-warnings.md | 3 +
test/check-warnings/test-pr-mode.sh | 121 ++++++++++++++++
8 files changed, 408 insertions(+), 12 deletions(-)
create mode 100644 test/check-warnings/lecture-clean.html
create mode 100644 test/check-warnings/lecture-clean.md
create mode 100644 test/check-warnings/lecture-with-warnings.html
create mode 100644 test/check-warnings/lecture-with-warnings.md
create mode 100755 test/check-warnings/test-pr-mode.sh
diff --git a/.github/actions/check-warnings/README.md b/.github/actions/check-warnings/README.md
index 1dc76e2..7b4cc34 100644
--- a/.github/actions/check-warnings/README.md
+++ b/.github/actions/check-warnings/README.md
@@ -25,6 +25,26 @@ This GitHub Action scans HTML files for Python warnings and optionally fails the
uses: QuantEcon/meta/.github/actions/check-warnings@main
```
+### Advanced Usage with PR Mode
+
+The action supports a special "PR mode" that only checks HTML files corresponding to changed `.md` files in a pull request. This is particularly useful for large documentation repositories where you only want to check warnings in lectures that are being modified:
+
+```yaml
+- name: Check for Python warnings in changed lectures only
+ uses: QuantEcon/meta/.github/actions/check-warnings@main
+ with:
+ html-path: './_build/html'
+ pr-mode: 'true'
+ fail-on-warning: 'true'
+```
+
+When `pr-mode` is enabled, the action will:
+1. Detect which `.md` files have changed in the current PR or push
+2. Map each changed `.md` file to its corresponding `.html` file in the build directory
+3. Only scan those specific HTML files for warnings
+
+This significantly reduces noise from warnings in unrelated lectures and helps focus on the changes being made.
+
### Advanced Usage with PR Comments
```yaml
@@ -211,6 +231,28 @@ You can enable both issue creation and artifact generation simultaneously:
This action specifically searches for Python warnings within HTML elements that have `cell_output` in their class attribute. This approach prevents false positives that would occur if warnings like "FutureWarning" or "DeprecationWarning" are mentioned in the text content of documentation pages.
+### PR Mode
+
+When `pr-mode` is enabled, the action performs these additional steps:
+
+1. **Detect Changed Files**: Uses git to identify which `.md` files have changed in the current PR or push
+2. **Map to HTML Files**: For each changed `.md` file, finds the corresponding `.html` file in the build directory using these strategies:
+ - Direct mapping: `lecture.md` → `build/html/lecture.html`
+ - Path-preserving mapping: `path/to/lecture.md` → `build/html/path/to/lecture.html`
+ - Recursive search: Finds `lecture.html` anywhere in the build directory
+3. **Focused Scanning**: Only scans the mapped HTML files instead of all HTML files in the directory
+
+This is particularly valuable for large documentation repositories where:
+- You have many lecture files but only modify a few in each PR
+- You want to avoid reporting warnings from unrelated lectures
+- You want faster CI runs by scanning fewer files
+
+### File Mapping Examples
+
+- `introduction.md` → `_build/html/introduction.html`
+- `lectures/chapter1.md` → `_build/html/lectures/chapter1.html`
+- `advanced/optimization.md` → `_build/html/advanced/optimization.html`
+
### Example HTML Structure
The action will detect warnings in this structure:
@@ -259,6 +301,7 @@ If you're only using the basic warning check functionality, only `contents: read
| `create-artifact` | Whether to create a workflow artifact with the warning report | No | `false` |
| `artifact-name` | Name for the workflow artifact containing the warning report | No | `warning-report` |
| `notify` | GitHub username(s) to assign to the created issue (comma-separated for multiple users) | No | `` |
+| `pr-mode` | When enabled, only check HTML files corresponding to changed .md files in the PR (requires git repository context) | No | `false` |
## Outputs
diff --git a/.github/actions/check-warnings/action.yml b/.github/actions/check-warnings/action.yml
index e97b4c4..a58f7fd 100755
--- a/.github/actions/check-warnings/action.yml
+++ b/.github/actions/check-warnings/action.yml
@@ -39,6 +39,10 @@ inputs:
description: 'GitHub username(s) to assign to the created issue (comma-separated for multiple users)'
required: false
default: ''
+ pr-mode:
+ description: 'When enabled, only check HTML files corresponding to changed .md files in the PR (requires git repository context)'
+ required: false
+ default: 'false'
outputs:
warnings-found:
@@ -69,9 +73,11 @@ runs:
WARNINGS="${{ inputs.warnings }}"
EXCLUDE_WARNINGS="${{ inputs.exclude-warning }}"
FAIL_ON_WARNING="${{ inputs.fail-on-warning }}"
+ PR_MODE="${{ inputs.pr-mode }}"
echo "Scanning HTML files in: $HTML_PATH"
echo "Looking for warnings: $WARNINGS"
+ echo "PR mode: $PR_MODE"
# Convert comma-separated warnings to array
IFS=',' read -ra WARNING_ARRAY <<< "$WARNINGS"
@@ -122,25 +128,132 @@ runs:
WARNINGS_FOUND="false"
DETAILED_REPORT=""
- # Find all HTML files
+ # Find HTML files to check
if [ ! -e "$HTML_PATH" ]; then
echo "Error: HTML path '$HTML_PATH' does not exist"
exit 1
fi
- # Determine if we're dealing with a file or directory
- if [ -f "$HTML_PATH" ]; then
- # Single file
- if [[ "$HTML_PATH" == *.html ]]; then
- echo "Checking single HTML file: $HTML_PATH"
- FILES=("$HTML_PATH")
+ # Handle PR mode - only check HTML files corresponding to changed .md files
+ if [ "$PR_MODE" = "true" ]; then
+ echo "Running in PR mode - detecting changed .md files..."
+
+ # Get the list of changed .md files in this PR/push
+ CHANGED_MD_FILES=()
+
+ # Try to get changed files from git
+ if command -v git >/dev/null 2>&1; then
+ # For pull requests, compare against the base branch
+ if [ -n "${GITHUB_BASE_REF:-}" ]; then
+ # This is a pull request
+ BASE_REF="${GITHUB_BASE_REF}"
+ echo "Comparing against base branch: $BASE_REF"
+
+ # Try different comparison strategies
+ if git rev-parse --verify "$BASE_REF" >/dev/null 2>&1; then
+ # Base branch exists locally
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"...HEAD | grep '\.md$' || true)
+ elif git rev-parse --verify "origin/$BASE_REF" >/dev/null 2>&1; then
+ # Try origin/base_ref
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "origin/$BASE_REF"...HEAD | grep '\.md$' || true)
+ else
+ # Fetch the base branch and try again
+ if git fetch origin "$BASE_REF:$BASE_REF" 2>/dev/null; then
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"...HEAD | grep '\.md$' || true)
+ else
+ echo "Warning: Could not compare with base branch $BASE_REF, falling back to HEAD~1"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM HEAD~1...HEAD | grep '\.md$' || true)
+ fi
+ fi
+ else
+ # This is a push event, compare with previous commit
+ if [ "${GITHUB_EVENT_NAME:-}" = "push" ] && [ -n "${GITHUB_EVENT_BEFORE:-}" ] && [ "${GITHUB_EVENT_BEFORE}" != "0000000000000000000000000000000000000000" ]; then
+ echo "Comparing against previous commit: ${GITHUB_EVENT_BEFORE}"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "${GITHUB_EVENT_BEFORE}"...HEAD | grep '\.md$' || true)
+ else
+ # Fallback to comparing with HEAD~1
+ echo "Comparing against HEAD~1"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM HEAD~1...HEAD | grep '\.md$' || true)
+ fi
+ fi
+ else
+ echo "Warning: git command not available, falling back to scanning all files"
+ PR_MODE="false"
+ fi
+
+ if [ ${#CHANGED_MD_FILES[@]} -eq 0 ]; then
+ echo "No .md files changed in this PR - no HTML files to check"
+ FILES=()
else
- echo "Error: '$HTML_PATH' is not an HTML file"
- exit 1
+ echo "Found ${#CHANGED_MD_FILES[@]} changed .md file(s):"
+ printf '%s\n' "${CHANGED_MD_FILES[@]}"
+
+ # Map changed .md files to corresponding .html files
+ FILES=()
+ for md_file in "${CHANGED_MD_FILES[@]}"; do
+ # Convert .md file path to corresponding .html file in the build directory
+ # Remove .md extension and add .html
+ base_name=$(basename "$md_file" .md)
+
+ # Look for the corresponding HTML file in the HTML_PATH
+ if [ -f "$HTML_PATH" ]; then
+ # HTML_PATH is a single file, only check if it matches
+ html_file_name=$(basename "$HTML_PATH" .html)
+ if [ "$base_name" = "$html_file_name" ]; then
+ FILES+=("$HTML_PATH")
+ echo "Mapped $md_file -> $HTML_PATH"
+ fi
+ else
+ # HTML_PATH is a directory, search for corresponding HTML file
+ # Try different possible mappings
+ possible_paths=(
+ "$HTML_PATH/$base_name.html"
+ "$HTML_PATH/$(dirname "$md_file")/$base_name.html"
+ )
+
+ for html_path in "${possible_paths[@]}"; do
+ if [ -f "$html_path" ]; then
+ FILES+=("$html_path")
+ echo "Mapped $md_file -> $html_path"
+ break
+ fi
+ done
+
+ # If no exact match found, search recursively
+ if ! printf '%s\n' "${FILES[@]}" | grep -q "/$base_name.html"; then
+ found_file=$(find "$HTML_PATH" -name "$base_name.html" -type f | head -1)
+ if [ -n "$found_file" ]; then
+ FILES+=("$found_file")
+ echo "Mapped $md_file -> $found_file (found recursively)"
+ else
+ echo "Warning: No corresponding HTML file found for $md_file"
+ fi
+ fi
+ fi
+ done
+
+ if [ ${#FILES[@]} -eq 0 ]; then
+ echo "No HTML files found corresponding to changed .md files"
+ else
+ echo "Will check ${#FILES[@]} HTML file(s) in PR mode"
+ fi
fi
else
- # Directory - find all HTML files
- mapfile -d '' FILES < <(find "$HTML_PATH" -name "*.html" -type f -print0)
+ # Normal mode - find all HTML files or use specified file
+ if [ -f "$HTML_PATH" ]; then
+ # Single file
+ if [[ "$HTML_PATH" == *.html ]]; then
+ echo "Checking single HTML file: $HTML_PATH"
+ FILES=("$HTML_PATH")
+ else
+ echo "Error: '$HTML_PATH' is not an HTML file"
+ exit 1
+ fi
+ else
+ # Directory - find all HTML files
+ echo "Scanning all HTML files in directory: $HTML_PATH"
+ mapfile -d '' FILES < <(find "$HTML_PATH" -name "*.html" -type f -print0)
+ fi
fi
# Create temporary Python script for parsing HTML
diff --git a/.github/workflows/test-warning-check.yml b/.github/workflows/test-warning-check.yml
index 535c0db..35bd475 100644
--- a/.github/workflows/test-warning-check.yml
+++ b/.github/workflows/test-warning-check.yml
@@ -322,4 +322,84 @@ jobs:
exit 1
fi
- echo "✅ Custom warning exclusion test passed"
\ No newline at end of file
+ echo "✅ Custom warning exclusion test passed"
+
+ test-pr-mode-basic:
+ runs-on: ubuntu-latest
+ name: Test PR mode basic functionality
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Test PR mode with non-git context (should fallback to normal mode)
+ id: pr-mode-fallback-test
+ uses: .//.github/actions/check-warnings
+ with:
+ html-path: './test/check-warnings/lecture-with-warnings.html'
+ pr-mode: 'true'
+ fail-on-warning: 'false'
+
+ - name: Verify fallback results
+ run: |
+ echo "Warnings found: ${{ steps.pr-mode-fallback-test.outputs.warnings-found }}"
+ echo "Warning count: ${{ steps.pr-mode-fallback-test.outputs.warning-count }}"
+
+ # Should find warnings since it falls back to normal mode
+ if [ "${{ steps.pr-mode-fallback-test.outputs.warnings-found }}" != "true" ]; then
+ echo "❌ Expected warnings in fallback mode but found none"
+ exit 1
+ fi
+
+ echo "✅ PR mode fallback test passed"
+
+ test-pr-mode-simulation:
+ runs-on: ubuntu-latest
+ name: Test PR mode with simulated git environment
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup git for PR mode simulation
+ run: |
+ # Configure git
+ git config user.email "test@example.com"
+ git config user.name "Test User"
+
+ # Create a test scenario: commit current state, modify a .md file, then test
+ git add -A
+ git commit -m "Base state for PR mode test" || echo "Nothing to commit"
+
+ # Create a feature branch
+ git checkout -b test-pr-mode-branch
+
+ # Modify one of our test .md files
+ echo "# Updated Test Lecture" > test/check-warnings/lecture-with-warnings.md
+ git add test/check-warnings/lecture-with-warnings.md
+ git commit -m "Update test lecture"
+
+ # Go back to main and then return to feature branch to simulate PR context
+ git checkout main
+ git checkout test-pr-mode-branch
+
+ - name: Test PR mode with git context
+ id: pr-mode-git-test
+ uses: .//.github/actions/check-warnings
+ with:
+ html-path: './test/check-warnings'
+ pr-mode: 'true'
+ fail-on-warning: 'false'
+ env:
+ GITHUB_BASE_REF: 'main'
+ GITHUB_EVENT_NAME: 'pull_request'
+
+ - name: Verify git-based PR mode results
+ run: |
+ echo "Warnings found: ${{ steps.pr-mode-git-test.outputs.warnings-found }}"
+ echo "Warning count: ${{ steps.pr-mode-git-test.outputs.warning-count }}"
+ echo "Warning details: ${{ steps.pr-mode-git-test.outputs.warning-details }}"
+
+ # Should find warnings only in the changed file (lecture-with-warnings.html)
+ # The exact behavior depends on whether the HTML file mapping works
+ # At minimum, it should run without errors
+
+ echo "✅ PR mode git simulation test passed"
\ No newline at end of file
diff --git a/test/check-warnings/lecture-clean.html b/test/check-warnings/lecture-clean.html
new file mode 100644
index 0000000..15ac823
--- /dev/null
+++ b/test/check-warnings/lecture-clean.html
@@ -0,0 +1,16 @@
+
+
+
+ Clean Lecture
+
+
+ Clean Test Lecture Output
+
+
+Running code...
+Result: 42
+Success!
+
+
+
+
\ No newline at end of file
diff --git a/test/check-warnings/lecture-clean.md b/test/check-warnings/lecture-clean.md
new file mode 100644
index 0000000..1fbee6f
--- /dev/null
+++ b/test/check-warnings/lecture-clean.md
@@ -0,0 +1,3 @@
+# Clean Test Lecture for PR Mode
+
+This is a clean test lecture file to test PR mode functionality.
\ No newline at end of file
diff --git a/test/check-warnings/lecture-with-warnings.html b/test/check-warnings/lecture-with-warnings.html
new file mode 100644
index 0000000..8ef22dc
--- /dev/null
+++ b/test/check-warnings/lecture-with-warnings.html
@@ -0,0 +1,17 @@
+
+
+
+ Lecture with Warnings
+
+
+ Test Lecture Output
+
+
+Running code...
+/path/to/file.py:15: UserWarning: This is a test warning for PR mode
+ result = function_call()
+Result: 42
+
+
+
+
\ No newline at end of file
diff --git a/test/check-warnings/lecture-with-warnings.md b/test/check-warnings/lecture-with-warnings.md
new file mode 100644
index 0000000..6dcdc73
--- /dev/null
+++ b/test/check-warnings/lecture-with-warnings.md
@@ -0,0 +1,3 @@
+# Test Lecture for PR Mode
+
+This is a test lecture file to test PR mode functionality.
\ No newline at end of file
diff --git a/test/check-warnings/test-pr-mode.sh b/test/check-warnings/test-pr-mode.sh
new file mode 100755
index 0000000..c163adc
--- /dev/null
+++ b/test/check-warnings/test-pr-mode.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+# Test script for PR mode functionality
+
+set -e
+
+echo "Testing PR mode functionality..."
+
+# Create a temporary git repository for testing
+TEST_DIR="/tmp/test-pr-mode"
+rm -rf "$TEST_DIR"
+mkdir -p "$TEST_DIR"
+cd "$TEST_DIR"
+
+# Initialize git repo
+git init
+git config user.email "test@example.com"
+git config user.name "Test User"
+
+# Create some test files
+mkdir -p _build/html
+echo '# Test Lecture 1' > lecture1.md
+echo '# Test Lecture 2' > lecture2.md
+echo '# Test Lecture 3' > lecture3.md
+
+# Create corresponding HTML files with and without warnings
+cat > _build/html/lecture1.html << 'EOF'
+
+
+Lecture 1
+
+ Lecture 1
+
+
/path/to/file.py:10: UserWarning: Test warning in lecture 1
+
+
+
+EOF
+
+cat > _build/html/lecture2.html << 'EOF'
+
+
+Lecture 2
+
+ Lecture 2
+
+
Clean output with no warnings
+
+
+
+EOF
+
+cat > _build/html/lecture3.html << 'EOF'
+
+
+Lecture 3
+
+ Lecture 3
+
+
/path/to/file.py:15: DeprecationWarning: Test warning in lecture 3
+
+
+
+EOF
+
+# Commit initial state
+git add .
+git commit -m "Initial commit"
+
+# Rename master to main for consistency
+git branch -m master main
+
+# Create a branch to simulate PR
+git checkout -b feature-branch
+
+# Modify only lecture1.md (simulate editing the lecture)
+echo '# Test Lecture 1 - Updated' > lecture1.md
+git add lecture1.md
+git commit -m "Update lecture1"
+
+# Switch back to main to simulate remote
+git checkout main
+git checkout feature-branch
+
+# Now test our PR mode logic
+echo "Testing PR mode file detection..."
+
+# Simulate the environment variables that would be present in a GitHub Action PR
+export GITHUB_BASE_REF="main"
+export GITHUB_EVENT_NAME="pull_request"
+
+# Test the git diff logic that our action uses (compare with main branch)
+echo "Changed .md files:"
+git diff --name-only --diff-filter=AM main...HEAD | grep '\.md$' || echo "No .md files found"
+
+# Test our file mapping logic
+CHANGED_MD_FILES=()
+mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM main...HEAD | grep '\.md$' || true)
+
+echo "Number of changed .md files: ${#CHANGED_MD_FILES[@]}"
+if [ ${#CHANGED_MD_FILES[@]} -gt 0 ]; then
+ echo "Changed files:"
+ printf '%s\n' "${CHANGED_MD_FILES[@]}"
+
+ # Test mapping to HTML files
+ HTML_PATH="_build/html"
+ for md_file in "${CHANGED_MD_FILES[@]}"; do
+ base_name=$(basename "$md_file" .md)
+ html_file="$HTML_PATH/$base_name.html"
+ if [ -f "$html_file" ]; then
+ echo "✅ Found corresponding HTML file: $html_file"
+ else
+ echo "❌ Missing HTML file: $html_file"
+ fi
+ done
+fi
+
+# Clean up
+cd /
+rm -rf "$TEST_DIR"
+
+echo "✅ PR mode test completed successfully"
\ No newline at end of file
From 9126bc84cb6e52de92ce2d11b70c39d604d9c511 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 Aug 2025 04:49:37 +0000
Subject: [PATCH 03/11] Enhance PR mode documentation and error handling
Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com>
---
.github/actions/check-warnings/README.md | 64 ++++++++++++++++++++---
.github/actions/check-warnings/action.yml | 2 +-
2 files changed, 57 insertions(+), 9 deletions(-)
diff --git a/.github/actions/check-warnings/README.md b/.github/actions/check-warnings/README.md
index 7b4cc34..a0db2a3 100644
--- a/.github/actions/check-warnings/README.md
+++ b/.github/actions/check-warnings/README.md
@@ -45,6 +45,37 @@ When `pr-mode` is enabled, the action will:
This significantly reduces noise from warnings in unrelated lectures and helps focus on the changes being made.
+**Benefits of PR Mode:**
+- **Faster CI runs**: Only scans relevant files instead of entire documentation
+- **Focused feedback**: Only reports warnings related to your changes
+- **Reduced noise**: Avoids confusion from pre-existing warnings in other files
+- **Better developer experience**: Clearer feedback on what needs to be fixed
+
+### Example: Normal Mode vs PR Mode
+
+**Normal Mode (scans all files):**
+```
+Scanning HTML files in: ./_build/html
+Found 50 HTML files
+❌ Found 15 warnings across all files
+```
+
+**PR Mode (scans only changed files):**
+```
+Running in PR mode - detecting changed .md files...
+Found 2 changed .md file(s):
+ lectures/optimization.md
+ exercises/exercise1.md
+Mapped lectures/optimization.md -> _build/html/lectures/optimization.html
+Mapped exercises/exercise1.md -> _build/html/exercises/exercise1.html
+Will check 2 HTML file(s) in PR mode
+❌ Found 1 warning in changed files
+```
+
+In this example, PR mode helps you focus on the 1 warning in your changes rather than being overwhelmed by 15 warnings across the entire codebase.
+
+In this example, PR mode helps you focus on the 1 warning in your changes rather than being overwhelmed by 15 warnings across the entire codebase.
+
### Advanced Usage with PR Comments
```yaml
@@ -315,7 +346,7 @@ If you're only using the basic warning check functionality, only `contents: read
## Example Workflow
-Here's a complete example of how to use this action in a workflow:
+Here's a complete example of how to use this action in a workflow with PR mode:
```yaml
name: Build and Check Documentation
@@ -338,6 +369,9 @@ jobs:
steps:
- uses: actions/checkout@v4
+ with:
+ # Fetch full history for proper PR mode operation
+ fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
@@ -352,18 +386,32 @@ jobs:
run: |
jupyter-book build .
- - name: Check for Python warnings
+ # For PRs: only check changed files to reduce noise
+ - name: Check for Python warnings (PR mode)
+ if: github.event_name == 'pull_request'
uses: QuantEcon/meta/.github/actions/check-warnings@main
with:
html-path: './_build/html'
- # Uses comprehensive default warnings (all Python warning types)
- fail-on-warning: ${{ github.event_name == 'push' }} # Fail on push, warn on PR
- create-issue: ${{ github.event_name == 'push' }} # Create issues for main branch
- notify: 'maintainer1,reviewer2' # Assign issues to team members
- create-artifact: 'true' # Always create artifacts
- artifact-name: 'warning-report'
+ pr-mode: 'true'
+ fail-on-warning: 'true'
+
+ # For pushes to main: check all files
+ - name: Check for Python warnings (full check)
+ if: github.event_name == 'push'
+ uses: QuantEcon/meta/.github/actions/check-warnings@main
+ with:
+ html-path: './_build/html'
+ pr-mode: 'false'
+ fail-on-warning: 'false'
+ create-issue: 'true'
+ notify: 'maintainer1,reviewer2'
```
+This workflow demonstrates:
+- **PR mode for pull requests**: Only checks files related to changes, provides quick feedback
+- **Full mode for main branch**: Comprehensive checking with issue creation for tracking
+- **Different failure behavior**: Strict for PRs, informational for main branch
+
## Use Case
This action is particularly useful for:
diff --git a/.github/actions/check-warnings/action.yml b/.github/actions/check-warnings/action.yml
index a58f7fd..623e41b 100755
--- a/.github/actions/check-warnings/action.yml
+++ b/.github/actions/check-warnings/action.yml
@@ -226,7 +226,7 @@ runs:
FILES+=("$found_file")
echo "Mapped $md_file -> $found_file (found recursively)"
else
- echo "Warning: No corresponding HTML file found for $md_file"
+ echo "Warning: No corresponding HTML file found for $md_file (searched for $base_name.html)"
fi
fi
fi
From 6171086f31bee77329baa9384124647392090bf7 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 Aug 2025 06:08:39 +0000
Subject: [PATCH 04/11] Fix PR mode git diff logic and extract shell script for
better maintainability
Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com>
---
.github/actions/check-warnings/action.yml | 302 +----------------
.../actions/check-warnings/check-warnings.sh | 317 ++++++++++++++++++
2 files changed, 325 insertions(+), 294 deletions(-)
create mode 100755 .github/actions/check-warnings/check-warnings.sh
diff --git a/.github/actions/check-warnings/action.yml b/.github/actions/check-warnings/action.yml
index 623e41b..cc18dc6 100755
--- a/.github/actions/check-warnings/action.yml
+++ b/.github/actions/check-warnings/action.yml
@@ -67,301 +67,15 @@ runs:
- name: Check for warnings
id: check
shell: bash
+ env:
+ INPUT_HTML_PATH: ${{ inputs.html-path }}
+ INPUT_WARNINGS: ${{ inputs.warnings }}
+ INPUT_EXCLUDE_WARNING: ${{ inputs.exclude-warning }}
+ INPUT_FAIL_ON_WARNING: ${{ inputs.fail-on-warning }}
+ INPUT_PR_MODE: ${{ inputs.pr-mode }}
run: |
- # Parse inputs
- HTML_PATH="${{ inputs.html-path }}"
- WARNINGS="${{ inputs.warnings }}"
- EXCLUDE_WARNINGS="${{ inputs.exclude-warning }}"
- FAIL_ON_WARNING="${{ inputs.fail-on-warning }}"
- PR_MODE="${{ inputs.pr-mode }}"
-
- echo "Scanning HTML files in: $HTML_PATH"
- echo "Looking for warnings: $WARNINGS"
- echo "PR mode: $PR_MODE"
-
- # Convert comma-separated warnings to array
- IFS=',' read -ra WARNING_ARRAY <<< "$WARNINGS"
-
- # Handle exclude-warning parameter
- if [ -n "$EXCLUDE_WARNINGS" ]; then
- echo "Excluding warnings: $EXCLUDE_WARNINGS"
- # Convert comma-separated exclude warnings to array
- IFS=',' read -ra EXCLUDE_ARRAY <<< "$EXCLUDE_WARNINGS"
-
- # Create a new array with warnings not in exclude list
- FILTERED_WARNING_ARRAY=()
- for warning in "${WARNING_ARRAY[@]}"; do
- # Remove leading/trailing whitespace from warning
- warning=$(echo "$warning" | xargs)
- exclude_warning=false
-
- # Check if this warning should be excluded
- for exclude in "${EXCLUDE_ARRAY[@]}"; do
- # Remove leading/trailing whitespace from exclude warning
- exclude=$(echo "$exclude" | xargs)
- if [ "$warning" = "$exclude" ]; then
- exclude_warning=true
- break
- fi
- done
-
- # Add to filtered array if not excluded
- if [ "$exclude_warning" = false ]; then
- FILTERED_WARNING_ARRAY+=("$warning")
- fi
- done
-
- # Replace WARNING_ARRAY with filtered array
- WARNING_ARRAY=("${FILTERED_WARNING_ARRAY[@]}")
-
- # Show final warning list
- if [ ${#WARNING_ARRAY[@]} -eq 0 ]; then
- echo "⚠️ All warnings have been excluded. No warnings will be checked."
- else
- echo "Final warning list after exclusions: ${WARNING_ARRAY[*]}"
- fi
- fi
-
- # Initialize counters
- TOTAL_WARNINGS=0
- WARNING_DETAILS=""
- WARNINGS_FOUND="false"
- DETAILED_REPORT=""
-
- # Find HTML files to check
- if [ ! -e "$HTML_PATH" ]; then
- echo "Error: HTML path '$HTML_PATH' does not exist"
- exit 1
- fi
-
- # Handle PR mode - only check HTML files corresponding to changed .md files
- if [ "$PR_MODE" = "true" ]; then
- echo "Running in PR mode - detecting changed .md files..."
-
- # Get the list of changed .md files in this PR/push
- CHANGED_MD_FILES=()
-
- # Try to get changed files from git
- if command -v git >/dev/null 2>&1; then
- # For pull requests, compare against the base branch
- if [ -n "${GITHUB_BASE_REF:-}" ]; then
- # This is a pull request
- BASE_REF="${GITHUB_BASE_REF}"
- echo "Comparing against base branch: $BASE_REF"
-
- # Try different comparison strategies
- if git rev-parse --verify "$BASE_REF" >/dev/null 2>&1; then
- # Base branch exists locally
- mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"...HEAD | grep '\.md$' || true)
- elif git rev-parse --verify "origin/$BASE_REF" >/dev/null 2>&1; then
- # Try origin/base_ref
- mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "origin/$BASE_REF"...HEAD | grep '\.md$' || true)
- else
- # Fetch the base branch and try again
- if git fetch origin "$BASE_REF:$BASE_REF" 2>/dev/null; then
- mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"...HEAD | grep '\.md$' || true)
- else
- echo "Warning: Could not compare with base branch $BASE_REF, falling back to HEAD~1"
- mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM HEAD~1...HEAD | grep '\.md$' || true)
- fi
- fi
- else
- # This is a push event, compare with previous commit
- if [ "${GITHUB_EVENT_NAME:-}" = "push" ] && [ -n "${GITHUB_EVENT_BEFORE:-}" ] && [ "${GITHUB_EVENT_BEFORE}" != "0000000000000000000000000000000000000000" ]; then
- echo "Comparing against previous commit: ${GITHUB_EVENT_BEFORE}"
- mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "${GITHUB_EVENT_BEFORE}"...HEAD | grep '\.md$' || true)
- else
- # Fallback to comparing with HEAD~1
- echo "Comparing against HEAD~1"
- mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM HEAD~1...HEAD | grep '\.md$' || true)
- fi
- fi
- else
- echo "Warning: git command not available, falling back to scanning all files"
- PR_MODE="false"
- fi
-
- if [ ${#CHANGED_MD_FILES[@]} -eq 0 ]; then
- echo "No .md files changed in this PR - no HTML files to check"
- FILES=()
- else
- echo "Found ${#CHANGED_MD_FILES[@]} changed .md file(s):"
- printf '%s\n' "${CHANGED_MD_FILES[@]}"
-
- # Map changed .md files to corresponding .html files
- FILES=()
- for md_file in "${CHANGED_MD_FILES[@]}"; do
- # Convert .md file path to corresponding .html file in the build directory
- # Remove .md extension and add .html
- base_name=$(basename "$md_file" .md)
-
- # Look for the corresponding HTML file in the HTML_PATH
- if [ -f "$HTML_PATH" ]; then
- # HTML_PATH is a single file, only check if it matches
- html_file_name=$(basename "$HTML_PATH" .html)
- if [ "$base_name" = "$html_file_name" ]; then
- FILES+=("$HTML_PATH")
- echo "Mapped $md_file -> $HTML_PATH"
- fi
- else
- # HTML_PATH is a directory, search for corresponding HTML file
- # Try different possible mappings
- possible_paths=(
- "$HTML_PATH/$base_name.html"
- "$HTML_PATH/$(dirname "$md_file")/$base_name.html"
- )
-
- for html_path in "${possible_paths[@]}"; do
- if [ -f "$html_path" ]; then
- FILES+=("$html_path")
- echo "Mapped $md_file -> $html_path"
- break
- fi
- done
-
- # If no exact match found, search recursively
- if ! printf '%s\n' "${FILES[@]}" | grep -q "/$base_name.html"; then
- found_file=$(find "$HTML_PATH" -name "$base_name.html" -type f | head -1)
- if [ -n "$found_file" ]; then
- FILES+=("$found_file")
- echo "Mapped $md_file -> $found_file (found recursively)"
- else
- echo "Warning: No corresponding HTML file found for $md_file (searched for $base_name.html)"
- fi
- fi
- fi
- done
-
- if [ ${#FILES[@]} -eq 0 ]; then
- echo "No HTML files found corresponding to changed .md files"
- else
- echo "Will check ${#FILES[@]} HTML file(s) in PR mode"
- fi
- fi
- else
- # Normal mode - find all HTML files or use specified file
- if [ -f "$HTML_PATH" ]; then
- # Single file
- if [[ "$HTML_PATH" == *.html ]]; then
- echo "Checking single HTML file: $HTML_PATH"
- FILES=("$HTML_PATH")
- else
- echo "Error: '$HTML_PATH' is not an HTML file"
- exit 1
- fi
- else
- # Directory - find all HTML files
- echo "Scanning all HTML files in directory: $HTML_PATH"
- mapfile -d '' FILES < <(find "$HTML_PATH" -name "*.html" -type f -print0)
- fi
- fi
-
- # Create temporary Python script for parsing HTML
- echo 'import re' > /tmp/check_warnings.py
- echo 'import sys' >> /tmp/check_warnings.py
- echo 'import os' >> /tmp/check_warnings.py
- echo '' >> /tmp/check_warnings.py
- echo 'def find_warnings_in_cell_outputs(file_path, warning_text):' >> /tmp/check_warnings.py
- echo ' try:' >> /tmp/check_warnings.py
- echo ' with open(file_path, "r", encoding="utf-8") as f:' >> /tmp/check_warnings.py
- echo ' content = f.read()' >> /tmp/check_warnings.py
- echo ' ' >> /tmp/check_warnings.py
- echo ' # Find all HTML elements with cell_output in the class attribute' >> /tmp/check_warnings.py
- echo ' pattern = r"<([^>]+)\s+class=\"[^\"]*cell_output[^\"]*\"[^>]*>(.*?)\1>"' >> /tmp/check_warnings.py
- echo ' ' >> /tmp/check_warnings.py
- echo ' matches = []' >> /tmp/check_warnings.py
- echo ' ' >> /tmp/check_warnings.py
- echo ' # Search for cell_output blocks' >> /tmp/check_warnings.py
- echo ' for match in re.finditer(pattern, content, re.DOTALL | re.IGNORECASE):' >> /tmp/check_warnings.py
- echo ' block_content = match.group(2)' >> /tmp/check_warnings.py
- echo ' block_start = match.start()' >> /tmp/check_warnings.py
- echo ' ' >> /tmp/check_warnings.py
- echo ' # Count line number where this block starts' >> /tmp/check_warnings.py
- echo ' block_line = content[:block_start].count("\\n") + 1' >> /tmp/check_warnings.py
- echo ' ' >> /tmp/check_warnings.py
- echo ' # Search for warning within this block' >> /tmp/check_warnings.py
- echo ' if warning_text in block_content:' >> /tmp/check_warnings.py
- echo ' # Find specific lines within the block that contain the warning' >> /tmp/check_warnings.py
- echo ' block_lines = block_content.split("\\n")' >> /tmp/check_warnings.py
- echo ' for i, line in enumerate(block_lines):' >> /tmp/check_warnings.py
- echo ' if warning_text in line:' >> /tmp/check_warnings.py
- echo ' actual_line_num = block_line + i' >> /tmp/check_warnings.py
- echo ' # Clean up the line for display (remove extra whitespace, HTML tags)' >> /tmp/check_warnings.py
- echo ' clean_line = re.sub(r"<[^>]+>", "", line).strip()' >> /tmp/check_warnings.py
- echo ' if clean_line: # Only add non-empty lines' >> /tmp/check_warnings.py
- echo ' matches.append(f"{actual_line_num}:{clean_line}")' >> /tmp/check_warnings.py
- echo ' ' >> /tmp/check_warnings.py
- echo ' # Output results' >> /tmp/check_warnings.py
- echo ' for match in matches:' >> /tmp/check_warnings.py
- echo ' print(match)' >> /tmp/check_warnings.py
- echo ' ' >> /tmp/check_warnings.py
- echo ' except Exception as e:' >> /tmp/check_warnings.py
- echo ' print(f"Error processing file: {e}", file=sys.stderr)' >> /tmp/check_warnings.py
- echo ' sys.exit(1)' >> /tmp/check_warnings.py
- echo '' >> /tmp/check_warnings.py
- echo 'if __name__ == "__main__":' >> /tmp/check_warnings.py
- echo ' file_path = sys.argv[1]' >> /tmp/check_warnings.py
- echo ' warning_text = sys.argv[2]' >> /tmp/check_warnings.py
- echo ' find_warnings_in_cell_outputs(file_path, warning_text)' >> /tmp/check_warnings.py
-
- # Search for warnings in HTML files within cell_output elements
- for file in "${FILES[@]}"; do
- echo "Checking file: $file"
-
- # Skip warning check if no warnings to check for
- if [ ${#WARNING_ARRAY[@]} -eq 0 ]; then
- echo "No warnings to check for in $file (all excluded)"
- continue
- fi
-
- for warning in "${WARNING_ARRAY[@]}"; do
- # Remove leading/trailing whitespace from warning
- warning=$(echo "$warning" | xargs)
-
- # Run the Python script and capture results
- matches=$(python3 /tmp/check_warnings.py "$file" "$warning" 2>/dev/null || true)
-
- if [ -n "$matches" ]; then
- WARNINGS_FOUND="true"
- count=$(echo "$matches" | wc -l)
- TOTAL_WARNINGS=$((TOTAL_WARNINGS + count))
-
- echo "⚠️ Found $count instance(s) of '$warning' in $file:"
- echo "$matches"
-
- # Add to basic details
- if [ -n "$WARNING_DETAILS" ]; then
- WARNING_DETAILS="$WARNING_DETAILS\n"
- fi
- WARNING_DETAILS="$WARNING_DETAILS$file: $count instance(s) of '$warning'"
-
- # Add to detailed report
- DETAILED_REPORT="$DETAILED_REPORT## $warning in $file\n\n"
- DETAILED_REPORT="$DETAILED_REPORT**Found $count instance(s):**\n\n"
- DETAILED_REPORT="$DETAILED_REPORT\`\`\`\n"
- DETAILED_REPORT="$DETAILED_REPORT$matches\n"
- DETAILED_REPORT="$DETAILED_REPORT\`\`\`\n\n"
- fi
- done
- done
-
- # Set outputs
- echo "warnings-found=$WARNINGS_FOUND" >> $GITHUB_OUTPUT
- echo "warning-count=$TOTAL_WARNINGS" >> $GITHUB_OUTPUT
- echo "warning-details<> $GITHUB_OUTPUT
- echo -e "$WARNING_DETAILS" >> $GITHUB_OUTPUT
- echo "EOF" >> $GITHUB_OUTPUT
- echo "detailed-report<> $GITHUB_OUTPUT
- echo -e "$DETAILED_REPORT" >> $GITHUB_OUTPUT
- echo "EOF" >> $GITHUB_OUTPUT
-
- # Summary
- if [ "$WARNINGS_FOUND" = "true" ]; then
- echo "❌ Found $TOTAL_WARNINGS warning(s) in HTML files"
- echo "::error::Found $TOTAL_WARNINGS Python warning(s) in HTML output"
- else
- echo "✅ No warnings found in HTML files"
- fi
+ # Run the check-warnings script
+ ${{ github.action_path }}/check-warnings.sh
- name: Post PR comment with warning report
if: inputs.fail-on-warning == 'true' && steps.check.outputs.warnings-found == 'true' && github.event_name == 'pull_request'
diff --git a/.github/actions/check-warnings/check-warnings.sh b/.github/actions/check-warnings/check-warnings.sh
new file mode 100755
index 0000000..558d1cd
--- /dev/null
+++ b/.github/actions/check-warnings/check-warnings.sh
@@ -0,0 +1,317 @@
+#!/bin/bash
+set -e
+
+# Parse inputs from environment variables set by GitHub Actions
+HTML_PATH="${INPUT_HTML_PATH}"
+WARNINGS="${INPUT_WARNINGS}"
+EXCLUDE_WARNINGS="${INPUT_EXCLUDE_WARNING}"
+FAIL_ON_WARNING="${INPUT_FAIL_ON_WARNING}"
+PR_MODE="${INPUT_PR_MODE}"
+
+echo "Scanning HTML files in: $HTML_PATH"
+echo "Looking for warnings: $WARNINGS"
+echo "PR mode: $PR_MODE"
+
+# Convert comma-separated warnings to array
+IFS=',' read -ra WARNING_ARRAY <<< "$WARNINGS"
+
+# Handle exclude-warning parameter
+if [ -n "$EXCLUDE_WARNINGS" ]; then
+ echo "Excluding warnings: $EXCLUDE_WARNINGS"
+ # Convert comma-separated exclude warnings to array
+ IFS=',' read -ra EXCLUDE_ARRAY <<< "$EXCLUDE_WARNINGS"
+
+ # Create a new array with warnings not in exclude list
+ FILTERED_WARNING_ARRAY=()
+ for warning in "${WARNING_ARRAY[@]}"; do
+ # Remove leading/trailing whitespace from warning
+ warning=$(echo "$warning" | xargs)
+ exclude_warning=false
+
+ # Check if this warning should be excluded
+ for exclude in "${EXCLUDE_ARRAY[@]}"; do
+ # Remove leading/trailing whitespace from exclude warning
+ exclude=$(echo "$exclude" | xargs)
+ if [ "$warning" = "$exclude" ]; then
+ exclude_warning=true
+ break
+ fi
+ done
+
+ # Add to filtered array if not excluded
+ if [ "$exclude_warning" = false ]; then
+ FILTERED_WARNING_ARRAY+=("$warning")
+ fi
+ done
+
+ # Replace WARNING_ARRAY with filtered array
+ WARNING_ARRAY=("${FILTERED_WARNING_ARRAY[@]}")
+
+ # Show final warning list
+ if [ ${#WARNING_ARRAY[@]} -eq 0 ]; then
+ echo "⚠️ All warnings have been excluded. No warnings will be checked."
+ else
+ echo "Final warning list after exclusions: ${WARNING_ARRAY[*]}"
+ fi
+fi
+
+# Initialize counters
+TOTAL_WARNINGS=0
+WARNING_DETAILS=""
+WARNINGS_FOUND="false"
+DETAILED_REPORT=""
+
+# Find HTML files to check
+if [ ! -e "$HTML_PATH" ]; then
+ echo "Error: HTML path '$HTML_PATH' does not exist"
+ exit 1
+fi
+
+# Handle PR mode - only check HTML files corresponding to changed .md files
+if [ "$PR_MODE" = "true" ]; then
+ echo "Running in PR mode - detecting changed .md files..."
+
+ # Get the list of changed .md files in this PR/push
+ CHANGED_MD_FILES=()
+
+ # Try to get changed files from git
+ if command -v git >/dev/null 2>&1; then
+ # For pull requests, compare against the base branch
+ if [ -n "${GITHUB_BASE_REF:-}" ]; then
+ # This is a pull request
+ BASE_REF="${GITHUB_BASE_REF}"
+ echo "Comparing against base branch: $BASE_REF"
+
+ # Improved git diff logic with better fallback handling
+ if git ls-remote --exit-code origin "$BASE_REF" >/dev/null 2>&1; then
+ # Base branch exists in origin, fetch it
+ echo "Fetching base branch: origin/$BASE_REF"
+ git fetch origin "$BASE_REF" 2>/dev/null || echo "Warning: Could not fetch $BASE_REF"
+
+ # Try different comparison strategies in order of preference
+ if git rev-parse --verify "origin/$BASE_REF" >/dev/null 2>&1; then
+ echo "Using origin/$BASE_REF for comparison"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "origin/$BASE_REF"...HEAD | grep '\.md$' || true)
+ elif git rev-parse --verify "$BASE_REF" >/dev/null 2>&1; then
+ echo "Using $BASE_REF for comparison"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"...HEAD | grep '\.md$' || true)
+ else
+ echo "Warning: Could not find base reference, using merge-base with origin/HEAD"
+ # Try to find merge base with origin/HEAD
+ if git rev-parse --verify "origin/HEAD" >/dev/null 2>&1; then
+ MERGE_BASE=$(git merge-base HEAD origin/HEAD 2>/dev/null || echo "")
+ if [ -n "$MERGE_BASE" ]; then
+ echo "Using merge-base: $MERGE_BASE"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$MERGE_BASE"...HEAD | grep '\.md$' || true)
+ else
+ echo "Warning: Could not find merge-base, falling back to HEAD~1"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM HEAD~1...HEAD | grep '\.md$' || true)
+ fi
+ else
+ echo "Warning: Could not find origin/HEAD, falling back to HEAD~1"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM HEAD~1...HEAD | grep '\.md$' || true)
+ fi
+ fi
+ else
+ echo "Warning: Base branch $BASE_REF not found in origin, falling back to HEAD~1"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM HEAD~1...HEAD | grep '\.md$' || true)
+ fi
+ else
+ # This is a push event, compare with previous commit
+ if [ "${GITHUB_EVENT_NAME:-}" = "push" ] && [ -n "${GITHUB_EVENT_BEFORE:-}" ] && [ "${GITHUB_EVENT_BEFORE}" != "0000000000000000000000000000000000000000" ]; then
+ echo "Comparing against previous commit: ${GITHUB_EVENT_BEFORE}"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "${GITHUB_EVENT_BEFORE}"...HEAD | grep '\.md$' || true)
+ else
+ # Fallback to comparing with HEAD~1
+ echo "Comparing against HEAD~1"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM HEAD~1...HEAD | grep '\.md$' || true)
+ fi
+ fi
+ else
+ echo "Warning: git command not available, falling back to scanning all files"
+ PR_MODE="false"
+ fi
+
+ if [ ${#CHANGED_MD_FILES[@]} -eq 0 ]; then
+ echo "No .md files changed in this PR - no HTML files to check"
+ FILES=()
+ else
+ echo "Found ${#CHANGED_MD_FILES[@]} changed .md file(s):"
+ printf '%s\n' "${CHANGED_MD_FILES[@]}"
+
+ # Map changed .md files to corresponding .html files
+ FILES=()
+ for md_file in "${CHANGED_MD_FILES[@]}"; do
+ # Convert .md file path to corresponding .html file in the build directory
+ # Remove .md extension and add .html
+ base_name=$(basename "$md_file" .md)
+
+ # Look for the corresponding HTML file in the HTML_PATH
+ if [ -f "$HTML_PATH" ]; then
+ # HTML_PATH is a single file, only check if it matches
+ html_file_name=$(basename "$HTML_PATH" .html)
+ if [ "$base_name" = "$html_file_name" ]; then
+ FILES+=("$HTML_PATH")
+ echo "Mapped $md_file -> $HTML_PATH"
+ fi
+ else
+ # HTML_PATH is a directory, search for corresponding HTML file
+ # Try different possible mappings
+ possible_paths=(
+ "$HTML_PATH/$base_name.html"
+ "$HTML_PATH/$(dirname "$md_file")/$base_name.html"
+ )
+
+ for html_path in "${possible_paths[@]}"; do
+ if [ -f "$html_path" ]; then
+ FILES+=("$html_path")
+ echo "Mapped $md_file -> $html_path"
+ break
+ fi
+ done
+
+ # If no exact match found, search recursively
+ if ! printf '%s\n' "${FILES[@]}" | grep -q "/$base_name.html"; then
+ found_file=$(find "$HTML_PATH" -name "$base_name.html" -type f | head -1)
+ if [ -n "$found_file" ]; then
+ FILES+=("$found_file")
+ echo "Mapped $md_file -> $found_file (found recursively)"
+ else
+ echo "Warning: No corresponding HTML file found for $md_file (searched for $base_name.html)"
+ fi
+ fi
+ fi
+ done
+
+ if [ ${#FILES[@]} -eq 0 ]; then
+ echo "No HTML files found corresponding to changed .md files"
+ else
+ echo "Will check ${#FILES[@]} HTML file(s) in PR mode"
+ fi
+ fi
+else
+ # Normal mode - find all HTML files or use specified file
+ if [ -f "$HTML_PATH" ]; then
+ # Single file
+ if [[ "$HTML_PATH" == *.html ]]; then
+ echo "Checking single HTML file: $HTML_PATH"
+ FILES=("$HTML_PATH")
+ else
+ echo "Error: '$HTML_PATH' is not an HTML file"
+ exit 1
+ fi
+ else
+ # Directory - find all HTML files
+ echo "Scanning all HTML files in directory: $HTML_PATH"
+ mapfile -d '' FILES < <(find "$HTML_PATH" -name "*.html" -type f -print0)
+ fi
+fi
+
+# Create temporary Python script for parsing HTML
+cat > /tmp/check_warnings.py << 'EOF'
+import re
+import sys
+import os
+
+def find_warnings_in_cell_outputs(file_path, warning_text):
+ try:
+ with open(file_path, "r", encoding="utf-8") as f:
+ content = f.read()
+
+ # Find all HTML elements with cell_output in the class attribute
+ pattern = r"<([^>]+)\s+class=\"[^\"]*cell_output[^\"]*\"[^>]*>(.*?)\1>"
+
+ matches = []
+
+ # Search for cell_output blocks
+ for match in re.finditer(pattern, content, re.DOTALL | re.IGNORECASE):
+ block_content = match.group(2)
+ block_start = match.start()
+
+ # Count line number where this block starts
+ block_line = content[:block_start].count("\n") + 1
+
+ # Search for warning within this block
+ if warning_text in block_content:
+ # Find specific lines within the block that contain the warning
+ block_lines = block_content.split("\n")
+ for i, line in enumerate(block_lines):
+ if warning_text in line:
+ actual_line_num = block_line + i
+ # Clean up the line for display (remove extra whitespace, HTML tags)
+ clean_line = re.sub(r"<[^>]+>", "", line).strip()
+ if clean_line: # Only add non-empty lines
+ matches.append(f"{actual_line_num}:{clean_line}")
+
+ # Output results
+ for match in matches:
+ print(match)
+
+ except Exception as e:
+ print(f"Error processing file: {e}", file=sys.stderr)
+ sys.exit(1)
+
+if __name__ == "__main__":
+ file_path = sys.argv[1]
+ warning_text = sys.argv[2]
+ find_warnings_in_cell_outputs(file_path, warning_text)
+EOF
+
+# Search for warnings in HTML files within cell_output elements
+for file in "${FILES[@]}"; do
+ echo "Checking file: $file"
+
+ # Skip warning check if no warnings to check for
+ if [ ${#WARNING_ARRAY[@]} -eq 0 ]; then
+ echo "No warnings to check for in $file (all excluded)"
+ continue
+ fi
+
+ for warning in "${WARNING_ARRAY[@]}"; do
+ # Remove leading/trailing whitespace from warning
+ warning=$(echo "$warning" | xargs)
+
+ # Run the Python script and capture results
+ matches=$(python3 /tmp/check_warnings.py "$file" "$warning" 2>/dev/null || true)
+
+ if [ -n "$matches" ]; then
+ WARNINGS_FOUND="true"
+ count=$(echo "$matches" | wc -l)
+ TOTAL_WARNINGS=$((TOTAL_WARNINGS + count))
+
+ echo "⚠️ Found $count instance(s) of '$warning' in $file:"
+ echo "$matches"
+
+ # Add to basic details
+ if [ -n "$WARNING_DETAILS" ]; then
+ WARNING_DETAILS="$WARNING_DETAILS\n"
+ fi
+ WARNING_DETAILS="$WARNING_DETAILS$file: $count instance(s) of '$warning'"
+
+ # Add to detailed report
+ DETAILED_REPORT="$DETAILED_REPORT## $warning in $file\n\n"
+ DETAILED_REPORT="$DETAILED_REPORT**Found $count instance(s):**\n\n"
+ DETAILED_REPORT="$DETAILED_REPORT\`\`\`\n"
+ DETAILED_REPORT="$DETAILED_REPORT$matches\n"
+ DETAILED_REPORT="$DETAILED_REPORT\`\`\`\n\n"
+ fi
+ done
+done
+
+# Set outputs
+echo "warnings-found=$WARNINGS_FOUND" >> $GITHUB_OUTPUT
+echo "warning-count=$TOTAL_WARNINGS" >> $GITHUB_OUTPUT
+echo "warning-details<> $GITHUB_OUTPUT
+echo -e "$WARNING_DETAILS" >> $GITHUB_OUTPUT
+echo "EOF" >> $GITHUB_OUTPUT
+echo "detailed-report<> $GITHUB_OUTPUT
+echo -e "$DETAILED_REPORT" >> $GITHUB_OUTPUT
+echo "EOF" >> $GITHUB_OUTPUT
+
+# Summary
+if [ "$WARNINGS_FOUND" = "true" ]; then
+ echo "❌ Found $TOTAL_WARNINGS warning(s) in HTML files"
+ echo "::error::Found $TOTAL_WARNINGS Python warning(s) in HTML output"
+else
+ echo "✅ No warnings found in HTML files"
+fi
\ No newline at end of file
From e6c11729752f677887768fff85a7839c00dc7e59 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 Aug 2025 06:18:31 +0000
Subject: [PATCH 05/11] Fix missing detailed-report output and YAML formatting
issues
Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com>
---
.github/actions/check-warnings/action.yml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/.github/actions/check-warnings/action.yml b/.github/actions/check-warnings/action.yml
index cc18dc6..eb1611c 100755
--- a/.github/actions/check-warnings/action.yml
+++ b/.github/actions/check-warnings/action.yml
@@ -54,6 +54,9 @@ outputs:
warning-details:
description: 'Details of warnings found'
value: ${{ steps.check.outputs.warning-details }}
+ detailed-report:
+ description: 'Detailed markdown report of warnings found'
+ value: ${{ steps.check.outputs.detailed-report }}
issue-url:
description: 'URL of the created GitHub issue (if create-issue is enabled)'
value: ${{ steps.create-issue.outputs.issue-url }}
@@ -302,4 +305,4 @@ runs:
branding:
icon: 'alert-triangle'
- color: 'orange'
\ No newline at end of file
+ color: 'orange'
From d51afea1804ef353aa22dc07ea15361f73d919c2 Mon Sep 17 00:00:00 2001
From: Test User
Date: Mon, 25 Aug 2025 06:29:37 +0000
Subject: [PATCH 06/11] Fix PR mode fallback logic to properly handle scenarios
with no changed .md files
Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com>
---
.../actions/check-warnings/check-warnings.sh | 101 +++++++++---------
1 file changed, 52 insertions(+), 49 deletions(-)
diff --git a/.github/actions/check-warnings/check-warnings.sh b/.github/actions/check-warnings/check-warnings.sh
index 558d1cd..047d89d 100755
--- a/.github/actions/check-warnings/check-warnings.sh
+++ b/.github/actions/check-warnings/check-warnings.sh
@@ -133,61 +133,64 @@ if [ "$PR_MODE" = "true" ]; then
fi
if [ ${#CHANGED_MD_FILES[@]} -eq 0 ]; then
- echo "No .md files changed in this PR - no HTML files to check"
- FILES=()
- else
- echo "Found ${#CHANGED_MD_FILES[@]} changed .md file(s):"
- printf '%s\n' "${CHANGED_MD_FILES[@]}"
+ echo "No .md files changed in this PR - falling back to normal mode"
+ PR_MODE="false"
+ fi
+fi
+
+# Handle file discovery (both for normal mode and PR mode fallback)
+if [ "$PR_MODE" = "true" ]; then
+ echo "Found ${#CHANGED_MD_FILES[@]} changed .md file(s):"
+ printf '%s\n' "${CHANGED_MD_FILES[@]}"
+
+ # Map changed .md files to corresponding .html files
+ FILES=()
+ for md_file in "${CHANGED_MD_FILES[@]}"; do
+ # Convert .md file path to corresponding .html file in the build directory
+ # Remove .md extension and add .html
+ base_name=$(basename "$md_file" .md)
- # Map changed .md files to corresponding .html files
- FILES=()
- for md_file in "${CHANGED_MD_FILES[@]}"; do
- # Convert .md file path to corresponding .html file in the build directory
- # Remove .md extension and add .html
- base_name=$(basename "$md_file" .md)
+ # Look for the corresponding HTML file in the HTML_PATH
+ if [ -f "$HTML_PATH" ]; then
+ # HTML_PATH is a single file, only check if it matches
+ html_file_name=$(basename "$HTML_PATH" .html)
+ if [ "$base_name" = "$html_file_name" ]; then
+ FILES+=("$HTML_PATH")
+ echo "Mapped $md_file -> $HTML_PATH"
+ fi
+ else
+ # HTML_PATH is a directory, search for corresponding HTML file
+ # Try different possible mappings
+ possible_paths=(
+ "$HTML_PATH/$base_name.html"
+ "$HTML_PATH/$(dirname "$md_file")/$base_name.html"
+ )
- # Look for the corresponding HTML file in the HTML_PATH
- if [ -f "$HTML_PATH" ]; then
- # HTML_PATH is a single file, only check if it matches
- html_file_name=$(basename "$HTML_PATH" .html)
- if [ "$base_name" = "$html_file_name" ]; then
- FILES+=("$HTML_PATH")
- echo "Mapped $md_file -> $HTML_PATH"
+ for html_path in "${possible_paths[@]}"; do
+ if [ -f "$html_path" ]; then
+ FILES+=("$html_path")
+ echo "Mapped $md_file -> $html_path"
+ break
fi
- else
- # HTML_PATH is a directory, search for corresponding HTML file
- # Try different possible mappings
- possible_paths=(
- "$HTML_PATH/$base_name.html"
- "$HTML_PATH/$(dirname "$md_file")/$base_name.html"
- )
-
- for html_path in "${possible_paths[@]}"; do
- if [ -f "$html_path" ]; then
- FILES+=("$html_path")
- echo "Mapped $md_file -> $html_path"
- break
- fi
- done
-
- # If no exact match found, search recursively
- if ! printf '%s\n' "${FILES[@]}" | grep -q "/$base_name.html"; then
- found_file=$(find "$HTML_PATH" -name "$base_name.html" -type f | head -1)
- if [ -n "$found_file" ]; then
- FILES+=("$found_file")
- echo "Mapped $md_file -> $found_file (found recursively)"
- else
- echo "Warning: No corresponding HTML file found for $md_file (searched for $base_name.html)"
- fi
+ done
+
+ # If no exact match found, search recursively
+ if ! printf '%s\n' "${FILES[@]}" | grep -q "/$base_name.html"; then
+ found_file=$(find "$HTML_PATH" -name "$base_name.html" -type f | head -1)
+ if [ -n "$found_file" ]; then
+ FILES+=("$found_file")
+ echo "Mapped $md_file -> $found_file (found recursively)"
+ else
+ echo "Warning: No corresponding HTML file found for $md_file (searched for $base_name.html)"
fi
fi
- done
-
- if [ ${#FILES[@]} -eq 0 ]; then
- echo "No HTML files found corresponding to changed .md files"
- else
- echo "Will check ${#FILES[@]} HTML file(s) in PR mode"
fi
+ done
+
+ if [ ${#FILES[@]} -eq 0 ]; then
+ echo "No HTML files found corresponding to changed .md files"
+ else
+ echo "Will check ${#FILES[@]} HTML file(s) in PR mode"
fi
else
# Normal mode - find all HTML files or use specified file
From 4832c34226f4874e55204fd2429c567d3237c15c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 Aug 2025 06:49:59 +0000
Subject: [PATCH 07/11] Fix git branch reference issue in PR mode test by
fetching main branch
Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com>
---
.github/workflows/test-warning-check.yml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.github/workflows/test-warning-check.yml b/.github/workflows/test-warning-check.yml
index 35bd475..4bd2dbd 100644
--- a/.github/workflows/test-warning-check.yml
+++ b/.github/workflows/test-warning-check.yml
@@ -365,6 +365,9 @@ jobs:
git config user.email "test@example.com"
git config user.name "Test User"
+ # Fetch the main branch from origin so it exists locally
+ git fetch origin main:main
+
# Create a test scenario: commit current state, modify a .md file, then test
git add -A
git commit -m "Base state for PR mode test" || echo "Nothing to commit"
From 0fa64cb91b64c411f32469fbd8175edf1d65bf6c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 Aug 2025 06:57:19 +0000
Subject: [PATCH 08/11] Change PR mode to exit early when no .md files changed
instead of falling back to normal mode
Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com>
---
.github/actions/check-warnings/action.yml | 2 +-
.../actions/check-warnings/check-warnings.sh | 16 +++++++++++++---
.github/workflows/test-warning-check.yml | 19 ++++++++++++-------
3 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/.github/actions/check-warnings/action.yml b/.github/actions/check-warnings/action.yml
index eb1611c..bbcafeb 100755
--- a/.github/actions/check-warnings/action.yml
+++ b/.github/actions/check-warnings/action.yml
@@ -40,7 +40,7 @@ inputs:
required: false
default: ''
pr-mode:
- description: 'When enabled, only check HTML files corresponding to changed .md files in the PR (requires git repository context)'
+ description: 'When enabled, only check HTML files corresponding to changed .md files in the PR. If no .md files changed, exits early with no warnings found (requires git repository context)'
required: false
default: 'false'
diff --git a/.github/actions/check-warnings/check-warnings.sh b/.github/actions/check-warnings/check-warnings.sh
index 047d89d..42b20d3 100755
--- a/.github/actions/check-warnings/check-warnings.sh
+++ b/.github/actions/check-warnings/check-warnings.sh
@@ -132,9 +132,19 @@ if [ "$PR_MODE" = "true" ]; then
PR_MODE="false"
fi
- if [ ${#CHANGED_MD_FILES[@]} -eq 0 ]; then
- echo "No .md files changed in this PR - falling back to normal mode"
- PR_MODE="false"
+ # Only exit early if git is available but no .md files changed
+ # If git is not available, we already fell back to normal mode above
+ if [ "$PR_MODE" = "true" ] && [ ${#CHANGED_MD_FILES[@]} -eq 0 ]; then
+ echo "📝 No .md files changed in this PR - no HTML files need to be checked"
+ echo "✅ Exiting successfully as no documentation files were modified"
+
+ # Set outputs for no warnings found
+ echo "warnings-found=false" >> $GITHUB_OUTPUT
+ echo "warning-count=0" >> $GITHUB_OUTPUT
+ echo "warning-details=" >> $GITHUB_OUTPUT
+ echo "detailed-report=" >> $GITHUB_OUTPUT
+
+ exit 0
fi
fi
diff --git a/.github/workflows/test-warning-check.yml b/.github/workflows/test-warning-check.yml
index 4bd2dbd..bb5c03e 100644
--- a/.github/workflows/test-warning-check.yml
+++ b/.github/workflows/test-warning-check.yml
@@ -326,12 +326,12 @@ jobs:
test-pr-mode-basic:
runs-on: ubuntu-latest
- name: Test PR mode basic functionality
+ name: Test PR mode early exit when no .md files changed
steps:
- name: Checkout
uses: actions/checkout@v4
- - name: Test PR mode with non-git context (should fallback to normal mode)
+ - name: Test PR mode with no changed .md files (should exit early)
id: pr-mode-fallback-test
uses: .//.github/actions/check-warnings
with:
@@ -339,18 +339,23 @@ jobs:
pr-mode: 'true'
fail-on-warning: 'false'
- - name: Verify fallback results
+ - name: Verify early exit results
run: |
echo "Warnings found: ${{ steps.pr-mode-fallback-test.outputs.warnings-found }}"
echo "Warning count: ${{ steps.pr-mode-fallback-test.outputs.warning-count }}"
- # Should find warnings since it falls back to normal mode
- if [ "${{ steps.pr-mode-fallback-test.outputs.warnings-found }}" != "true" ]; then
- echo "❌ Expected warnings in fallback mode but found none"
+ # Should find no warnings since no .md files changed and it exits early
+ if [ "${{ steps.pr-mode-fallback-test.outputs.warnings-found }}" != "false" ]; then
+ echo "❌ Expected no warnings when no .md files changed but found some"
exit 1
fi
- echo "✅ PR mode fallback test passed"
+ if [ "${{ steps.pr-mode-fallback-test.outputs.warning-count }}" != "0" ]; then
+ echo "❌ Expected 0 warnings when no .md files changed but found ${{ steps.pr-mode-fallback-test.outputs.warning-count }}"
+ exit 1
+ fi
+
+ echo "✅ PR mode early exit test passed"
test-pr-mode-simulation:
runs-on: ubuntu-latest
From 76f4242bb8baa530c54501aa09b9f3d999261bb3 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 Aug 2025 07:14:45 +0000
Subject: [PATCH 09/11] Fix PR mode git diff logic to properly handle
environments where origin/main isn't available
Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com>
---
.../actions/check-warnings/check-warnings.sh | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/.github/actions/check-warnings/check-warnings.sh b/.github/actions/check-warnings/check-warnings.sh
index 42b20d3..1154262 100755
--- a/.github/actions/check-warnings/check-warnings.sh
+++ b/.github/actions/check-warnings/check-warnings.sh
@@ -91,10 +91,25 @@ if [ "$PR_MODE" = "true" ]; then
# Try different comparison strategies in order of preference
if git rev-parse --verify "origin/$BASE_REF" >/dev/null 2>&1; then
echo "Using origin/$BASE_REF for comparison"
- mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "origin/$BASE_REF"...HEAD | grep '\.md$' || true)
+ # Try three-dot syntax first, fallback to two-dot if no merge base
+ if ! mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "origin/$BASE_REF"...HEAD 2>/dev/null | grep '\.md$' || true); then
+ echo "Three-dot syntax failed, trying two-dot syntax"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "origin/$BASE_REF"..HEAD | grep '\.md$' || true)
+ fi
+ elif git rev-parse --verify "FETCH_HEAD" >/dev/null 2>&1; then
+ echo "Using FETCH_HEAD for comparison (after fetch)"
+ # Try three-dot syntax first, fallback to two-dot if no merge base
+ if ! mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "FETCH_HEAD"...HEAD 2>/dev/null | grep '\.md$' || true); then
+ echo "Three-dot syntax failed, trying two-dot syntax"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "FETCH_HEAD"..HEAD | grep '\.md$' || true)
+ fi
elif git rev-parse --verify "$BASE_REF" >/dev/null 2>&1; then
echo "Using $BASE_REF for comparison"
- mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"...HEAD | grep '\.md$' || true)
+ # Try three-dot syntax first, fallback to two-dot if no merge base
+ if ! mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"...HEAD 2>/dev/null | grep '\.md$' || true); then
+ echo "Three-dot syntax failed, trying two-dot syntax"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"..HEAD | grep '\.md$' || true)
+ fi
else
echo "Warning: Could not find base reference, using merge-base with origin/HEAD"
# Try to find merge base with origin/HEAD
From ad771988cc531ac1fbead20fb9308220aee1c103 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 Aug 2025 08:13:16 +0000
Subject: [PATCH 10/11] Fix PR mode git diff logic to properly detect changed
.md files
Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com>
---
.../actions/check-warnings/check-warnings.sh | 21 +++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/.github/actions/check-warnings/check-warnings.sh b/.github/actions/check-warnings/check-warnings.sh
index 1154262..257e229 100755
--- a/.github/actions/check-warnings/check-warnings.sh
+++ b/.github/actions/check-warnings/check-warnings.sh
@@ -92,22 +92,31 @@ if [ "$PR_MODE" = "true" ]; then
if git rev-parse --verify "origin/$BASE_REF" >/dev/null 2>&1; then
echo "Using origin/$BASE_REF for comparison"
# Try three-dot syntax first, fallback to two-dot if no merge base
- if ! mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "origin/$BASE_REF"...HEAD 2>/dev/null | grep '\.md$' || true); then
- echo "Three-dot syntax failed, trying two-dot syntax"
+ if git diff --name-only --diff-filter=AM "origin/$BASE_REF"...HEAD >/dev/null 2>&1; then
+ echo "Using three-dot syntax with origin/$BASE_REF"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "origin/$BASE_REF"...HEAD | grep '\.md$' || true)
+ else
+ echo "Three-dot syntax failed, trying two-dot syntax with origin/$BASE_REF"
mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "origin/$BASE_REF"..HEAD | grep '\.md$' || true)
fi
elif git rev-parse --verify "FETCH_HEAD" >/dev/null 2>&1; then
echo "Using FETCH_HEAD for comparison (after fetch)"
# Try three-dot syntax first, fallback to two-dot if no merge base
- if ! mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "FETCH_HEAD"...HEAD 2>/dev/null | grep '\.md$' || true); then
- echo "Three-dot syntax failed, trying two-dot syntax"
+ if git diff --name-only --diff-filter=AM "FETCH_HEAD"...HEAD >/dev/null 2>&1; then
+ echo "Using three-dot syntax with FETCH_HEAD"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "FETCH_HEAD"...HEAD | grep '\.md$' || true)
+ else
+ echo "Three-dot syntax failed, trying two-dot syntax with FETCH_HEAD"
mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "FETCH_HEAD"..HEAD | grep '\.md$' || true)
fi
elif git rev-parse --verify "$BASE_REF" >/dev/null 2>&1; then
echo "Using $BASE_REF for comparison"
# Try three-dot syntax first, fallback to two-dot if no merge base
- if ! mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"...HEAD 2>/dev/null | grep '\.md$' || true); then
- echo "Three-dot syntax failed, trying two-dot syntax"
+ if git diff --name-only --diff-filter=AM "$BASE_REF"...HEAD >/dev/null 2>&1; then
+ echo "Using three-dot syntax with $BASE_REF"
+ mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"...HEAD | grep '\.md$' || true)
+ else
+ echo "Three-dot syntax failed, trying two-dot syntax with $BASE_REF"
mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"..HEAD | grep '\.md$' || true)
fi
else
From 789b2080beb4f1216c9bc2a83b27e2c45e1a219d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 25 Aug 2025 11:08:26 +0000
Subject: [PATCH 11/11] Fix git diff logic in PR mode to use merge-base instead
of testing git diff commands twice
Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com>
---
.github/actions/check-warnings/check-warnings.sh | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/.github/actions/check-warnings/check-warnings.sh b/.github/actions/check-warnings/check-warnings.sh
index 257e229..88f4ea9 100755
--- a/.github/actions/check-warnings/check-warnings.sh
+++ b/.github/actions/check-warnings/check-warnings.sh
@@ -92,31 +92,31 @@ if [ "$PR_MODE" = "true" ]; then
if git rev-parse --verify "origin/$BASE_REF" >/dev/null 2>&1; then
echo "Using origin/$BASE_REF for comparison"
# Try three-dot syntax first, fallback to two-dot if no merge base
- if git diff --name-only --diff-filter=AM "origin/$BASE_REF"...HEAD >/dev/null 2>&1; then
+ if git merge-base "origin/$BASE_REF" HEAD >/dev/null 2>&1; then
echo "Using three-dot syntax with origin/$BASE_REF"
mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "origin/$BASE_REF"...HEAD | grep '\.md$' || true)
else
- echo "Three-dot syntax failed, trying two-dot syntax with origin/$BASE_REF"
+ echo "No merge base found, trying two-dot syntax with origin/$BASE_REF"
mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "origin/$BASE_REF"..HEAD | grep '\.md$' || true)
fi
elif git rev-parse --verify "FETCH_HEAD" >/dev/null 2>&1; then
echo "Using FETCH_HEAD for comparison (after fetch)"
# Try three-dot syntax first, fallback to two-dot if no merge base
- if git diff --name-only --diff-filter=AM "FETCH_HEAD"...HEAD >/dev/null 2>&1; then
+ if git merge-base "FETCH_HEAD" HEAD >/dev/null 2>&1; then
echo "Using three-dot syntax with FETCH_HEAD"
mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "FETCH_HEAD"...HEAD | grep '\.md$' || true)
else
- echo "Three-dot syntax failed, trying two-dot syntax with FETCH_HEAD"
+ echo "No merge base found, trying two-dot syntax with FETCH_HEAD"
mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "FETCH_HEAD"..HEAD | grep '\.md$' || true)
fi
elif git rev-parse --verify "$BASE_REF" >/dev/null 2>&1; then
echo "Using $BASE_REF for comparison"
# Try three-dot syntax first, fallback to two-dot if no merge base
- if git diff --name-only --diff-filter=AM "$BASE_REF"...HEAD >/dev/null 2>&1; then
+ if git merge-base "$BASE_REF" HEAD >/dev/null 2>&1; then
echo "Using three-dot syntax with $BASE_REF"
mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"...HEAD | grep '\.md$' || true)
else
- echo "Three-dot syntax failed, trying two-dot syntax with $BASE_REF"
+ echo "No merge base found, trying two-dot syntax with $BASE_REF"
mapfile -t CHANGED_MD_FILES < <(git diff --name-only --diff-filter=AM "$BASE_REF"..HEAD | grep '\.md$' || true)
fi
else