Skip to content

Commit e1c0394

Browse files
Copilotmmcky
andcommitted
Add glob pattern support to code-style-checker action
Co-authored-by: mmcky <[email protected]>
1 parent 6299052 commit e1c0394

File tree

4 files changed

+240
-15
lines changed

4 files changed

+240
-15
lines changed

.github/actions/code-style-checker/README.md

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ A GitHub Action that automatically formats Python code in MyST markdown files an
2020
- name: Format Python code in markdown files
2121
uses: QuantEcon/meta/.github/actions/code-style-checker@main
2222
with:
23-
files: 'lecture/aiyagari.md,lecture/mccall.md'
23+
files: 'lecture/**/*.md'
2424
check-myst-code-cells: 'true'
2525
check-markdown-blocks: 'true'
2626
python-languages: 'python,python3,ipython,ipython3'
@@ -69,7 +69,7 @@ jobs:
6969

7070
| Input | Description | Required | Default |
7171
|-------|-------------|----------|---------|
72-
| `files` | Comma-separated list of markdown files to process | ✅ | |
72+
| `files` | Comma-separated list of markdown files to process or glob patterns (e.g., `lecture/**/*.md`) | ✅ | |
7373
| `check-myst-code-cells` | Enable processing of MyST `{code-cell}` directives | ❌ | `true` |
7474
| `check-markdown-blocks` | Enable processing of standard markdown fenced code blocks | ❌ | `true` |
7575
| `python-languages` | Comma-separated list of language identifiers to treat as Python | ❌ | `python,python3,ipython,ipython3` |
@@ -143,14 +143,54 @@ The action will:
143143
5. **File Updates**: Replaces original code blocks with formatted versions
144144
6. **Git Operations**: Commits each modified file individually with descriptive commit messages
145145

146+
## File Input Formats
147+
148+
The `files` input accepts multiple formats:
149+
150+
### Explicit File Paths
151+
Comma-separated list of specific file paths:
152+
```yaml
153+
files: 'lecture/aiyagari.md,lecture/mccall.md,examples/optimization.md'
154+
```
155+
156+
### Glob Patterns
157+
Use shell glob patterns to match multiple files:
158+
```yaml
159+
# All markdown files in lecture directory and subdirectories
160+
files: 'lecture/**/*.md'
161+
162+
# All markdown files in specific directories
163+
files: 'lecture/*.md,examples/*.md'
164+
165+
# Mixed patterns and explicit files
166+
files: 'lecture/**/*.md,specific-file.md'
167+
```
168+
169+
### Supported Glob Patterns
170+
- `*` - matches any characters (excluding path separators)
171+
- `**` - matches any characters including path separators (recursive)
172+
- `?` - matches any single character
173+
- `[abc]` - matches any character in the set
174+
- `[a-z]` - matches any character in the range
175+
146176
## Configuration Examples
147177

178+
### Process All Files in Directory
179+
180+
```yaml
181+
- uses: QuantEcon/meta/.github/actions/code-style-checker@main
182+
with:
183+
files: 'lecture/**/*.md'
184+
check-myst-code-cells: 'true'
185+
check-markdown-blocks: 'false'
186+
```
187+
148188
### Only Process MyST Code-Cells
149189

150190
```yaml
151191
- uses: QuantEcon/meta/.github/actions/code-style-checker@main
152192
with:
153-
files: 'lecture/*.md'
193+
files: 'lecture/**/*.md'
154194
check-myst-code-cells: 'true'
155195
check-markdown-blocks: 'false'
156196
```

.github/actions/code-style-checker/action.yml

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ author: 'QuantEcon'
44

55
inputs:
66
files:
7-
description: 'Comma-separated list of markdown files to process'
7+
description: 'Comma-separated list of markdown files to process or glob patterns (e.g., "lecture/**/*.md")'
88
required: true
99
check-myst-code-cells:
1010
description: 'Enable searching for Python code in MyST code-cell directives'
@@ -83,10 +83,46 @@ runs:
8383
echo "Python languages: $PYTHON_LANGS"
8484
echo "Black arguments: $BLACK_ARGS"
8585
86-
# Convert comma-separated inputs to arrays
87-
IFS=',' read -ra FILE_ARRAY <<< "$FILES"
86+
# Convert comma-separated inputs to arrays and expand glob patterns
87+
IFS=',' read -ra FILE_INPUT_ARRAY <<< "$FILES"
8888
IFS=',' read -ra LANG_ARRAY <<< "$PYTHON_LANGS"
8989
90+
# Expand glob patterns to actual file paths
91+
FILE_ARRAY=()
92+
for pattern in "${FILE_INPUT_ARRAY[@]}"; do
93+
# Remove leading/trailing whitespace
94+
pattern=$(echo "$pattern" | xargs)
95+
96+
# Check if pattern contains glob characters
97+
if [[ "$pattern" == *"*"* || "$pattern" == *"?"* || "$pattern" == *"["* ]]; then
98+
echo "🔍 Expanding glob pattern: $pattern"
99+
# Use bash glob expansion with nullglob to handle no matches
100+
shopt -s nullglob
101+
expanded_files=($pattern)
102+
shopt -u nullglob
103+
104+
if [ ${#expanded_files[@]} -eq 0 ]; then
105+
echo "⚠️ No files found matching pattern: $pattern"
106+
else
107+
echo " Found ${#expanded_files[@]} file(s) matching pattern"
108+
for file in "${expanded_files[@]}"; do
109+
# Only add markdown files
110+
if [[ "$file" == *.md ]]; then
111+
FILE_ARRAY+=("$file")
112+
echo " + $file"
113+
else
114+
echo " - Skipping non-markdown file: $file"
115+
fi
116+
done
117+
fi
118+
else
119+
# Direct file path (original behavior)
120+
FILE_ARRAY+=("$pattern")
121+
fi
122+
done
123+
124+
echo "📂 Total files to process: ${#FILE_ARRAY[@]}"
125+
90126
# Initialize counters
91127
FILES_PROCESSED=0
92128
FILES_CHANGED=0
@@ -273,7 +309,12 @@ EOF
273309

274310
# Process each file
275311
for file in "${FILE_ARRAY[@]}"; do
276-
# Remove leading/trailing whitespace
312+
# Skip empty entries
313+
if [ -z "$file" ]; then
314+
continue
315+
fi
316+
317+
# Remove leading/trailing whitespace (for explicit file paths)
277318
file=$(echo "$file" | xargs)
278319

279320
if [ ! -f "$file" ]; then

.github/actions/code-style-checker/examples.md

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,32 @@ jobs:
3737
run: git push
3838
```
3939
40+
### Format All Markdown Files Using Glob Patterns
41+
42+
```yaml
43+
- name: Format all lecture files
44+
uses: QuantEcon/meta/.github/actions/code-style-checker@main
45+
with:
46+
files: 'lectures/**/*.md'
47+
48+
- name: Format multiple directories
49+
uses: QuantEcon/meta/.github/actions/code-style-checker@main
50+
with:
51+
files: 'lectures/**/*.md,examples/**/*.md,notebooks/**/*.md'
52+
```
53+
4054
### Format All Markdown Files
4155
4256
```yaml
43-
- name: Get all markdown files
44-
id: get-files
45-
run: |
46-
files=$(find . -name "*.md" -type f | paste -sd "," -)
47-
echo "files=$files" >> $GITHUB_OUTPUT
57+
- name: Get all markdown files using glob pattern
58+
uses: QuantEcon/meta/.github/actions/code-style-checker@main
59+
with:
60+
files: '**/*.md'
4861

49-
- name: Format all markdown files
62+
- name: Format specific directories
5063
uses: QuantEcon/meta/.github/actions/code-style-checker@main
5164
with:
52-
files: ${{ steps.get-files.outputs.files }}
65+
files: 'lectures/**/*.md,examples/**/*.md'
5366
```
5467
5568
## Trigger on PR Comments

.github/workflows/test-code-style-checker.yml

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,4 +300,135 @@ jobs:
300300
exit 1
301301
fi
302302
303-
echo "✅ Multiple files test passed"
303+
echo "✅ Multiple files test passed"
304+
305+
test-glob-patterns:
306+
runs-on: ubuntu-latest
307+
name: Test glob pattern support
308+
steps:
309+
- name: Checkout
310+
uses: actions/checkout@v4
311+
312+
- name: Setup test environment
313+
run: |
314+
# Create test directory structure
315+
mkdir -p /tmp/glob-test/subdir
316+
317+
# Create test files with Python code
318+
cat > /tmp/glob-test/file1.md << 'EOF'
319+
# Test File 1
320+
```python
321+
def test_function(x,y):
322+
return x+y
323+
```
324+
EOF
325+
326+
cat > /tmp/glob-test/subdir/file2.md << 'EOF'
327+
# Test File 2
328+
```{code-cell} python
329+
def another_function(a,b):
330+
result=a+b
331+
return result
332+
```
333+
EOF
334+
335+
cat > /tmp/glob-test/not-markdown.txt << 'EOF'
336+
This is not a markdown file
337+
EOF
338+
339+
- name: Test action with glob pattern
340+
id: glob-test
341+
uses: .//.github/actions/code-style-checker
342+
with:
343+
files: '/tmp/glob-test/**/*.md'
344+
commit-files: 'false' # Don't commit during tests
345+
346+
- name: Verify glob pattern results
347+
run: |
348+
echo "Files processed: ${{ steps.glob-test.outputs.files-processed }}"
349+
echo "Files changed: ${{ steps.glob-test.outputs.files-changed }}"
350+
echo "Blocks formatted: ${{ steps.glob-test.outputs.total-blocks-formatted }}"
351+
echo "Changes made: ${{ steps.glob-test.outputs.changes-made }}"
352+
353+
if [ "${{ steps.glob-test.outputs.files-processed }}" != "2" ]; then
354+
echo "❌ Expected 2 files processed but got ${{ steps.glob-test.outputs.files-processed }}"
355+
exit 1
356+
fi
357+
358+
if [ "${{ steps.glob-test.outputs.changes-made }}" != "true" ]; then
359+
echo "❌ Expected changes to be made but none were made"
360+
exit 1
361+
fi
362+
363+
if [ "${{ steps.glob-test.outputs.files-changed }}" != "2" ]; then
364+
echo "❌ Expected 2 files changed but got ${{ steps.glob-test.outputs.files-changed }}"
365+
exit 1
366+
fi
367+
368+
if [ "${{ steps.glob-test.outputs.total-blocks-formatted }}" != "2" ]; then
369+
echo "❌ Expected 2 blocks formatted but got ${{ steps.glob-test.outputs.total-blocks-formatted }}"
370+
exit 1
371+
fi
372+
373+
echo "✅ Glob pattern test passed"
374+
375+
test-mixed-input:
376+
runs-on: ubuntu-latest
377+
name: Test mixed glob patterns and explicit files
378+
steps:
379+
- name: Checkout
380+
uses: actions/checkout@v4
381+
382+
- name: Setup test environment
383+
run: |
384+
# Create test directory
385+
mkdir -p /tmp/mixed-test
386+
387+
# Create a test file with Python code
388+
cat > /tmp/mixed-test/glob-file.md << 'EOF'
389+
# Glob File
390+
```python
391+
def glob_function(x,y):
392+
return x+y
393+
```
394+
EOF
395+
396+
# Use existing test file as explicit file
397+
cp test/code-style-checker/unformatted-code.md /tmp/explicit-file.md
398+
399+
- name: Test action with mixed input
400+
id: mixed-test
401+
uses: .//.github/actions/code-style-checker
402+
with:
403+
files: '/tmp/mixed-test/*.md,/tmp/explicit-file.md'
404+
commit-files: 'false' # Don't commit during tests
405+
406+
- name: Verify mixed input results
407+
run: |
408+
echo "Files processed: ${{ steps.mixed-test.outputs.files-processed }}"
409+
echo "Files changed: ${{ steps.mixed-test.outputs.files-changed }}"
410+
echo "Blocks formatted: ${{ steps.mixed-test.outputs.total-blocks-formatted }}"
411+
echo "Changes made: ${{ steps.mixed-test.outputs.changes-made }}"
412+
413+
if [ "${{ steps.mixed-test.outputs.files-processed }}" != "2" ]; then
414+
echo "❌ Expected 2 files processed but got ${{ steps.mixed-test.outputs.files-processed }}"
415+
exit 1
416+
fi
417+
418+
if [ "${{ steps.mixed-test.outputs.changes-made }}" != "true" ]; then
419+
echo "❌ Expected changes to be made but none were made"
420+
exit 1
421+
fi
422+
423+
if [ "${{ steps.mixed-test.outputs.files-changed }}" != "2" ]; then
424+
echo "❌ Expected 2 files changed but got ${{ steps.mixed-test.outputs.files-changed }}"
425+
exit 1
426+
fi
427+
428+
# Should format 1 block from glob file + at least 4 from explicit file
429+
if [ "${{ steps.mixed-test.outputs.total-blocks-formatted }}" -lt "5" ]; then
430+
echo "❌ Expected at least 5 blocks formatted but got ${{ steps.mixed-test.outputs.total-blocks-formatted }}"
431+
exit 1
432+
fi
433+
434+
echo "✅ Mixed input test passed"

0 commit comments

Comments
 (0)