Daily Community Attribution Updater #13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: Daily Community Attribution Updater | |
| description: Maintains a live community contributions section in README.md and an all-time Community Contributors wiki page by attributing all community-labeled issues using the five-tier attribution strategy | |
| on: | |
| schedule: | |
| - cron: daily | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| issues: read | |
| engine: copilot | |
| timeout-minutes: 30 | |
| network: | |
| allowed: | |
| - defaults | |
| tools: | |
| github: | |
| mode: "local" | |
| toolsets: [issues, pull_requests] | |
| repo-memory: | |
| wiki: true | |
| description: "All-time Community Contributors list" | |
| bash: | |
| - "gh pr list *" | |
| - "gh issue list *" | |
| - "jq *" | |
| - "mkdir *" | |
| - "echo *" | |
| - "cp *" | |
| - "cat *" | |
| - "date *" | |
| edit: | |
| safe-outputs: | |
| create-pull-request: | |
| expires: 1d | |
| title-prefix: "[community] " | |
| labels: [community, automation] | |
| reviewers: [] | |
| draft: true | |
| imports: | |
| - shared/community-attribution.md | |
| steps: | |
| - name: Fetch PR data for attribution index | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| mkdir -p /tmp/gh-aw/community-data | |
| # Fetch merged PRs from the last 90 days (wide enough to catch any recently attributed issue) | |
| SINCE=$(date -d '90 days ago' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null \ | |
| || date -v-90d '+%Y-%m-%dT%H:%M:%SZ') | |
| echo "Fetching PRs merged since $SINCE..." | |
| gh pr list \ | |
| --state merged \ | |
| --limit 500 \ | |
| --json number,title,author,mergedAt,url,body,closingIssuesReferences \ | |
| --jq "[.[] | select(.mergedAt >= \"$SINCE\")]" \ | |
| > /tmp/gh-aw/community-data/pull_requests.json \ | |
| || echo "[]" > /tmp/gh-aw/community-data/pull_requests.json | |
| PR_COUNT=$(jq length /tmp/gh-aw/community-data/pull_requests.json) | |
| echo "✓ Fetched $PR_COUNT merged PRs" | |
| # Build closing references index: {issue_number: [pr_numbers]} | |
| # Use a nested reduce so the outer body always returns the accumulator, | |
| # even when closingIssuesReferences is empty (avoids jq setting acc to null). | |
| jq ' | |
| reduce .[] as $pr ( | |
| {}; | |
| reduce ($pr.closingIssuesReferences // [])[] as $issue ( | |
| .; | |
| ($issue.number | tostring) as $key | | |
| .[$key] = (.[$key] // []) + [$pr.number] | |
| ) | |
| ) | |
| ' /tmp/gh-aw/community-data/pull_requests.json \ | |
| > /tmp/gh-aw/community-data/closing_refs_by_issue.json 2>/dev/null \ | |
| || echo "{}" > /tmp/gh-aw/community-data/closing_refs_by_issue.json | |
| LINK_COUNT=$(jq 'keys | length' /tmp/gh-aw/community-data/closing_refs_by_issue.json) | |
| echo "✓ Built closing refs index: $LINK_COUNT issues with native GitHub close links" | |
| # Find community issues closed within the PR lookback window (attribution candidates) | |
| jq --arg since "$SINCE" \ | |
| '[.[] | select(.closedAt != null and .closedAt >= $since)]' \ | |
| /tmp/gh-aw/community-data/community_issues.json \ | |
| > /tmp/gh-aw/community-data/community_issues_closed_in_window.json 2>/dev/null \ | |
| || echo "[]" > /tmp/gh-aw/community-data/community_issues_closed_in_window.json | |
| CLOSED_COUNT=$(jq length /tmp/gh-aw/community-data/community_issues_closed_in_window.json) | |
| echo "✓ Found $CLOSED_COUNT community issues closed in the lookback window" | |
| echo "" | |
| echo "Data available in /tmp/gh-aw/community-data/:" | |
| echo " community_issues.json — all community-labeled issues (includes stateReason)" | |
| echo " pull_requests.json — merged PRs (last 90 days)" | |
| echo " closing_refs_by_issue.json — native GitHub close links" | |
| echo " community_issues_closed_in_window.json — closed during lookback" | |
| --- | |
| # Daily Community Attribution Updater | |
| Maintain an up-to-date **🌍 Community Contributions** section in `README.md` | |
| and an all-time **Community Contributors** wiki page by attributing all | |
| resolved community-labeled issues using the five-tier attribution strategy. | |
| ## Mission | |
| The `community` label is the **primary attribution signal**: every issue | |
| tagged with it was explicitly identified by a maintainer as community-authored. | |
| This workflow attributes those issues (including direct-issue contributions | |
| with `stateReason == "COMPLETED"`), updates `README.md`, maintains the wiki, | |
| and opens a PR for review. | |
| ## Pre-fetched Data | |
| All data is in `/tmp/gh-aw/community-data/`: | |
| ```bash | |
| # View all community-labeled issues (with stateReason) | |
| cat /tmp/gh-aw/community-data/community_issues.json | \ | |
| jq -r '.[] | "- #\(.number) [\(.state // "?")] stateReason=\(.stateReason // "null") \(.title) by @\(.author.login)"' | |
| # View Tier 0 contributions (COMPLETED, direct issue — no PR needed) | |
| cat /tmp/gh-aw/community-data/community_issues.json | \ | |
| jq -r '.[] | select(.stateReason == "COMPLETED") | "- #\(.number): \(.title) by @\(.author.login) (closed: \(.closedAt))"' | |
| # View recently closed community issues (attribution candidates) | |
| cat /tmp/gh-aw/community-data/community_issues_closed_in_window.json | \ | |
| jq -r '.[] | "- #\(.number): \(.title) by @\(.author.login) (closed: \(.closedAt), stateReason: \(.stateReason // "null"))"' | |
| # View closing reference index | |
| cat /tmp/gh-aw/community-data/closing_refs_by_issue.json | jq | |
| # View current README | |
| head -80 /tmp/gh-aw/community-data/README_current.md | |
| # View existing wiki page (if any) | |
| cat /tmp/gh-aw/repo-memory-default/Community-Contributors.md 2>/dev/null || echo "(wiki page does not exist yet)" | |
| ``` | |
| ## Workflow | |
| ### 1. Attribute All Resolved Community Issues | |
| Apply the **Community Attribution Strategy** from the imported shared component | |
| to every closed community-labeled issue. | |
| Focus on issues in `community_issues_closed_in_window.json` first (recently | |
| closed, most likely to be new). Then check older closed issues in | |
| `community_issues.json` that are not already reflected in `README.md` or the | |
| wiki page. | |
| For each community issue, work through all five attribution tiers (see shared | |
| component) and mark it as **confirmed**, **confirmed (via follow-up)**, or | |
| **needs review**. | |
| ### 2. Update the Community Contributors Wiki Page | |
| Read the existing wiki page at | |
| `/tmp/gh-aw/repo-memory-default/Community-Contributors.md` (empty/missing on | |
| first run). Merge all confirmed attributions — both newly found ones and all | |
| previously recorded ones — without duplicating entries. | |
| The wiki page uses issue numbers as link text for quick scanning, while `README.md` | |
| uses issue titles. Both use full GitHub issue URLs. | |
| The wiki page format: | |
| ```markdown | |
| # Community Contributors | |
| ### @author | |
| - [#N](https://github.com/OWNER/REPO/issues/N) Issue title — YYYY-MM-DD — direct issue | |
| - [#N](https://github.com/OWNER/REPO/issues/N) Issue title — YYYY-MM-DD — resolved by #PR | |
| ### @author2 | |
| - [#N](https://github.com/OWNER/REPO/issues/N) Issue title — YYYY-MM-DD — direct issue | |
| ``` | |
| - Group entries by author (alphabetical order) | |
| - Within each author section, sort by issue number descending (newest first) | |
| - **`direct issue`** — Tier 0: closed as `COMPLETED`, no PR linkage | |
| - **`resolved by #PR`** — Tiers 1–3: attributed to a specific merged PR | |
| - Do not add entries for unresolved or ambiguous candidates (Tier 4) | |
| Write the updated content back to | |
| `/tmp/gh-aw/repo-memory-default/Community-Contributors.md` using the edit tool. | |
| ### 3. Build the Community Contributions Section | |
| Produce a compact section of attributed community contributors for | |
| `README.md`, wrapped in a `<details>` element. Use **one list item per | |
| author** with all their issues listed inline. Use GitHub issue references | |
| (`#N`) so that GitHub automatically expands them with the issue title — | |
| do **not** use full URLs or explicit issue titles as link text (GitHub | |
| renders the title for you): | |
| ```markdown | |
| ## 🌍 Community Contributions | |
| <details> | |
| <summary>Thank you to the community members whose issue reports were resolved in this project! This list is updated automatically and reflects all attributed contributions.</summary> | |
| - @author: #N _(direct issue)_, #N, #N _(via follow-up #M)_ | |
| - @author2: #N, #N | |
| </details> | |
| ``` | |
| **Important**: always leave a blank line after `</details>` (as shown | |
| above) so that the next markdown header renders correctly. | |
| - One bullet per author, sorted alphabetically by username | |
| - Within each author's entry, list issues in descending order (newest first), comma-separated | |
| - **`_(direct issue)_`** (Tier 0): issue closed as `COMPLETED`, no PR linkage | |
| - _(no suffix)_ (Tier 1/2): PR closes the issue via native close reference or keyword | |
| - **`_(via follow-up #M)_`** (Tier 3): indirect chain through a follow-up issue | |
| - Omit issues that cannot be attributed (see Attribution Candidates section below) | |
| If there are unattributed candidates (Tier 4), append after the `</details>` blank line: | |
| ```markdown | |
| ### ⚠️ Attribution Candidates Need Review | |
| The following community issues were closed but could not be automatically | |
| linked to a specific merged PR. Please verify whether they should be credited: | |
| - **@author** for [Issue title](#N) — closed DATE | |
| ``` | |
| ### 4. Update README.md | |
| Replace the existing `## 🌍 Community Contributions` section in `README.md` | |
| with the newly generated content, or append it after the `## Contributing` | |
| section if it does not yet exist. | |
| Use the edit tool to make the change in-place. | |
| ### 5. Open a Pull Request | |
| If `README.md` **or** the wiki page changed, call the `create_pull_request` | |
| safe-output tool to open a PR with the changes. | |
| **PR title**: `[community] Update community contributions in README` | |
| **PR body template**: | |
| ```markdown | |
| ### Community Contributions Update | |
| Automated update to the 🌍 Community Contributions section in `README.md` | |
| and the Community Contributors wiki page. | |
| #### Changes | |
| - N community issues newly attributed | |
| - N attribution candidates flagged for review (if any) | |
| - Wiki page updated: Y/N | |
| #### Attribution Summary | |
| [brief summary of what changed and how each was attributed] | |
| ``` | |
| **Important**: If no action is needed after completing your analysis, you | |
| **MUST** call the `noop` safe-output tool with a brief explanation. | |
| ```json | |
| {"noop": {"message": "No action needed: [brief explanation]"}} | |
| ``` |