Skip to content

Daily org status report via GitHub Actions - #169

Merged
don-petry merged 6 commits into
mainfrom
feat/daily-org-status-workflow
May 2, 2026
Merged

Daily org status report via GitHub Actions#169
don-petry merged 6 commits into
mainfrom
feat/daily-org-status-workflow

Conversation

@don-petry

@don-petry don-petry commented May 1, 2026

Copy link
Copy Markdown
Contributor

Closes #174

Adds a scheduled GitHub Actions workflow that posts a daily org status digest as a GitHub Issue.

What it does:

  • Discovers all repos across petry-projects and don-petry
  • Paginates GitHub GraphQL for open PRs with CI status, review state, labels, and linked issues
  • Collects open issues, discussions, and 8-day merge activity
  • Uses Claude Code CLI to format everything into a structured markdown report
  • Posts the report as a labeled daily-report issue in petry-projects/.github, tagging @don-petry

Files:

  • .github/workflows/daily-org-status.yml — Actions workflow (cron 6 AM CDT + workflow_dispatch)
  • scripts/org_status.sh — data collection, prompt building, Claude invocation

Security:

  • Actions pinned to full commit SHAs
  • npm install --ignore-scripts for Claude Code CLI
  • --allowedTools "" on Claude invocation (no tool access — pure text formatting task)
  • permissions: {} at workflow level; job grants only issues: write

Preview: #172 (generated locally before merge)

Summary by CodeRabbit

  • New Features
    • Automated daily organization-status reports summarizing PRs, issues, discussions, and recent merge activity.
    • Aggregated metrics and categorized insights, including flagged items needing human review and dependency bumps.
    • Reports can run on a daily schedule or be triggered manually and are posted as dated, labeled issues to a central repository for review.

Runs at 6am CDT via cron, collects PR/issue/merge/discussion data
across petry-projects org and don-petry personal account, generates
a formatted markdown report via Claude, and opens a GitHub issue
labeled daily-report for daily review.
Copilot AI review requested due to automatic review settings May 1, 2026 01:23
@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@don-petry has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 47 minutes and 35 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 05e0386a-30d1-4b24-9fb5-1003d3334a85

📥 Commits

Reviewing files that changed from the base of the PR and between eb36188 and 760ddcf.

📒 Files selected for processing (2)
  • .github/workflows/daily-org-status.yml
  • scripts/org_status.sh
📝 Walkthrough

Walkthrough

Adds a scheduled + manually-triggerable GitHub Actions workflow that runs scripts/org_status.sh to collect repo PR/issue/discussion data via gh/GraphQL, generate a Markdown org status report with Claude, and post it as a labeled daily-report issue in petry-projects/.github.

Changes

Daily Org Status workflow and script

Layer / File(s) Summary
Data Shape / Inputs
scripts/org_status.sh
Computes TODAY/SINCE, discovers repos via gh repo list, and assembles JSON datasets: per-PR records, PR aggregates, issue→PR map, merged-PR daily counts, open issues, and discussions.
Core Implementation
scripts/org_status.sh
collect_classify_prs paginates GraphQL PR queries, derives flags/categories (needsHumanReview, isDepBump), aggregates PRs by repo/category, gathers merged PR history, issues, and discussions, and builds prompt.txt embedding JSON inputs.
AI Report Generation
scripts/org_status.sh
Invokes claude with the constructed prompt (tooling disabled) to produce the final Markdown report to stdout.
Workflow / Integration
.github/workflows/daily-org-status.yml
New GitHub Actions workflow (cron + workflow_dispatch) checks out code, sets up Node 20, installs @anthropic-ai/claude-code, runs scripts/org_status.sh to generate /tmp/report.md, truncates if >60,000 bytes, and creates a daily-report issue in petry-projects/.github using gh.
Operational Safety / Artifacts
.github/workflows/daily-org-status.yml, scripts/org_status.sh
Job-level minimal permissions (issues: write, contents: read), 30m timeout, strict Bash error handling, temp-dir cleanup, and explicit failure if report is empty.

Sequence Diagram

sequenceDiagram
    participant GHA as GitHub Actions (Scheduler) 
    participant Script as org_status.sh
    participant GH as GitHub CLI / GraphQL API
    participant Claude as Claude AI
    participant GH_Issues as GitHub Issues API

    GHA->>Script: run workflow (cron / manual)
    Script->>GH: gh repo list / GraphQL queries (open PRs, issues, discussions)
    GH-->>Script: repo, PR, issue, discussion data
    Script->>Script: enrich data, aggregate JSON, build prompt
    Script->>Claude: send prompt + JSON
    Claude-->>Script: Markdown report
    Script->>GH_Issues: gh issue create in petry-projects/.github (uses GH token)
    GH_Issues-->>Script: issue created
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding a daily org status report via GitHub Actions. It accurately reflects the two core files added (workflow and script) and their purpose.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/daily-org-status-workflow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 47 minutes and 35 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/daily-org-status.yml:
- Around line 33-35: Guard the workflow against creating empty reports by
checking the computed line count for /tmp/report.md after running
scripts/org_status.sh and aborting or skipping the issue-creation steps when
lines == 0; update the step that echoes "lines=$(wc -l < /tmp/report.md)" to
also fail early (exit non-zero) or set an output you can use in an if:
conditional, then add an if: condition referencing that output (the "lines"
output) on the subsequent issue-creation job/step so it runs only when lines !=
'0' (use the /tmp/report.md path and the echoed "lines=" output as the
identifying symbols to locate where to insert this guard).
- Around line 17-19: Replace the mutable workflow action tags with immutable
commit SHAs: change the two uses entries for actions/checkout and
actions/setup-node (the lines referencing actions/checkout@v4 and
actions/setup-node@v4) to pin the specific SHAs provided in the comment (use
34e114876b0b11c390a56381ad16ebd13914f8d5 for actions/checkout and
49933ea5288caeca8642d1e84afbd3f7d6820020 for actions/setup-node) so the workflow
references fixed, immutable action versions.
- Line 24: Replace the unpinned global install of `@anthropic-ai/claude-code` with
a pinned version and handle its postinstall script: change the run step that
currently calls "npm install -g `@anthropic-ai/claude-code`" to use an explicit
version (e.g., `@anthropic-ai/claude-code`@2.1.116) and, if the postinstall script
should not run in CI, add the --ignore-scripts flag (npm install -g
--ignore-scripts `@anthropic-ai/claude-code`@2.1.116); alternatively, pin the
version and keep the postinstall only after verifying the script is safe to run
in this workflow.

In `@scripts/org_status.sh`:
- Around line 39-40: The current fallback assignment to result (the "||
result='{\"data\":...}'" after the GraphQL fetch using owner, repo, cursor)
masks API failures as empty PR data; instead detect the fetch/jq pipeline exit
status and fail loudly: capture the command output into a temp var, check its
exit code, and if non-zero or the output is empty/invalid, write an error to
stderr (including the original command error/output) and exit non‑zero rather
than assigning a bogus empty JSON to result so maintainers are alerted to API
failures.
- Around line 12-13: The repo lists are being truncated by the hard-coded
"--limit 100" so ORG_REPOS and PERSONAL_REPOS (and the similar block referenced
at 149-153) miss repos once the org grows; update the gh calls to fetch all
pages (replace "--limit 100" with "--limit 0" or implement proper pagination
using gh api/--page looping) so the gh repo list and the discussions traversal
consume the full result set and then pipe to jq/sort as before; apply the same
change to both ORG_REPOS, PERSONAL_REPOS and the other occurrence at 149-153.
- Around line 120-128: The jq map currently compares .closedAt[:10] to the
current object (.) which is wrong; update the map to bind each date to a
variable and use that variable in the selects. Replace the map(...) with
something like: dates | map(. as $d | { date: $d, org: ([$org[] |
select(.closedAt[:10] == $d)] | length), personal: ([$personal[] |
select(.closedAt[:10] == $d)] | length) }) so the inner selects compare
closedAt[:10] to the date string ($d) rather than the entire object.
- Around line 134-136: The owner inference is ambiguous because the loop "for
repo in $ORG_REPOS $PERSONAL_REPOS" and the owner assignment using "echo
\"$ORG_REPOS\" | grep -qx \"$repo\"" can misidentify repos with the same name;
change the logic to iterate known owners explicitly or map repos to owners
instead of guessing: either loop first over ORG_REPOS (set
owner="petry-projects") and then over PERSONAL_REPOS (set owner="don-petry"), or
build a list/associative array that pairs each repo with its owner and use that
map when setting owner and calling gh; update the code that computes owner (the
owner variable assignment and the for loop) accordingly so same-named personal
repos are not treated as org repos.
- Line 260: Replace the unsafe Claude invocation that uses
--dangerously-skip-permissions with a non-interactive, restricted-tool call:
remove --dangerously-skip-permissions and instead add --bare to disable
auto-discovery, supply --allowedTools with a minimal whitelist (e.g.,
"Read,Edit") and set --permission-mode dontAsk so it cannot prompt
interactively; update the invocation that currently reads claude -p "$(cat
"$DATA_DIR/prompt.txt")" to use these flags and retain existing
input/redirection behavior (2>/dev/null) so CI runs non-interactively with only
the needed tool permissions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e912b924-3e10-4549-af3e-8661a99e8de9

📥 Commits

Reviewing files that changed from the base of the PR and between 3951a35 and 4be9237.

📒 Files selected for processing (2)
  • .github/workflows/daily-org-status.yml
  • scripts/org_status.sh

Comment thread .github/workflows/daily-org-status.yml Outdated
Comment thread .github/workflows/daily-org-status.yml Outdated
Comment thread .github/workflows/daily-org-status.yml
Comment thread scripts/org_status.sh Outdated
Comment thread scripts/org_status.sh Outdated
Comment thread scripts/org_status.sh Outdated
Comment thread scripts/org_status.sh Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds automated daily reporting for GitHub activity across the petry-projects org and don-petry account, generating a markdown summary via gh + jq and posting it as a labeled issue.

Changes:

  • Introduces a scheduled + manually-triggerable workflow to generate and post a daily “Org Status” issue.
  • Adds a bash data-collection script that queries PRs/issues/merges/discussions and builds a structured prompt for Claude Code CLI formatting.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 13 comments.

File Description
.github/workflows/daily-org-status.yml Schedules and runs the daily report job, installs Claude Code CLI, and creates a daily-report issue.
scripts/org_status.sh Discovers repos, collects GitHub data via gh/GraphQL, pre-aggregates with jq, and invokes Claude to format the report.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/org_status.sh
Comment thread scripts/org_status.sh Outdated
Comment thread .github/workflows/daily-org-status.yml Outdated
Comment thread .github/workflows/daily-org-status.yml Outdated
Comment thread scripts/org_status.sh Outdated
Comment thread .github/workflows/daily-org-status.yml
Comment thread scripts/org_status.sh
Comment thread scripts/org_status.sh Outdated
Comment thread scripts/org_status.sh Outdated
Comment thread scripts/org_status.sh Outdated
…ange(8), truncation

- Pin actions/checkout and actions/setup-node to commit SHAs
- Pin @anthropic-ai/claude-code to 2.1.123
- Add timeout-minutes: 30 to job
- Remove unused 'lines' step output
- Add issue body truncation guard (60k bytes)
- Split issues loop into two separate owner loops (fixes collision bug)
- Fix jq merge daily filter: capture date as $date before generator (scope bug)
- Fix range(7) -> range(8) so today is included in merge daily table
- Bump reviews(last:5) -> reviews(last:20)
- Add --dangerously-skip-permissions comment explaining CI requirement
- Cross-platform date: macOS -v vs Linux -d
Comment thread .github/workflows/daily-org-status.yml Fixed
…don-petry mention

- Add closingIssuesReferences to PR GraphQL query; build ISSUE_PR_MAP
- Add url field to gh issue list and discussion GraphQL
- Render every PR #, issue #, discussion # as a markdown hyperlink
- Issues table gains Linked PR column (from ISSUE_PR_MAP, — if none)
- Titles are also linked (not just issue/PR numbers)
- Repo names in breakdown tables link to the repo
- Report opens with @don-petry mention for GitHub notification

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
scripts/org_status.sh (3)

307-309: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Don’t run Claude in bypass-permissions mode here.

Official Claude Code docs say --dangerously-skip-permissions enables bypassPermissions, which auto-approves tool use and is intended only for isolated environments. The same docs recommend --bare for scripted calls, and dontAsk for locked-down CI where non-preapproved tool calls should be denied. Because this prompt is built from untrusted PR/issue/discussion content and the workflow injects both GitHub and Claude tokens into the same step, this is an avoidable exfiltration surface. Switch this to --bare --permission-mode dontAsk, and only add an explicit --allowedTools list if the formatter proves it needs one. (code.claude.com)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/org_status.sh` around lines 307 - 309, The script invokes the Claude
CLI with --dangerously-skip-permissions which enables bypassPermissions; change
the claude invocation in scripts/org_status.sh (the line calling claude -p
"$(cat "$DATA_DIR/prompt.txt")" --dangerously-skip-permissions) to use safer
flags: replace --dangerously-skip-permissions with --bare --permission-mode
dontAsk, and only add an explicit --allowedTools argument if you later confirm
the formatter requires specific tools; ensure the invocation still reads the
prompt from "$DATA_DIR/prompt.txt" and preserves stderr redirection.

16-17: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Paginate repo discovery and discussion traversal.

Both repo discovery and the discussions query stop after the first 100 repositories, so this report silently becomes incomplete as either account grows past that threshold.

Also applies to: 174-177

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/org_status.sh` around lines 16 - 17, The repo listing uses a fixed
--limit 100 which truncates results; change the calls that set ORG_REPOS and
PERSONAL_REPOS (currently using "gh repo list ... --json name --limit 100") to
use gh's pagination (e.g., replace --limit 100 with --paginate or a sufficiently
large --limit) so all repositories are returned, and do the same for the
discussions traversal code referenced around lines 174-177 to ensure discussion
queries iterate across all pages rather than stopping at the first 100.

28-45: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail the job when PR collection fails.

The || result='…nodes":[]…' fallback turns GraphQL/auth/rate-limit failures into “0 open PRs”, which can publish a materially wrong report without alerting anyone.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/org_status.sh` around lines 28 - 45, The current fallback that sets
result='{"data":{"repository":{"pullRequests":{"pageInfo":{"hasNextPage":false},"nodes":[]}}}}'
masks failures from the gh api graphql call and should be removed; instead run
the gh api graphql command assigning to result, check its exit status, and if it
fails print the gh error (don't swallow stderr) and exit with a non-zero code so
the job fails; update the code around the result=$(gh api graphql ...
2>/dev/null) invocation to preserve stderr (or capture it to a variable), remove
the || result=... fallback, and add a conditional that logs the error and exits
(use the same result variable and reference the graphql call/variables owner,
repo, cursor and the pullRequests data retrieval).
.github/workflows/daily-org-status.yml (1)

27-33: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fail before opening an empty daily-report issue.

If report generation exits 0 but writes an empty or whitespace-only /tmp/report.md, this workflow still creates a blank daily-report issue. Add a non-empty check after generation and stop before the create step when the file has no real content.

Also applies to: 43-52

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/daily-org-status.yml around lines 27 - 33, After running
the "Generate org status report" step that executes scripts/org_status.sh and
writes /tmp/report.md, add a check that tests whether /tmp/report.md contains
any non-whitespace content and aborts the workflow (or skips the subsequent
create-issue step) if it is empty or only whitespace; specifically, after the
bash scripts/org_status.sh > /tmp/report.md line verify the file length or
content (e.g., strip whitespace and test non-empty) and fail/exit early with a
clear message so the later "create daily-report issue" action does not run when
/tmp/report.md has no real content.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/org_status.sh`:
- Around line 135-144: MERGE_DAILY is building an 8-day window (def dates uses
range(8)) but downstream text asks for “Last 7 Days”, causing a label/data
mismatch; change the date generator to produce exactly 7 days or make the prompt
consistently request “Last 8 Days”. Specifically, update the dates generator
used to compute MERGE_DAILY (the def dates expression that currently uses
range(8)) to use range(7) if you want a 7-day inclusive window (SINCE through
TODAY) or alternatively change the reporting prompt/labels that reference
MERGE_DAILY (the places that say “Last 7 Days”) to say “Last 8 Days” so the data
and label match; apply the same fix to the other occurrences noted (the other
MERGE_*/reporting prompt usages).

---

Duplicate comments:
In @.github/workflows/daily-org-status.yml:
- Around line 27-33: After running the "Generate org status report" step that
executes scripts/org_status.sh and writes /tmp/report.md, add a check that tests
whether /tmp/report.md contains any non-whitespace content and aborts the
workflow (or skips the subsequent create-issue step) if it is empty or only
whitespace; specifically, after the bash scripts/org_status.sh > /tmp/report.md
line verify the file length or content (e.g., strip whitespace and test
non-empty) and fail/exit early with a clear message so the later "create
daily-report issue" action does not run when /tmp/report.md has no real content.

In `@scripts/org_status.sh`:
- Around line 307-309: The script invokes the Claude CLI with
--dangerously-skip-permissions which enables bypassPermissions; change the
claude invocation in scripts/org_status.sh (the line calling claude -p "$(cat
"$DATA_DIR/prompt.txt")" --dangerously-skip-permissions) to use safer flags:
replace --dangerously-skip-permissions with --bare --permission-mode dontAsk,
and only add an explicit --allowedTools argument if you later confirm the
formatter requires specific tools; ensure the invocation still reads the prompt
from "$DATA_DIR/prompt.txt" and preserves stderr redirection.
- Around line 16-17: The repo listing uses a fixed --limit 100 which truncates
results; change the calls that set ORG_REPOS and PERSONAL_REPOS (currently using
"gh repo list ... --json name --limit 100") to use gh's pagination (e.g.,
replace --limit 100 with --paginate or a sufficiently large --limit) so all
repositories are returned, and do the same for the discussions traversal code
referenced around lines 174-177 to ensure discussion queries iterate across all
pages rather than stopping at the first 100.
- Around line 28-45: The current fallback that sets
result='{"data":{"repository":{"pullRequests":{"pageInfo":{"hasNextPage":false},"nodes":[]}}}}'
masks failures from the gh api graphql call and should be removed; instead run
the gh api graphql command assigning to result, check its exit status, and if it
fails print the gh error (don't swallow stderr) and exit with a non-zero code so
the job fails; update the code around the result=$(gh api graphql ...
2>/dev/null) invocation to preserve stderr (or capture it to a variable), remove
the || result=... fallback, and add a conditional that logs the error and exits
(use the same result variable and reference the graphql call/variables owner,
repo, cursor and the pullRequests data retrieval).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b65ba13b-456e-4a26-9444-5fbb4fd112c3

📥 Commits

Reviewing files that changed from the base of the PR and between 4be9237 and b5492fb.

📒 Files selected for processing (2)
  • .github/workflows/daily-org-status.yml
  • scripts/org_status.sh

Comment thread scripts/org_status.sh
@don-petry
don-petry enabled auto-merge (squash) May 1, 2026 17:53
- Raise repo discovery limit from 100 to 1000
- Increase GraphQL labels page from 5 to 20 (prevent missing needs-human-review)
- Fix ci/review fields to emit JSON null instead of string "null"
- Add sort_by before group_by for PR and merge aggregations
- Replace --dangerously-skip-permissions with --allowedTools "" (no tool access for formatting task)
- Add top-level permissions: {} to workflow
- Guard against empty report before creating issue
- Fix merge activity section header: "Last 7 Days" → "Last 8 Days" to match 8-day data window
@don-petry

Copy link
Copy Markdown
Contributor Author

Addressed all review feedback in eb36188:

Comment Fix
--dangerously-skip-permissions security risk (CodeRabbit 🔴, Copilot) Replaced with --allowedTools "" — no tools available so no permissions to bypass, eliminating the prompt-injection exfiltration vector
Repo discovery capped at 100 (CodeRabbit, Copilot) Raised to --limit 1000
labels(first:5) could miss needs-human-review (Copilot) Raised to labels(first:20)
ci/review emitting string "null" instead of JSON null (Copilot) Changed // "null"// null
group_by without preceding sort_by (Copilot) Added sort_by before all group_by calls
Guard against empty report before creating issue (CodeRabbit) Added [ -s /tmp/report.md ] || exit 1 after script run
Top-level permissions: {} missing (Copilot) Added at workflow level
Merge activity header says "Last 7 Days" but window is 8 days (CodeRabbit) Fixed to "Last 8 Days"
Action SHA pinning (CodeRabbit) Already pinned since initial commit
Owner inference ambiguity for same-named repos (CodeRabbit) Already fixed with separate loops in d2b7990
API failure silently converting to empty data Left intentional — repos without PR/issue features enabled return 404; suppressing those errors is correct. Added note: genuine network failures will still fail the overall set -euo pipefail script.

Also created #174 to track the problem this solves and linked this PR to close it.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
scripts/org_status.sh (2)

36-54: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail the job when PR collection fails instead of fabricating an empty result.

Line 54 still converts any GraphQL/auth/rate-limit failure into “0 open PRs”, which can publish a materially wrong daily report without alerting anyone.

Suggested fix
-    result=$(gh api graphql \
+    if ! result=$(gh api graphql \
       "${cursor_arg[@]}" \
       -f query='query($owner:String!,$repo:String!,$cursor:String){
         repository(owner:$owner,name:$repo){
           pullRequests(states:OPEN,first:100,after:$cursor){
             pageInfo{hasNextPage endCursor}
             nodes{
               number title createdAt isDraft
               labels(first:20){nodes{name}}
               reviewDecision
               statusCheckRollup{state}
               reviews(last:20){nodes{state}}
               closingIssuesReferences(first:10){nodes{number}}
             }
           }
         }
       }' \
-      -f owner="$owner" -f repo="$repo" 2>/dev/null) \
-      || result='{"data":{"repository":{"pullRequests":{"pageInfo":{"hasNextPage":false},"nodes":[]}}}}'
+      -f owner="$owner" -f repo="$repo" 2>&1); then
+      printf 'Failed to fetch open PRs for %s/%s:\n%s\n' "$owner" "$repo" "$result" >&2
+      exit 1
+    fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/org_status.sh` around lines 36 - 54, The current assignment to result
after calling gh api graphql for pull requests masks failures by substituting a
fabricated empty JSON (the fallback assigned to result), so change the logic in
scripts/org_status.sh around the gh api graphql call (the result variable set
from "gh api graphql" that uses cursor_arg, owner, repo) to stop swallowing
errors: remove the "|| result='...'" fallback, capture and check the gh command
exit status, and on non-zero exit log an error message and exit with a non-zero
status (or otherwise propagate the original error) instead of pretending there
are 0 open PRs.

183-200: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Paginate the discussions repo traversal instead of stopping at 100 repos.

The discussions query is still capped at repositories(first:100), so the “org-wide” discussions section silently becomes incomplete once petry-projects grows past 100 repositories.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/org_status.sh` around lines 183 - 200, The repositories GraphQL call
used to populate DISCUSSIONS is limited to repositories(first:100) so it stops
collecting discussions after 100 repos; modify the logic to paginate
repositories by adding pageInfo { hasNextPage endCursor } to the query and
iterate using the after cursor (e.g., repositories(first:100, after:$cursor)) in
a loop that updates the cursor and continues while hasNextPage is true,
aggregating nodes across pages before piping to jq; adjust the DISCUSSIONS
assembly to perform repeated gh api graphql calls with the after parameter until
all pages are fetched.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/daily-org-status.yml:
- Around line 26-27: Update the "Install Claude Code CLI" GitHub Actions step to
remove the --ignore-scripts flag so the package's postinstall runs; replace the
run command `npm install -g --ignore-scripts `@anthropic-ai/claude-code`@2.1.123`
with `npm install -g `@anthropic-ai/claude-code`@2.1.123` to ensure the
postinstall script needed by the Claude CLI executes.

---

Duplicate comments:
In `@scripts/org_status.sh`:
- Around line 36-54: The current assignment to result after calling gh api
graphql for pull requests masks failures by substituting a fabricated empty JSON
(the fallback assigned to result), so change the logic in scripts/org_status.sh
around the gh api graphql call (the result variable set from "gh api graphql"
that uses cursor_arg, owner, repo) to stop swallowing errors: remove the "||
result='...'" fallback, capture and check the gh command exit status, and on
non-zero exit log an error message and exit with a non-zero status (or otherwise
propagate the original error) instead of pretending there are 0 open PRs.
- Around line 183-200: The repositories GraphQL call used to populate
DISCUSSIONS is limited to repositories(first:100) so it stops collecting
discussions after 100 repos; modify the logic to paginate repositories by adding
pageInfo { hasNextPage endCursor } to the query and iterate using the after
cursor (e.g., repositories(first:100, after:$cursor)) in a loop that updates the
cursor and continues while hasNextPage is true, aggregating nodes across pages
before piping to jq; adjust the DISCUSSIONS assembly to perform repeated gh api
graphql calls with the after parameter until all pages are fetched.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 68443821-0621-4b84-9b10-ddc42a387659

📥 Commits

Reviewing files that changed from the base of the PR and between b5492fb and eb36188.

📒 Files selected for processing (2)
  • .github/workflows/daily-org-status.yml
  • scripts/org_status.sh

Comment thread .github/workflows/daily-org-status.yml Outdated
…on; fix remaining review comments

- Remove --ignore-scripts from npm install: claude-code postinstall downloads
  the binary and is required for the CLI to function; add NOSONAR annotation
  to acknowledge the postinstall is the Anthropic binary fetcher, not arbitrary
- Add sort_by(.key) before group_by(.key) in ISSUE_PR_MAP
- Fix discussions query: labels(first:5) -> labels(first:20)
@sonarqubecloud

sonarqubecloud Bot commented May 2, 2026

Copy link
Copy Markdown

@don-petry
don-petry disabled auto-merge May 2, 2026 02:07
@don-petry
don-petry merged commit af066a7 into main May 2, 2026
16 checks passed
@don-petry
don-petry deleted the feat/daily-org-status-workflow branch May 2, 2026 02:07
don-petry added a commit that referenced this pull request Jun 8, 2026
* Add daily org status GitHub Action

Runs at 6am CDT via cron, collects PR/issue/merge/discussion data
across petry-projects org and don-petry personal account, generates
a formatted markdown report via Claude, and opens a GitHub issue
labeled daily-report for daily review.

* Fix review findings: pinned actions, timeout, owner loop, jq scope, range(8), truncation

- Pin actions/checkout and actions/setup-node to commit SHAs
- Pin @anthropic-ai/claude-code to 2.1.123
- Add timeout-minutes: 30 to job
- Remove unused 'lines' step output
- Add issue body truncation guard (60k bytes)
- Split issues loop into two separate owner loops (fixes collision bug)
- Fix jq merge daily filter: capture date as $date before generator (scope bug)
- Fix range(7) -> range(8) so today is included in merge daily table
- Bump reviews(last:5) -> reviews(last:20)
- Add --dangerously-skip-permissions comment explaining CI requirement
- Cross-platform date: macOS -v vs Linux -d

* Enhance report: hyperlinks on all items, Linked PR column on issues, @don-petry mention

- Add closingIssuesReferences to PR GraphQL query; build ISSUE_PR_MAP
- Add url field to gh issue list and discussion GraphQL
- Render every PR #, issue #, discussion # as a markdown hyperlink
- Issues table gains Linked PR column (from ISSUE_PR_MAP, — if none)
- Titles are also linked (not just issue/PR numbers)
- Repo names in breakdown tables link to the repo
- Report opens with @don-petry mention for GitHub notification

* fix: add --ignore-scripts to npm install to satisfy SonarCloud security gate

* fix: address CodeRabbit and Copilot review comments

- Raise repo discovery limit from 100 to 1000
- Increase GraphQL labels page from 5 to 20 (prevent missing needs-human-review)
- Fix ci/review fields to emit JSON null instead of string "null"
- Add sort_by before group_by for PR and merge aggregations
- Replace --dangerously-skip-permissions with --allowedTools "" (no tool access for formatting task)
- Add top-level permissions: {} to workflow
- Guard against empty report before creating issue
- Fix merge activity section header: "Last 7 Days" → "Last 8 Days" to match 8-day data window

* fix: remove --ignore-scripts (postinstall required), NOSONAR annotation; fix remaining review comments

- Remove --ignore-scripts from npm install: claude-code postinstall downloads
  the binary and is required for the CLI to function; add NOSONAR annotation
  to acknowledge the postinstall is the Anthropic binary fetcher, not arbitrary
- Add sort_by(.key) before group_by(.key) in ISSUE_PR_MAP
- Fix discussions query: labels(first:5) -> labels(first:20)

---------

Co-authored-by: don-petry <don-petry@users.noreply.github.com>
don-petry added a commit that referenced this pull request Jun 10, 2026
* Add daily org status GitHub Action

Runs at 6am CDT via cron, collects PR/issue/merge/discussion data
across petry-projects org and don-petry personal account, generates
a formatted markdown report via Claude, and opens a GitHub issue
labeled daily-report for daily review.

* Fix review findings: pinned actions, timeout, owner loop, jq scope, range(8), truncation

- Pin actions/checkout and actions/setup-node to commit SHAs
- Pin @anthropic-ai/claude-code to 2.1.123
- Add timeout-minutes: 30 to job
- Remove unused 'lines' step output
- Add issue body truncation guard (60k bytes)
- Split issues loop into two separate owner loops (fixes collision bug)
- Fix jq merge daily filter: capture date as $date before generator (scope bug)
- Fix range(7) -> range(8) so today is included in merge daily table
- Bump reviews(last:5) -> reviews(last:20)
- Add --dangerously-skip-permissions comment explaining CI requirement
- Cross-platform date: macOS -v vs Linux -d

* Enhance report: hyperlinks on all items, Linked PR column on issues, @don-petry mention

- Add closingIssuesReferences to PR GraphQL query; build ISSUE_PR_MAP
- Add url field to gh issue list and discussion GraphQL
- Render every PR #, issue #, discussion # as a markdown hyperlink
- Issues table gains Linked PR column (from ISSUE_PR_MAP, — if none)
- Titles are also linked (not just issue/PR numbers)
- Repo names in breakdown tables link to the repo
- Report opens with @don-petry mention for GitHub notification

* fix: add --ignore-scripts to npm install to satisfy SonarCloud security gate

* fix: address CodeRabbit and Copilot review comments

- Raise repo discovery limit from 100 to 1000
- Increase GraphQL labels page from 5 to 20 (prevent missing needs-human-review)
- Fix ci/review fields to emit JSON null instead of string "null"
- Add sort_by before group_by for PR and merge aggregations
- Replace --dangerously-skip-permissions with --allowedTools "" (no tool access for formatting task)
- Add top-level permissions: {} to workflow
- Guard against empty report before creating issue
- Fix merge activity section header: "Last 7 Days" → "Last 8 Days" to match 8-day data window

* fix: remove --ignore-scripts (postinstall required), NOSONAR annotation; fix remaining review comments

- Remove --ignore-scripts from npm install: claude-code postinstall downloads
  the binary and is required for the CLI to function; add NOSONAR annotation
  to acknowledge the postinstall is the Anthropic binary fetcher, not arbitrary
- Add sort_by(.key) before group_by(.key) in ISSUE_PR_MAP
- Fix discussions query: labels(first:5) -> labels(first:20)

---------

Co-authored-by: don-petry <don-petry@users.noreply.github.com>
don-petry added a commit that referenced this pull request Jun 11, 2026
* Add daily org status GitHub Action

Runs at 6am CDT via cron, collects PR/issue/merge/discussion data
across petry-projects org and don-petry personal account, generates
a formatted markdown report via Claude, and opens a GitHub issue
labeled daily-report for daily review.

* Fix review findings: pinned actions, timeout, owner loop, jq scope, range(8), truncation

- Pin actions/checkout and actions/setup-node to commit SHAs
- Pin @anthropic-ai/claude-code to 2.1.123
- Add timeout-minutes: 30 to job
- Remove unused 'lines' step output
- Add issue body truncation guard (60k bytes)
- Split issues loop into two separate owner loops (fixes collision bug)
- Fix jq merge daily filter: capture date as $date before generator (scope bug)
- Fix range(7) -> range(8) so today is included in merge daily table
- Bump reviews(last:5) -> reviews(last:20)
- Add --dangerously-skip-permissions comment explaining CI requirement
- Cross-platform date: macOS -v vs Linux -d

* Enhance report: hyperlinks on all items, Linked PR column on issues, @don-petry mention

- Add closingIssuesReferences to PR GraphQL query; build ISSUE_PR_MAP
- Add url field to gh issue list and discussion GraphQL
- Render every PR #, issue #, discussion # as a markdown hyperlink
- Issues table gains Linked PR column (from ISSUE_PR_MAP, — if none)
- Titles are also linked (not just issue/PR numbers)
- Repo names in breakdown tables link to the repo
- Report opens with @don-petry mention for GitHub notification

* fix: add --ignore-scripts to npm install to satisfy SonarCloud security gate

* fix: address CodeRabbit and Copilot review comments

- Raise repo discovery limit from 100 to 1000
- Increase GraphQL labels page from 5 to 20 (prevent missing needs-human-review)
- Fix ci/review fields to emit JSON null instead of string "null"
- Add sort_by before group_by for PR and merge aggregations
- Replace --dangerously-skip-permissions with --allowedTools "" (no tool access for formatting task)
- Add top-level permissions: {} to workflow
- Guard against empty report before creating issue
- Fix merge activity section header: "Last 7 Days" → "Last 8 Days" to match 8-day data window

* fix: remove --ignore-scripts (postinstall required), NOSONAR annotation; fix remaining review comments

- Remove --ignore-scripts from npm install: claude-code postinstall downloads
  the binary and is required for the CLI to function; add NOSONAR annotation
  to acknowledge the postinstall is the Anthropic binary fetcher, not arbitrary
- Add sort_by(.key) before group_by(.key) in ISSUE_PR_MAP
- Fix discussions query: labels(first:5) -> labels(first:20)

---------

Co-authored-by: don-petry <don-petry@users.noreply.github.com>
don-petry added a commit that referenced this pull request Jun 11, 2026
* Add daily org status GitHub Action

Runs at 6am CDT via cron, collects PR/issue/merge/discussion data
across petry-projects org and don-petry personal account, generates
a formatted markdown report via Claude, and opens a GitHub issue
labeled daily-report for daily review.

* Fix review findings: pinned actions, timeout, owner loop, jq scope, range(8), truncation

- Pin actions/checkout and actions/setup-node to commit SHAs
- Pin @anthropic-ai/claude-code to 2.1.123
- Add timeout-minutes: 30 to job
- Remove unused 'lines' step output
- Add issue body truncation guard (60k bytes)
- Split issues loop into two separate owner loops (fixes collision bug)
- Fix jq merge daily filter: capture date as $date before generator (scope bug)
- Fix range(7) -> range(8) so today is included in merge daily table
- Bump reviews(last:5) -> reviews(last:20)
- Add --dangerously-skip-permissions comment explaining CI requirement
- Cross-platform date: macOS -v vs Linux -d

* Enhance report: hyperlinks on all items, Linked PR column on issues, @don-petry mention

- Add closingIssuesReferences to PR GraphQL query; build ISSUE_PR_MAP
- Add url field to gh issue list and discussion GraphQL
- Render every PR #, issue #, discussion # as a markdown hyperlink
- Issues table gains Linked PR column (from ISSUE_PR_MAP, — if none)
- Titles are also linked (not just issue/PR numbers)
- Repo names in breakdown tables link to the repo
- Report opens with @don-petry mention for GitHub notification

* fix: add --ignore-scripts to npm install to satisfy SonarCloud security gate

* fix: address CodeRabbit and Copilot review comments

- Raise repo discovery limit from 100 to 1000
- Increase GraphQL labels page from 5 to 20 (prevent missing needs-human-review)
- Fix ci/review fields to emit JSON null instead of string "null"
- Add sort_by before group_by for PR and merge aggregations
- Replace --dangerously-skip-permissions with --allowedTools "" (no tool access for formatting task)
- Add top-level permissions: {} to workflow
- Guard against empty report before creating issue
- Fix merge activity section header: "Last 7 Days" → "Last 8 Days" to match 8-day data window

* fix: remove --ignore-scripts (postinstall required), NOSONAR annotation; fix remaining review comments

- Remove --ignore-scripts from npm install: claude-code postinstall downloads
  the binary and is required for the CLI to function; add NOSONAR annotation
  to acknowledge the postinstall is the Anthropic binary fetcher, not arbitrary
- Add sort_by(.key) before group_by(.key) in ISSUE_PR_MAP
- Fix discussions query: labels(first:5) -> labels(first:20)

---------

Co-authored-by: don-petry <don-petry@users.noreply.github.com>
don-petry added a commit that referenced this pull request Jun 11, 2026
* Add daily org status GitHub Action

Runs at 6am CDT via cron, collects PR/issue/merge/discussion data
across petry-projects org and don-petry personal account, generates
a formatted markdown report via Claude, and opens a GitHub issue
labeled daily-report for daily review.

* Fix review findings: pinned actions, timeout, owner loop, jq scope, range(8), truncation

- Pin actions/checkout and actions/setup-node to commit SHAs
- Pin @anthropic-ai/claude-code to 2.1.123
- Add timeout-minutes: 30 to job
- Remove unused 'lines' step output
- Add issue body truncation guard (60k bytes)
- Split issues loop into two separate owner loops (fixes collision bug)
- Fix jq merge daily filter: capture date as $date before generator (scope bug)
- Fix range(7) -> range(8) so today is included in merge daily table
- Bump reviews(last:5) -> reviews(last:20)
- Add --dangerously-skip-permissions comment explaining CI requirement
- Cross-platform date: macOS -v vs Linux -d

* Enhance report: hyperlinks on all items, Linked PR column on issues, @don-petry mention

- Add closingIssuesReferences to PR GraphQL query; build ISSUE_PR_MAP
- Add url field to gh issue list and discussion GraphQL
- Render every PR #, issue #, discussion # as a markdown hyperlink
- Issues table gains Linked PR column (from ISSUE_PR_MAP, — if none)
- Titles are also linked (not just issue/PR numbers)
- Repo names in breakdown tables link to the repo
- Report opens with @don-petry mention for GitHub notification

* fix: add --ignore-scripts to npm install to satisfy SonarCloud security gate

* fix: address CodeRabbit and Copilot review comments

- Raise repo discovery limit from 100 to 1000
- Increase GraphQL labels page from 5 to 20 (prevent missing needs-human-review)
- Fix ci/review fields to emit JSON null instead of string "null"
- Add sort_by before group_by for PR and merge aggregations
- Replace --dangerously-skip-permissions with --allowedTools "" (no tool access for formatting task)
- Add top-level permissions: {} to workflow
- Guard against empty report before creating issue
- Fix merge activity section header: "Last 7 Days" → "Last 8 Days" to match 8-day data window

* fix: remove --ignore-scripts (postinstall required), NOSONAR annotation; fix remaining review comments

- Remove --ignore-scripts from npm install: claude-code postinstall downloads
  the binary and is required for the CLI to function; add NOSONAR annotation
  to acknowledge the postinstall is the Anthropic binary fetcher, not arbitrary
- Add sort_by(.key) before group_by(.key) in ISSUE_PR_MAP
- Fix discussions query: labels(first:5) -> labels(first:20)

---------

Co-authored-by: don-petry <don-petry@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Daily org-wide status visibility: automate PR/issue/discussion digest

3 participants