Skip to content

Commit a4a4ea5

Browse files
Copilotmmcky
andauthored
Add GitHub Action for efficient weekly QuantEcon organization reporting with repository exclusion and optimized CI workflows (#206)
* Initial plan * Implement weekly report GitHub Action for QuantEcon organization Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com> * Optimize repository filtering using GitHub Search API for recent activity Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com> * Restrict test-warning-check workflow to run only on relevant file changes Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com> * Add exclude-repos option to weekly-report action for filtering repositories Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com> * Add exclude-paths feature to check-warnings action to skip test directories Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com> * Revert all changes to check-warnings action Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com> * Remove self-referential path filter from test-warning-check workflow Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: mmcky <8263752+mmcky@users.noreply.github.com>
1 parent 07e1957 commit a4a4ea5

File tree

9 files changed

+480
-1
lines changed

9 files changed

+480
-1
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# QuantEcon Weekly Report Action
2+
3+
A GitHub Action that generates a weekly report summarizing activity across all repositories in the QuantEcon organization.
4+
5+
## Features
6+
7+
This action generates a report containing:
8+
- Number of issues opened by repository (last 7 days)
9+
- Number of issues closed by repository (last 7 days)
10+
- Number of PRs merged by repository (last 7 days)
11+
- Summary totals across all repositories
12+
13+
### Efficiency Features
14+
- **Smart repository filtering**: Uses GitHub Search API to identify repositories with recent activity (commits in the last 7 days) before checking for issues and PRs
15+
- **Fallback mechanism**: If no repositories are found with recent commits, falls back to checking all organization repositories to ensure complete coverage
16+
- **Activity-based reporting**: Only includes repositories with actual activity in the generated report
17+
18+
## Usage
19+
20+
```yaml
21+
- name: Generate weekly report
22+
uses: QuantEcon/meta/.github/actions/weekly-report@main
23+
with:
24+
github-token: ${{ secrets.GITHUB_TOKEN }}
25+
organization: 'QuantEcon'
26+
output-format: 'markdown'
27+
exclude-repos: 'lecture-python.notebooks,auto-updated-repo'
28+
```
29+
30+
## Inputs
31+
32+
| Input | Description | Required | Default |
33+
|-------|-------------|----------|---------|
34+
| `github-token` | GitHub token with access to the organization | Yes | - |
35+
| `organization` | GitHub organization name | No | `QuantEcon` |
36+
| `output-format` | Output format (`markdown` or `json`) | No | `markdown` |
37+
| `exclude-repos` | Comma-separated list of repository names to exclude from the report | No | `''` |
38+
39+
## Outputs
40+
41+
| Output | Description |
42+
|--------|-------------|
43+
| `report-content` | The full generated report content |
44+
| `report-summary` | A brief summary of the report metrics |
45+
46+
## Permissions
47+
48+
The GitHub token must have read access to:
49+
- Organization repositories
50+
- Repository issues
51+
- Repository pull requests
52+
53+
## Example Workflow
54+
55+
See the [weekly report workflow](../../workflows/weekly-report.yml) for a complete example that runs every Saturday and creates an issue with the report.
56+
57+
## Report Format
58+
59+
The generated markdown report includes:
60+
- A summary table showing activity by repository
61+
- Total counts across all repositories
62+
- Report metadata (generation date, period covered)
63+
64+
Only repositories with activity in the reporting period are included in the detailed table.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: 'QuantEcon Weekly Report'
2+
description: 'Generate a weekly report of issues and PRs across QuantEcon repositories'
3+
author: 'QuantEcon'
4+
5+
inputs:
6+
github-token:
7+
description: 'GitHub token with access to the QuantEcon organization'
8+
required: true
9+
organization:
10+
description: 'GitHub organization name'
11+
required: false
12+
default: 'QuantEcon'
13+
output-format:
14+
description: 'Output format for the report (markdown, json)'
15+
required: false
16+
default: 'markdown'
17+
exclude-repos:
18+
description: 'Comma-separated list of repository names to exclude from the report'
19+
required: false
20+
default: ''
21+
22+
outputs:
23+
report-content:
24+
description: 'The generated weekly report content'
25+
report-summary:
26+
description: 'A brief summary of the report metrics'
27+
28+
runs:
29+
using: 'composite'
30+
steps:
31+
- name: Generate weekly report
32+
shell: bash
33+
run: ${{ github.action_path }}/generate-report.sh
34+
env:
35+
INPUT_GITHUB_TOKEN: ${{ inputs.github-token }}
36+
INPUT_ORGANIZATION: ${{ inputs.organization }}
37+
INPUT_OUTPUT_FORMAT: ${{ inputs.output-format }}
38+
INPUT_EXCLUDE_REPOS: ${{ inputs.exclude-repos }}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Get inputs
5+
GITHUB_TOKEN="${INPUT_GITHUB_TOKEN}"
6+
ORGANIZATION="${INPUT_ORGANIZATION:-QuantEcon}"
7+
OUTPUT_FORMAT="${INPUT_OUTPUT_FORMAT:-markdown}"
8+
EXCLUDE_REPOS="${INPUT_EXCLUDE_REPOS:-}"
9+
10+
# Date calculations for last week
11+
WEEK_AGO=$(date -d "7 days ago" -u +"%Y-%m-%dT%H:%M:%SZ")
12+
NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
13+
14+
echo "Generating weekly report for ${ORGANIZATION} organization"
15+
echo "Period: ${WEEK_AGO} to ${NOW}"
16+
17+
# Function to make GitHub API calls
18+
api_call() {
19+
local endpoint="$1"
20+
local page="${2:-1}"
21+
curl -s -H "Authorization: token ${GITHUB_TOKEN}" \
22+
-H "Accept: application/vnd.github.v3+json" \
23+
"https://api.github.com${endpoint}?page=${page}&per_page=100"
24+
}
25+
26+
# Get repositories with recent activity using GitHub Search API
27+
echo "Fetching repositories with recent activity for ${ORGANIZATION}..."
28+
29+
# Search for repositories with recent commits, issues, or PRs in the last week
30+
WEEK_AGO_DATE=$(date -d "7 days ago" -u +"%Y-%m-%d")
31+
32+
# Use search API to find repos with recent activity
33+
search_query="org:${ORGANIZATION} pushed:>${WEEK_AGO_DATE}"
34+
search_response=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \
35+
-H "Accept: application/vnd.github.v3+json" \
36+
"https://api.github.com/search/repositories?q=$(echo "$search_query" | sed 's/ /%20/g')&per_page=100")
37+
38+
repo_names=$(echo "$search_response" | jq -r '.items[]?.name // empty')
39+
40+
# If no repos found with recent commits, fall back to checking all org repos
41+
# This ensures we don't miss repos that might have issues/PRs but no commits
42+
if [ -z "$repo_names" ]; then
43+
echo "No repositories found with recent commits, checking all organization repositories..."
44+
repos_response=$(api_call "/orgs/${ORGANIZATION}/repos")
45+
repo_names=$(echo "$repos_response" | jq -r '.[].name // empty')
46+
47+
if [ -z "$repo_names" ]; then
48+
echo "No repositories found or API call failed"
49+
exit 1
50+
fi
51+
else
52+
echo "Found repositories with recent activity:"
53+
echo "$repo_names" | head -10 # Show first 10 for logging
54+
fi
55+
56+
# Filter out excluded repositories if any are specified
57+
if [ -n "$EXCLUDE_REPOS" ]; then
58+
echo "Excluding repositories: $EXCLUDE_REPOS"
59+
# Convert comma-separated list to array and filter out excluded repos
60+
IFS=',' read -ra exclude_array <<< "$EXCLUDE_REPOS"
61+
filtered_repos=""
62+
while IFS= read -r repo; do
63+
[ -z "$repo" ] && continue
64+
excluded=false
65+
for exclude_repo in "${exclude_array[@]}"; do
66+
# Trim whitespace and compare
67+
exclude_repo=$(echo "$exclude_repo" | xargs)
68+
if [ "$repo" = "$exclude_repo" ]; then
69+
excluded=true
70+
echo "Excluding repository: $repo"
71+
break
72+
fi
73+
done
74+
if [ "$excluded" = false ]; then
75+
if [ -z "$filtered_repos" ]; then
76+
filtered_repos="$repo"
77+
else
78+
filtered_repos="$filtered_repos"$'\n'"$repo"
79+
fi
80+
fi
81+
done <<< "$repo_names"
82+
repo_names="$filtered_repos"
83+
fi
84+
85+
# Initialize report variables
86+
total_opened_issues=0
87+
total_closed_issues=0
88+
total_merged_prs=0
89+
report_content=""
90+
91+
# Start building the report
92+
if [ "$OUTPUT_FORMAT" = "markdown" ]; then
93+
report_content="# QuantEcon Weekly Report\n\n"
94+
report_content+="**Report Period:** $(date -d "$WEEK_AGO" '+%B %d, %Y') - $(date -d "$NOW" '+%B %d, %Y')\n\n"
95+
report_content+="## Summary\n\n"
96+
report_content+="| Repository | Opened Issues | Closed Issues | Merged PRs |\n"
97+
report_content+="|------------|---------------|---------------|------------|\n"
98+
fi
99+
100+
# Process each repository
101+
while IFS= read -r repo; do
102+
[ -z "$repo" ] && continue
103+
104+
echo "Processing repository: $repo"
105+
106+
# Count opened issues in the last week
107+
opened_issues=$(api_call "/repos/${ORGANIZATION}/${repo}/issues" | \
108+
jq --arg since "$WEEK_AGO" '[.[] | select(.created_at >= $since and .pull_request == null)] | length')
109+
110+
# Count closed issues in the last week
111+
closed_issues=$(api_call "/repos/${ORGANIZATION}/${repo}/issues?state=closed" | \
112+
jq --arg since "$WEEK_AGO" '[.[] | select(.closed_at >= $since and .pull_request == null)] | length')
113+
114+
# Count merged PRs in the last week
115+
merged_prs=$(api_call "/repos/${ORGANIZATION}/${repo}/pulls?state=closed" | \
116+
jq --arg since "$WEEK_AGO" '[.[] | select(.merged_at != null and .merged_at >= $since)] | length')
117+
118+
# Handle null/empty values
119+
opened_issues=${opened_issues:-0}
120+
closed_issues=${closed_issues:-0}
121+
merged_prs=${merged_prs:-0}
122+
123+
# Add to totals
124+
total_opened_issues=$((total_opened_issues + opened_issues))
125+
total_closed_issues=$((total_closed_issues + closed_issues))
126+
total_merged_prs=$((total_merged_prs + merged_prs))
127+
128+
# Add to report if there's activity
129+
if [ $((opened_issues + closed_issues + merged_prs)) -gt 0 ]; then
130+
if [ "$OUTPUT_FORMAT" = "markdown" ]; then
131+
report_content+="| $repo | $opened_issues | $closed_issues | $merged_prs |\n"
132+
fi
133+
fi
134+
135+
done <<< "$repo_names"
136+
137+
# Add summary to report
138+
if [ "$OUTPUT_FORMAT" = "markdown" ]; then
139+
report_content+="|**Total**|**$total_opened_issues**|**$total_closed_issues**|**$total_merged_prs**|\n\n"
140+
report_content+="## Details\n\n"
141+
report_content+="- **Total Repositories Checked:** $(echo "$repo_names" | wc -l)\n"
142+
report_content+="- **Total Issues Opened:** $total_opened_issues\n"
143+
report_content+="- **Total Issues Closed:** $total_closed_issues\n"
144+
report_content+="- **Total PRs Merged:** $total_merged_prs\n\n"
145+
report_content+="*Report generated on $(date) by QuantEcon Weekly Report Action*\n"
146+
fi
147+
148+
# Create summary
149+
summary="Week Summary: $total_opened_issues issues opened, $total_closed_issues issues closed, $total_merged_prs PRs merged"
150+
151+
# Save report to file
152+
echo -e "$report_content" > weekly-report.md
153+
154+
# Set outputs
155+
echo "report-content<<EOF" >> $GITHUB_OUTPUT
156+
echo -e "$report_content" >> $GITHUB_OUTPUT
157+
echo "EOF" >> $GITHUB_OUTPUT
158+
159+
echo "report-summary=$summary" >> $GITHUB_OUTPUT
160+
161+
echo "Weekly report generated successfully!"
162+
echo "Summary: $summary"

.github/workflows/test-warning-check.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@ name: Test Warning Check Action
33
on:
44
push:
55
branches: [ main ]
6+
paths:
7+
- '.github/actions/check-warnings/**'
8+
- 'test/check-warnings/**'
69
pull_request:
710
branches: [ main ]
11+
paths:
12+
- '.github/actions/check-warnings/**'
13+
- 'test/check-warnings/**'
814
workflow_dispatch:
915

1016
jobs:
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
name: Test Weekly Report Action
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths:
7+
- '.github/actions/weekly-report/**'
8+
- '.github/workflows/test-weekly-report.yml'
9+
pull_request:
10+
branches: [ main ]
11+
paths:
12+
- '.github/actions/weekly-report/**'
13+
- '.github/workflows/test-weekly-report.yml'
14+
workflow_dispatch:
15+
16+
jobs:
17+
test-basic:
18+
runs-on: ubuntu-latest
19+
name: Test basic weekly report functionality
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- name: Run basic test
25+
run: ./test/weekly-report/test-basic.sh
26+
27+
test-action-structure:
28+
runs-on: ubuntu-latest
29+
name: Test action structure and inputs
30+
steps:
31+
- name: Checkout
32+
uses: actions/checkout@v4
33+
34+
- name: Validate action.yml
35+
run: |
36+
# Check that action.yml exists and has required fields
37+
if [ ! -f ".github/actions/weekly-report/action.yml" ]; then
38+
echo "❌ action.yml not found"
39+
exit 1
40+
fi
41+
42+
# Check for required fields using basic grep
43+
if ! grep -q "name:" .github/actions/weekly-report/action.yml; then
44+
echo "❌ Missing name field"
45+
exit 1
46+
fi
47+
48+
if ! grep -q "github-token:" .github/actions/weekly-report/action.yml; then
49+
echo "❌ Missing github-token input"
50+
exit 1
51+
fi
52+
53+
echo "✅ Action structure validation passed"
54+
55+
- name: Test script exists and is executable
56+
run: |
57+
if [ ! -f ".github/actions/weekly-report/generate-report.sh" ]; then
58+
echo "❌ generate-report.sh not found"
59+
exit 1
60+
fi
61+
62+
if [ ! -x ".github/actions/weekly-report/generate-report.sh" ]; then
63+
echo "❌ generate-report.sh is not executable"
64+
exit 1
65+
fi
66+
67+
echo "✅ Script validation passed"

0 commit comments

Comments
 (0)