From d81ee5e6039ad6fd33e717317f0628da5993852d Mon Sep 17 00:00:00 2001 From: Ashley Wolf Date: Mon, 23 Feb 2026 18:33:14 -0800 Subject: [PATCH 1/4] feat: add OSPO agentic workflow examples Add 4 OSPO workflow templates to workflows/ directory: - ospo-org-health.md: Weekly organization health report - ospo-contributors-report.md: Monthly contributor activity metrics - ospo-release-compliance-checker.md: OSS release readiness audit - ospo-stale-repos.md: Inactive repository detection and archival recommendations Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/README.workflows.md | 8 +- workflows/ospo-contributors-report.md | 141 ++++++++++++ workflows/ospo-org-health.md | 215 +++++++++++++++++++ workflows/ospo-release-compliance-checker.md | 125 +++++++++++ workflows/ospo-stale-repos.md | 120 +++++++++++ 5 files changed, 607 insertions(+), 2 deletions(-) create mode 100644 workflows/ospo-contributors-report.md create mode 100644 workflows/ospo-org-health.md create mode 100644 workflows/ospo-release-compliance-checker.md create mode 100644 workflows/ospo-stale-repos.md diff --git a/docs/README.workflows.md b/docs/README.workflows.md index 93bdfdca4..715588579 100644 --- a/docs/README.workflows.md +++ b/docs/README.workflows.md @@ -1,7 +1,6 @@ # ⚡ Agentic Workflows [Agentic Workflows](https://github.github.com/gh-aw) are AI-powered repository automations that run coding agents in GitHub Actions. Defined in markdown with natural language instructions, they enable event-triggered and scheduled automation with built-in guardrails and security-first design. - ### How to Use Agentic Workflows **What's Included:** @@ -28,4 +27,9 @@ - Respond to slash commands in issues and PRs - Orchestrate multi-step repository automation -_No entries found yet._ \ No newline at end of file +| Name | Description | Triggers | +| ---- | ----------- | -------- | +| [Contributors Report](../workflows/ospo-contributors-report.md) | Monthly contributor activity metrics across an organization's repositories. | schedule, workflow_dispatch | +| [OSS Release Compliance Checker](../workflows/ospo-release-compliance-checker.md) | Analyzes a target repository against open source release requirements and posts a detailed compliance report as an issue comment. | issues, workflow_dispatch | +| [Stale Repository Report](../workflows/ospo-stale-repos.md) | Identifies inactive repositories in your organization and generates an archival recommendation report. | schedule, workflow_dispatch | +| [Weekly Organization Health Report](../workflows/ospo-org-health.md) | Comprehensive weekly health report for a GitHub organization. Surfaces stale issues/PRs, merge time analysis, contributor leaderboards, and actionable items needing human attention. | schedule, workflow_dispatch | diff --git a/workflows/ospo-contributors-report.md b/workflows/ospo-contributors-report.md new file mode 100644 index 000000000..b4dc412d8 --- /dev/null +++ b/workflows/ospo-contributors-report.md @@ -0,0 +1,141 @@ +--- +name: 'Contributors Report' +description: "Monthly contributor activity metrics across an organization's repositories." +triggers: ['schedule', 'workflow_dispatch'] +tags: ['ospo', 'reporting', 'contributors'] +on: + schedule: + - cron: "3 2 1 * *" + workflow_dispatch: + inputs: + organization: + description: "GitHub organization to analyze (e.g. github)" + required: false + type: string + repositories: + description: "Comma-separated list of repos to analyze (e.g. owner/repo1,owner/repo2)" + required: false + type: string + start_date: + description: "Start date for the report period (YYYY-MM-DD)" + required: false + type: string + end_date: + description: "End date for the report period (YYYY-MM-DD)" + required: false + type: string + sponsor_info: + description: "Include GitHub Sponsors information for contributors" + required: false + type: boolean + default: false + +permissions: + contents: read + issues: read + pull-requests: read + +engine: copilot + +tools: + github: + toolsets: + - repos + - issues + - pull_requests + - orgs + - users + bash: true + +safe-outputs: + create-issue: + max: 1 + title-prefix: "[Contributors Report] " + +timeout-minutes: 60 +--- + +# Contributors Report + +Generate a contributors report for the specified organization or repositories. + +## Step 1: Validate Configuration + +Check the workflow inputs. Either `organization` or `repositories` must be provided. + +- If **both** are empty and this is a **scheduled run**, default to analyzing all public repositories in the organization that owns the current repository. Determine the org from the `GITHUB_REPOSITORY` environment variable (the part before the `/`). +- If **both** are empty and this is a **manual dispatch**, fail with a clear error message: "You must provide either an organization or a comma-separated list of repositories." +- If **both** are provided, prefer `repositories` and ignore `organization`. + +## Step 2: Determine Date Range + +- If `start_date` and `end_date` are provided, use them. +- Otherwise, default to the **previous calendar month**. For example, if today is 2025-03-15, the range is 2025-02-01 to 2025-02-28. +- Use bash to compute the dates if needed. Store them as `START_DATE` and `END_DATE`. + +## Step 3: Enumerate Repositories + +- If `repositories` input was provided, split the comma-separated string into a list. Each entry should be in `owner/repo` format. +- If `organization` input was provided (or defaulted from Step 1), list all **public, non-archived, non-fork** repositories in the organization using the GitHub API. Collect their `owner/repo` identifiers. + +## Step 4: Collect Contributors from Commit History + +For each repository in scope: + +1. Use the GitHub API to list commits between `START_DATE` and `END_DATE` (use the `since` and `until` parameters on the commits endpoint). +2. For each commit, extract the **author login** (from `author.login` on the commit object). +3. **Exclude bot accounts**: skip any contributor whose username contains `[bot]` or whose `type` field is `"Bot"`. +4. Track per-contributor: + - Total number of commits across all repos. + - The set of repos they contributed to. + +Use bash to aggregate and deduplicate the contributor data across all repositories. + +## Step 5: Determine New vs Returning Contributors + +For each contributor found in Step 4, check whether they have **any commits before `START_DATE`** in any of the in-scope repositories. + +- If a contributor has **no commits before `START_DATE`**, mark them as a **New Contributor**. +- Otherwise, mark them as a **Returning Contributor**. + +## Step 6: Collect Sponsor Information (Optional) + +If the `sponsor_info` input is `true`: + +1. For each contributor, check whether they have a GitHub Sponsors profile by querying the user's profile via the GitHub API. +2. If the user has sponsorship enabled, record their sponsor URL as `https://github.com/sponsors/`. +3. If not, leave the sponsor field empty. + +## Step 7: Generate Markdown Report + +Build a markdown report with the following structure: + +### Summary Table + +| Metric | Value | +|---|---| +| Total Contributors | count | +| Total Contributions (Commits) | count | +| New Contributors | count | +| Returning Contributors | count | +| % New Contributors | percentage | + +### Contributors Detail Table + +Sort contributors by commit count descending. + +| # | Username | Contribution Count | New Contributor | Sponsor URL | Commits | +|---|---|---|---|---|---| +| 1 | @username | 42 | Yes | [Sponsor](url) | [View](commits-url) | + +- The **Username** column should link to the contributor's GitHub profile. +- The **Sponsor URL** column should show "N/A" if `sponsor_info` is false or the user has no Sponsors page. +- The **Commits** column should link to a filtered commits view. + +## Step 8: Create Issue with Report + +Create an issue in the **current repository** with: + +- **Title:** `[Contributors Report] — START_DATE to END_DATE` +- **Body:** The full markdown report from Step 7. +- **Labels:** Add the label `contributors-report` if it exists; do not fail if it does not. diff --git a/workflows/ospo-org-health.md b/workflows/ospo-org-health.md new file mode 100644 index 000000000..750b1372f --- /dev/null +++ b/workflows/ospo-org-health.md @@ -0,0 +1,215 @@ +--- +name: 'Weekly Organization Health Report' +description: 'Comprehensive weekly health report for a GitHub organization. Surfaces stale issues/PRs, merge time analysis, contributor leaderboards, and actionable items needing human attention.' +triggers: ['schedule', 'workflow_dispatch'] +tags: ['ospo', 'reporting', 'org-health'] +on: + schedule: + - cron: "0 10 * * 1" + workflow_dispatch: + inputs: + organization: + description: "GitHub organization to report on" + type: string + required: true + +permissions: + contents: read + issues: read + pull-requests: read + actions: read + +engine: copilot + +tools: + github: + toolsets: + - repos + - issues + - pull_requests + - orgs + bash: true + +safe-outputs: + create-issue: + max: 1 + title-prefix: "[Org Health] " + +timeout-minutes: 60 + +network: + allowed: + - defaults + - python +--- + +You are an expert GitHub organization analyst. Your job is to produce a +comprehensive weekly health report for your GitHub organization +(provided via workflow input). + +## Primary Goal + +**Surface issues and PRs that need human attention**, celebrate wins, and +provide actionable metrics so maintainers can prioritize their time. + +--- + +## Step 1 — Determine the Organization + +``` +ORG = inputs.organization OR "my-org" +PERIOD_DAYS = 30 +SINCE = date 30 days ago (ISO 8601) +STALE_ISSUE_DAYS = 60 +STALE_PR_DAYS = 30 +``` + +## Step 2 — Gather Organization-Wide Aggregates (Search API) + +Use GitHub search APIs for fast org-wide counts. These are efficient and +avoid per-repo iteration for basic aggregates. + +Collect the following using search queries: + +| Metric | Search Query | +|--------|-------------| +| Total open issues | `org: is:issue is:open` | +| Total open PRs | `org: is:pr is:open` | +| Issues opened (last 30d) | `org: is:issue created:>={SINCE}` | +| Issues closed (last 30d) | `org: is:issue is:closed closed:>={SINCE}` | +| PRs opened (last 30d) | `org: is:pr created:>={SINCE}` | +| PRs merged (last 30d) | `org: is:pr is:merged merged:>={SINCE}` | +| PRs closed unmerged (last 30d) | `org: is:pr is:closed is:unmerged closed:>={SINCE}` | +| Stale issues (60+ days) | `org: is:issue is:open updated:<={60_DAYS_AGO}` | +| Stale PRs (30+ days) | `org: is:pr is:open updated:<={30_DAYS_AGO}` | + +**Performance tip:** Add 1–2 second delays between search API calls to +stay well within rate limits. + +## Step 3 — Stale Issues & PRs (Heat Scores) + +For stale issues and stale PRs found above, retrieve the top results and +sort them by **heat score** (comment count). The heat score helps +maintainers prioritize: a stale issue with many comments signals community +interest that is going unaddressed. + +- **Stale issues**: Retrieve up to 50, sort by `comments` descending, + keep top 10. For each, record: repo, number, title, days since last + update, comment count (heat score), author, labels. +- **Stale PRs**: Same approach — retrieve up to 50, sort by `comments` + descending, keep top 10. + +## Step 4 — PR Merge Time Analysis + +From the PRs merged in the last 30 days (Step 2), retrieve a sample of +recently merged PRs (up to 100). For each, calculate: + +``` +merge_time = merged_at - created_at (in hours) +``` + +Then compute percentiles: +- **p50** (median merge time) +- **p75** +- **p95** + +Use bash with Python for percentile calculations: + +```bash +python3 -c " +import json, sys +times = json.loads(sys.stdin.read()) +times.sort() +n = len(times) +if n == 0: + print('No data') +else: + p50 = times[int(n * 0.50)] + p75 = times[int(n * 0.75)] + p95 = times[int(n * 0.95)] if n >= 20 else times[-1] + print(f'p50={p50:.1f}h, p75={p75:.1f}h, p95={p95:.1f}h') +" +``` + +## Step 5 — First Response Time + +For issues and PRs opened in the last 30 days, sample up to 50 of each. +For each item, find the first comment (excluding the author). Calculate: + +``` +first_response_time = first_comment.created_at - item.created_at (in hours) +``` + +Report median first response time for issues and PRs separately. + +## Step 6 — Repository Activity & Contributor Leaderboard + +### Top 10 Active Repos +List all non-archived repos in the org. For each, count pushes / commits / +issues+PRs opened in the last 30 days. Sort by total activity, keep top 10. + +### Contributor Leaderboard +From the top 10 active repos, aggregate commit authors over the last 30 +days. Rank by commit count, keep top 10. Award: +- 🥇 for #1 +- 🥈 for #2 +- 🥉 for #3 + +### Inactive Repos +Repos with 0 pushes, 0 issues, 0 PRs in the last 30 days. List them +(name + last push date) so the org can decide whether to archive. + +## Step 7 — Health Alerts & Trends + +Compute velocity indicators and assign status: + +| Indicator | 🟢 Green | 🟡 Yellow | 🔴 Red | +|-----------|----------|-----------|--------| +| Issue close rate | closed ≥ opened | closed ≥ 70% opened | closed < 70% opened | +| PR merge rate | merged ≥ opened | merged ≥ 60% opened | merged < 60% opened | +| Median merge time | < 24h | 24–72h | > 72h | +| Median first response | < 24h | 24–72h | > 72h | +| Stale issue count | < 10 | 10–50 | > 50 | +| Stale PR count | < 5 | 5–20 | > 20 | + +## Step 8 — Wins & Shoutouts + +Celebrate positive signals: +- PRs merged with fast turnaround (< 4 hours) +- Issues closed quickly (< 24 hours from open to close) +- Top contributors (from leaderboard) +- Repos with zero stale items + +## Step 9 — Compose the Report + +Create a single issue in the org's `.github` repository (or the most +appropriate central repo) with the title: + +``` +[Org Health] Weekly Report — +``` + +The issue body should include these sections in order: + +1. **Header** — org name, period, generation date +2. **🚨 Health Alerts** — table of indicators with 🟢/🟡/🔴 status and values +3. **🏆 Wins & Shoutouts** — fast merges, quick closes, top contributors +4. **📋 Stale Issues** — top 10 by heat score (repo, issue, days stale, comment count, labels) +5. **📋 Stale PRs** — top 10 by heat score (repo, PR, days stale, comment count, author) +6. **⏱️ PR Merge Time** — p50, p75, p95 percentiles +7. **⚡ First Response Time** — median for issues and PRs +8. **📊 Top 10 Active Repos** — sorted by total activity (issues + PRs + commits) +9. **👥 Contributor Leaderboard** — top 10 by commits with 🥇🥈🥉 +10. **😴 Inactive Repos** — repos with 0 activity in 30 days + +Use markdown tables for all data sections. + +## Important Notes + +- **Update the organization name** in the frontmatter before use. +- If any API call fails, note it in the report and continue with available + data. Do not let a single failure block the entire report. +- Keep the issue body under 65,000 characters (GitHub issue body limit). +- All times should be reported in hours. Convert to days only if > 72 hours. +- Use the `safe-outputs` constraint: only create 1 issue, with title + prefixed `[Org Health] `. diff --git a/workflows/ospo-release-compliance-checker.md b/workflows/ospo-release-compliance-checker.md new file mode 100644 index 000000000..80d54afc6 --- /dev/null +++ b/workflows/ospo-release-compliance-checker.md @@ -0,0 +1,125 @@ +--- +name: 'OSS Release Compliance Checker' +description: 'Analyzes a target repository against open source release requirements and posts a detailed compliance report as an issue comment.' +triggers: ['issues', 'workflow_dispatch'] +tags: ['ospo', 'compliance', 'release'] +on: + issues: + types: [opened, labeled] + workflow_dispatch: + +permissions: + contents: read + issues: read + pull-requests: read + actions: read + +engine: copilot + +tools: + github: + toolsets: + - repos + - issues + bash: true + +safe-outputs: + add-comment: + max: 1 + +timeout-minutes: 20 +--- + +You are an open source release compliance checker. Your job is to analyze a +repository that has been proposed for open source release and post a thorough, +constructive compliance report as a comment on the triggering issue. + +## 1. Trigger Guard + +First, determine whether this workflow should proceed: + +- If the event is `workflow_dispatch`, proceed. +- If the event is `issues` with type `opened`, proceed. +- If the event is `issues` with type `labeled`, only proceed if the label that + was just added is **`ospo-release-check`**. +- Otherwise, stop and do nothing. + +## 2. Extract Target Repository + +Read the body of the triggering issue. Look for the repository that is being +proposed for release. It may appear as: + +- A full GitHub URL such as `https://github.com/org/repo-name` +- An `owner/repo` shorthand such as `org/repo-name` + +Extract the **owner** and **repo name**. If you cannot find a repository +reference, post a comment asking the issue author to include one and stop. + +## 3. File Compliance Check + +For the target repository, check whether each of the following files exists at +the repository root (or in `.github/` where conventional). For each file that +exists, also assess whether it has meaningful content. + +| File | What to look for | +|------|-----------------| +| `LICENSE` | Must be present. Contents must match the license declared in the repo metadata. | +| `README.md` | Must be present and substantial (>100 lines recommended). Should contain sections for usage, install, and contributing. | +| `CODEOWNERS` | Must list at least one maintainer or team. | +| `CONTRIBUTING.md` | Must describe how to contribute (issues, PRs, CLA/DCO, code style). | +| `SUPPORT.md` | Must explain how users can get help. | +| `CODE_OF_CONDUCT.md` | Must adopt a recognized code of conduct. | +| `SECURITY.md` | Must describe the security vulnerability disclosure process. | + +## 4. Security Configuration Check + +Using the GitHub API, check the following security settings on the target +repository: + +- **Secret scanning** — Is secret scanning enabled? +- **Dependabot** — Are Dependabot alerts and/or security updates enabled? +- **Code scanning (CodeQL)** — Are any code scanning analyses present? +- **Branch protection** — Is the default branch protected? Are required reviews, + status checks, or signed commits configured? + +Handle `404` or `403` responses gracefully — they typically mean the feature is +not enabled or you lack permission to check it. + +## 5. License & Legal Analysis + +- Compare the contents of the `LICENSE` file against the license declared in + the repository metadata (`license.spdx_id` from the repo API response). + Flag any mismatch. +- Look for dependency manifests (`package.json`, `requirements.txt`, `go.mod`, + `Cargo.toml`, `pom.xml`, `Gemfile`, `*.csproj`, etc.) in the repository. +- For each manifest found, attempt to identify declared dependency licenses. + Specifically flag any **GPL**, **AGPL**, **LGPL**, or other strong-copyleft + licenses that would require legal review before an open source release. + +## 6. Risk Assessment + +Based on your findings, assign a risk level (**Low**, **Medium**, or **High**) +to each of the following categories: + +| Category | Low 🟢 | Medium 🟡 | High 🔴 | +|----------|--------|-----------|---------| +| **Business Risk** | No secrets, no proprietary code patterns | Some internal references found | Secrets detected, proprietary code | +| **Legal Risk** | Permissive license, no copyleft deps | Minor license inconsistencies | GPL/AGPL deps, license mismatch | +| **Open Source Risk** | All files present, active maintainers | Some files missing or thin | No README, no CODEOWNERS | + +## 7. Generate Compliance Report + +Post **one** comment on the triggering issue with these sections: + +1. **Header** — repo name, timestamp, overall status (PASS ✅ / NEEDS WORK ⚠️ / BLOCKED 🚫) +2. **📄 File Compliance** — table of 7 files with ✅/❌ status and notes +3. **🔒 Security Configuration** — table of 4 settings with status +4. **⚖️ License Analysis** — declared license, LICENSE file match, copyleft flags +5. **📊 Risk Assessment** — Business/Legal/Open Source risk levels (🟢/🟡/🔴) with details +6. **📋 Recommendations** — prioritized as Must Fix (blocking), Should Address, Nice to Have + +### Tone Guidelines + +- Be **constructive** — help teams succeed, don't gatekeep. +- Explain *why* missing items matter and link to guidance. +- Celebrate what the team has already done well. diff --git a/workflows/ospo-stale-repos.md b/workflows/ospo-stale-repos.md new file mode 100644 index 000000000..ad6f0387d --- /dev/null +++ b/workflows/ospo-stale-repos.md @@ -0,0 +1,120 @@ +--- +name: 'Stale Repository Report' +description: 'Identifies inactive repositories in your organization and generates an archival recommendation report.' +triggers: ['schedule', 'workflow_dispatch'] +tags: ['ospo', 'maintenance', 'stale-repos'] +on: + schedule: + - cron: "3 2 1 * *" + workflow_dispatch: + inputs: + organization: + description: "GitHub organization to scan" + required: true + type: string + default: "my-org" + inactive_days: + description: "Number of days of inactivity before a repo is considered stale" + required: false + type: number + default: 365 + exempt_repos: + description: "Comma-separated list of repos to exempt from the report" + required: false + type: string + default: "" + exempt_topics: + description: "Comma-separated list of topics — repos with any of these topics are exempt" + required: false + type: string + default: "" + activity_method: + description: "Method to determine last activity" + required: false + type: choice + options: + - pushed + - default_branch_updated + default: pushed + +permissions: + contents: read + issues: read + +engine: copilot +tools: + github: + toolsets: + - repos + - issues + bash: true + +safe-outputs: + create-issue: + max: 1 + title-prefix: "[Stale Repos] " + labels: + - stale-repos + +timeout-minutes: 30 +--- + +You are an assistant that audits GitHub repositories for staleness. + +## Inputs + +| Input | Default | +|---|---| +| `organization` | `my-org` | +| `inactive_days` | `365` | +| `exempt_repos` | _(none)_ | +| `exempt_topics` | _(none)_ | +| `activity_method` | `pushed` | + +Use the workflow dispatch inputs if provided; otherwise fall back to the defaults above. + +## Instructions + +### 1. Enumerate repositories + +List **all** repositories in the `organization`. Exclude any repo that is: + +- **Archived** — skip it entirely. +- **Listed in `exempt_repos`** — compare repo names (case-insensitive) against the comma-separated list. +- **Tagged with an exempt topic** — if the repo has any topic that appears in the comma-separated `exempt_topics` list, skip it. + +### 2. Determine last activity date + +For each remaining repo, determine the **last activity date** based on `activity_method`: + +- **`pushed`** — use the repository's `pushed_at` timestamp (this is the default and most efficient method). +- **`default_branch_updated`** — fetch the most recent commit on the repo's default branch and use that commit's `committer.date`. + +### 3. Identify stale repos + +Calculate the number of days between the last activity date and **today**. If the number of days exceeds `inactive_days`, mark the repo as **stale**. + +### 4. Generate report + +Build a **Markdown report** with a summary and a table: + +> **Stale Repository Report — \** +> Found **N** repositories with no activity in the last **inactive_days** days. + +| Repository | Days Inactive | Last Push Date | Visibility | +|---|---|---|---| +| [owner/repo](https://github.com/owner/repo) | 420 | 2024-01-15 | public | + +Sort the table by **Days Inactive** descending (most stale first). + +If there are **no stale repos**, still create the issue but note that all repositories are active. + +### 5. Create or update issue + +Search for an existing **open** issue in the `organization/.github` repo (or the repo this workflow runs in) with the label `stale-repos` and a title starting with `[Stale Repos]`. + +- If an **existing open issue** is found, **update its body** with the new report. +- If **no open issue** exists, **create a new issue** with: + - Title: `[Stale Repos] Inactive Repository Report — ` + - Label: `stale-repos` + - Body: the full Markdown report from step 4. From da2da6e4bbf4827d12ee4d88da51a9c1426cc72e Mon Sep 17 00:00:00 2001 From: Ashley Wolf Date: Mon, 23 Feb 2026 18:37:34 -0800 Subject: [PATCH 2/4] chore: add OSPO prefix to workflow names for discoverability Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/README.workflows.md | 6 +++--- workflows/ospo-contributors-report.md | 2 +- workflows/ospo-org-health.md | 2 +- workflows/ospo-stale-repos.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/README.workflows.md b/docs/README.workflows.md index 715588579..4d8b171ad 100644 --- a/docs/README.workflows.md +++ b/docs/README.workflows.md @@ -29,7 +29,7 @@ | Name | Description | Triggers | | ---- | ----------- | -------- | -| [Contributors Report](../workflows/ospo-contributors-report.md) | Monthly contributor activity metrics across an organization's repositories. | schedule, workflow_dispatch | +| [OSPO Contributors Report](../workflows/ospo-contributors-report.md) | Monthly contributor activity metrics across an organization's repositories. | schedule, workflow_dispatch | +| [OSPO Organization Health Report](../workflows/ospo-org-health.md) | Comprehensive weekly health report for a GitHub organization. Surfaces stale issues/PRs, merge time analysis, contributor leaderboards, and actionable items needing human attention. | schedule, workflow_dispatch | +| [OSPO Stale Repository Report](../workflows/ospo-stale-repos.md) | Identifies inactive repositories in your organization and generates an archival recommendation report. | schedule, workflow_dispatch | | [OSS Release Compliance Checker](../workflows/ospo-release-compliance-checker.md) | Analyzes a target repository against open source release requirements and posts a detailed compliance report as an issue comment. | issues, workflow_dispatch | -| [Stale Repository Report](../workflows/ospo-stale-repos.md) | Identifies inactive repositories in your organization and generates an archival recommendation report. | schedule, workflow_dispatch | -| [Weekly Organization Health Report](../workflows/ospo-org-health.md) | Comprehensive weekly health report for a GitHub organization. Surfaces stale issues/PRs, merge time analysis, contributor leaderboards, and actionable items needing human attention. | schedule, workflow_dispatch | diff --git a/workflows/ospo-contributors-report.md b/workflows/ospo-contributors-report.md index b4dc412d8..f9bf80c43 100644 --- a/workflows/ospo-contributors-report.md +++ b/workflows/ospo-contributors-report.md @@ -1,5 +1,5 @@ --- -name: 'Contributors Report' +name: 'OSPO Contributors Report' description: "Monthly contributor activity metrics across an organization's repositories." triggers: ['schedule', 'workflow_dispatch'] tags: ['ospo', 'reporting', 'contributors'] diff --git a/workflows/ospo-org-health.md b/workflows/ospo-org-health.md index 750b1372f..aa4fbac02 100644 --- a/workflows/ospo-org-health.md +++ b/workflows/ospo-org-health.md @@ -1,5 +1,5 @@ --- -name: 'Weekly Organization Health Report' +name: 'OSPO Organization Health Report' description: 'Comprehensive weekly health report for a GitHub organization. Surfaces stale issues/PRs, merge time analysis, contributor leaderboards, and actionable items needing human attention.' triggers: ['schedule', 'workflow_dispatch'] tags: ['ospo', 'reporting', 'org-health'] diff --git a/workflows/ospo-stale-repos.md b/workflows/ospo-stale-repos.md index ad6f0387d..a4f57310a 100644 --- a/workflows/ospo-stale-repos.md +++ b/workflows/ospo-stale-repos.md @@ -1,5 +1,5 @@ --- -name: 'Stale Repository Report' +name: 'OSPO Stale Repository Report' description: 'Identifies inactive repositories in your organization and generates an archival recommendation report.' triggers: ['schedule', 'workflow_dispatch'] tags: ['ospo', 'maintenance', 'stale-repos'] From 8fbd80a79acdd1257e2277d4f6489f9f3efd6c9b Mon Sep 17 00:00:00 2001 From: Ashley Wolf Date: Mon, 23 Feb 2026 19:10:46 -0800 Subject: [PATCH 3/4] fix: use gh-aw-compatible frontmatter fields Replace 'triggers:' with 'metadata.triggers:' and 'tags:' with 'labels:' to pass gh aw compile --validate. Update yaml-parser to read from both awesome-copilot and gh-aw field names. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- eng/yaml-parser.mjs | 6 ++++-- workflows/ospo-contributors-report.md | 5 +++-- workflows/ospo-org-health.md | 5 +++-- workflows/ospo-release-compliance-checker.md | 5 +++-- workflows/ospo-stale-repos.md | 5 +++-- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/eng/yaml-parser.mjs b/eng/yaml-parser.mjs index 88d16582f..fcde9f286 100644 --- a/eng/yaml-parser.mjs +++ b/eng/yaml-parser.mjs @@ -276,13 +276,15 @@ function parseWorkflowMetadata(filePath) { } // Extract triggers from frontmatter if present - const triggers = frontmatter.triggers || []; + // Support both awesome-copilot 'triggers' and gh-aw-compatible 'metadata.triggers' + const triggers = frontmatter.triggers || frontmatter.metadata?.triggers || []; return { name: frontmatter.name, description: frontmatter.description, triggers, - tags: frontmatter.tags || [], + // Support both awesome-copilot 'tags' and gh-aw-compatible 'labels' + tags: frontmatter.tags || frontmatter.labels || [], path: filePath, }; }, diff --git a/workflows/ospo-contributors-report.md b/workflows/ospo-contributors-report.md index f9bf80c43..2901688b8 100644 --- a/workflows/ospo-contributors-report.md +++ b/workflows/ospo-contributors-report.md @@ -1,8 +1,9 @@ --- name: 'OSPO Contributors Report' description: "Monthly contributor activity metrics across an organization's repositories." -triggers: ['schedule', 'workflow_dispatch'] -tags: ['ospo', 'reporting', 'contributors'] +metadata: + triggers: ['schedule', 'workflow_dispatch'] +labels: ['ospo', 'reporting', 'contributors'] on: schedule: - cron: "3 2 1 * *" diff --git a/workflows/ospo-org-health.md b/workflows/ospo-org-health.md index aa4fbac02..ab4c68d2f 100644 --- a/workflows/ospo-org-health.md +++ b/workflows/ospo-org-health.md @@ -1,8 +1,9 @@ --- name: 'OSPO Organization Health Report' description: 'Comprehensive weekly health report for a GitHub organization. Surfaces stale issues/PRs, merge time analysis, contributor leaderboards, and actionable items needing human attention.' -triggers: ['schedule', 'workflow_dispatch'] -tags: ['ospo', 'reporting', 'org-health'] +metadata: + triggers: ['schedule', 'workflow_dispatch'] +labels: ['ospo', 'reporting', 'org-health'] on: schedule: - cron: "0 10 * * 1" diff --git a/workflows/ospo-release-compliance-checker.md b/workflows/ospo-release-compliance-checker.md index 80d54afc6..c649c5606 100644 --- a/workflows/ospo-release-compliance-checker.md +++ b/workflows/ospo-release-compliance-checker.md @@ -1,8 +1,9 @@ --- name: 'OSS Release Compliance Checker' description: 'Analyzes a target repository against open source release requirements and posts a detailed compliance report as an issue comment.' -triggers: ['issues', 'workflow_dispatch'] -tags: ['ospo', 'compliance', 'release'] +metadata: + triggers: ['issues', 'workflow_dispatch'] +labels: ['ospo', 'compliance', 'release'] on: issues: types: [opened, labeled] diff --git a/workflows/ospo-stale-repos.md b/workflows/ospo-stale-repos.md index a4f57310a..80a6424d1 100644 --- a/workflows/ospo-stale-repos.md +++ b/workflows/ospo-stale-repos.md @@ -1,8 +1,9 @@ --- name: 'OSPO Stale Repository Report' description: 'Identifies inactive repositories in your organization and generates an archival recommendation report.' -triggers: ['schedule', 'workflow_dispatch'] -tags: ['ospo', 'maintenance', 'stale-repos'] +metadata: + triggers: ['schedule', 'workflow_dispatch'] +labels: ['ospo', 'maintenance', 'stale-repos'] on: schedule: - cron: "3 2 1 * *" From dc1b269b293b9d2520bd48cbe07f649cad6db33e Mon Sep 17 00:00:00 2001 From: Ashley Wolf Date: Mon, 23 Feb 2026 19:16:09 -0800 Subject: [PATCH 4/4] fix: address review comments - Use single quotes for description in ospo-contributors-report.md - Define 60_DAYS_AGO and 30_DAYS_AGO variables in org-health Step 1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- workflows/ospo-contributors-report.md | 2 +- workflows/ospo-org-health.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/workflows/ospo-contributors-report.md b/workflows/ospo-contributors-report.md index 2901688b8..89e085b29 100644 --- a/workflows/ospo-contributors-report.md +++ b/workflows/ospo-contributors-report.md @@ -1,6 +1,6 @@ --- name: 'OSPO Contributors Report' -description: "Monthly contributor activity metrics across an organization's repositories." +description: 'Monthly contributor activity metrics across an organization''s repositories.' metadata: triggers: ['schedule', 'workflow_dispatch'] labels: ['ospo', 'reporting', 'contributors'] diff --git a/workflows/ospo-org-health.md b/workflows/ospo-org-health.md index ab4c68d2f..a528bf5b5 100644 --- a/workflows/ospo-org-health.md +++ b/workflows/ospo-org-health.md @@ -63,6 +63,8 @@ PERIOD_DAYS = 30 SINCE = date 30 days ago (ISO 8601) STALE_ISSUE_DAYS = 60 STALE_PR_DAYS = 30 +60_DAYS_AGO = date 60 days ago (ISO 8601) +30_DAYS_AGO = date 30 days ago (ISO 8601, same as SINCE) ``` ## Step 2 — Gather Organization-Wide Aggregates (Search API)