Generated: 2026-02-21 Sources: 15 resources analyzed Depth: deep
- Familiarity with GitHub Issues and Pull Requests
- Basic understanding of GitHub Organizations
- Awareness of multi-repo project structures
- Optional: GraphQL API knowledge for automation
- GitHub Projects v2 is the primary tool for cross-repo org-level project management, supporting up to 50,000 items and 50 custom fields across all repos in an org.
- Issue Types (public preview, Jan 2025) and Sub-Issues enable structured work hierarchies at the org level without extra tooling.
- Automation via built-in workflows, GitHub Actions (
actions/add-to-project@v1), and the GraphQL API is essential for keeping cross-repo boards accurate at scale. - Successful open source orgs (Rust, Kubernetes, Astro, GitHub itself) combine a public roadmap project, RFC/enhancement-proposal repos, and working groups or SIGs to coordinate distributed contributors.
- The GraphQL API with the
projectOAuth scope unlocks full programmatic control;read:projectis sufficient for read-only integrations.
Projects v2 replaced the classic Projects board in 2022. It lives at the org level (not per-repo) and can aggregate items from any repository in the organization.
Key capabilities:
- Views: Table (spreadsheet-style), Board (kanban), Roadmap (Gantt-like timeline)
- Custom fields: Up to 50 per project. Types: text, number, date, single-select, iteration
- Grouping, filtering, sorting: Available across all views; filters use GitHub's advanced search syntax including AND/OR keywords and parentheses
- Capacity: 50,000 items per project
- Cross-repo: A single project can contain issues and PRs from any repo in the org
Introduced in public preview January 2025. Org admins define up to 25 custom issue types (defaults: Task, Bug, Feature). Types are available across all repos and can be filtered in Projects and search.
This replaces the common pattern of using label conventions (type: bug, kind/feature) with a first-class field.
Also in public preview. Issues can have a parent-child relationship:
- Break a large epic into sub-issues
- Progress bar displayed on the parent issue
- Sub-issues can live in different repos from the parent
- Enables hierarchical tracking without external tools
| Plan | Built-in Workflows |
|---|---|
| Free | 1 active workflow |
| Pro / Team | 5 active workflows |
| Enterprise | 20 active workflows |
Built-in workflow triggers:
- Item closed → set status
- PR merged → set status
- Item added to repo → add to project (filter by label, status, or assignee)
- Item archived by staleness (14 days, 3 weeks, or 1 month of inactivity)
For more complex rules, use GitHub Actions or the GraphQL API.
All project mutations require the project OAuth scope. Read-only operations use read:project.
Primary operations:
addProjectV2ItemById- add an issue/PR to a projectupdateProjectV2ItemFieldValue- set a field value on an itemcreateProjectV2- create a new project
Webhook events: projects_v2_item (created, edited, deleted, reordered, converted)
# .github/workflows/add-to-project.yml
# Place this in EACH repo that should auto-add items to the org project
name: Add to Org Project
on:
issues:
types: [opened]
pull_request:
types: [opened]
jobs:
add-to-project:
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v1
with:
project-url: https://github.com/orgs/MY-ORG/projects/42
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
# Optional: only add if issue has specific label
labeled: triage, bug, enhancementThe PAT must belong to an org member and have the project scope.
mutation AddIssueToProject($projectId: ID!, $contentId: ID!) {
addProjectV2ItemById(input: {
projectId: $projectId
contentId: $contentId
}) {
item {
id
}
}
}mutation SetStatus($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) {
updateProjectV2ItemFieldValue(input: {
projectId: $projectId
itemId: $itemId
fieldId: $fieldId
value: {
singleSelectOptionId: $optionId
}
}) {
projectV2Item {
id
}
}
}query FindProject($org: String!, $number: Int!) {
organization(login: $org) {
projectV2(number: $number) {
id
title
fields(first: 20) {
nodes {
... on ProjectV2Field {
id
name
}
... on ProjectV2SingleSelectField {
id
name
options {
id
name
}
}
}
}
}
}
}org:MY-ORG is:open type:feature label:roadmap
org:MY-ORG is:open type:bug (label:priority-high OR label:priority-critical)
GitHub maintains a public project at github.com/orgs/github/projects/4247. Key practices:
- Quarterly columns map to release milestones
- The
shippedlabel is applied when a feature lands, and the issue body is updated with a changelog link - Items stay visible after shipping in a "Shipped" column (archive only after some time)
- This gives external contributors a real-time view of planned and recent work
Kubernetes uses Special Interest Groups (SIGs) to coordinate work across 100+ repos:
- Each SIG owns a subset of repos and has a dedicated project board
- Kubernetes Enhancement Proposals (KEPs) live in a single
kubernetes/enhancementsrepo as structured markdown files - KEPs link to issues/PRs in implementation repos
- SIG leads triage new issues weekly and apply standardized labels (
sig/network,kind/feature, etc.)
- RFCs live in
rust-lang/rfcsas PRs - Working groups coordinate cross-team implementation
- A dedicated project tracks RFC lifecycle stages (proposed → accepted → stabilized → closed)
- Cross-repo coordination uses GitHub Projects with a single-select "Phase" field
- 51 repos under one org
withastro/roadmaprepo hosts RFC discussions and a public-facing roadmap project- Uses pnpm workspaces for the core monorepo; satellite repos (integrations, adapters) auto-add to the roadmap project via GitHub Actions
- Labels are org-wide and enforced consistently
| Pitfall | Why It Happens | How to Avoid |
|---|---|---|
| Project scope creep | One project tracks everything; becomes unusable | One project per initiative or quarter; archive completed projects |
| Label inconsistency across repos | Each repo grows its own labels organically | Manage labels programmatically; use a shared label config script or action |
| Missing automation tokens | PATs expire or lack correct scopes; cross-repo actions silently fail | Use fine-grained PATs with explicit project scope; rotate with secrets manager |
| Stale items clogging board | Closed issues not archived; old PRs linger | Enable auto-archive: set staleness to 14 days or archive on close/merge |
| No triage process | New issues pile up without status | Add "Needs Triage" as default status; automate: new issue → Needs Triage |
| Cross-repo sub-issue confusion | Contributors open sub-issues in wrong repo | Document in CONTRIBUTING.md which repo to use for which issue type |
| Workflow count limits on Free plan | Only 1 built-in workflow on Free | Use GitHub Actions instead of built-in workflows for more rules |
| Views not shared with team | Each person builds their own view | Create named saved views in the project for common filters (My Items, This Sprint, Blocked) |
-
One source of truth per initiative - Each major feature or release gets exactly one project. Avoid tracking the same item in multiple projects.
-
Standardize labels org-wide - Use a label sync action (e.g.,
EndBug/add-or-update-label) to keep labels consistent across all repos. Document the label taxonomy in aCONTRIBUTING.mdor.githubrepo. -
Use Issue Types instead of type labels - Now that Issue Types are available (Jan 2025 public preview), prefer them over label conventions for
bug,feature,task. Labels are better for priority, status, and component. -
Automate triage with GitHub Actions - New issues opened in any repo auto-add to the org triage project with status "Needs Triage". Maintainers process the triage board, not individual repos.
-
Keep the roadmap project public - A public roadmap project builds contributor trust and reduces duplicate "when will X be done?" issues. Model: GitHub's own public roadmap.
-
Use Iteration fields for sprints or releases - Iterations are time-boxed periods (e.g., 2-week sprints). Assign items to iterations instead of milestones for better burndown tracking.
-
Multiple saved views per audience - Create views for: "My open items" (assignee filter), "This sprint" (iteration filter), "Blocked" (status filter), "Triage queue" (status = Needs Triage).
-
Sub-issues for epics, not just labels - Break large epics into sub-issues rather than relying on a checklist in the parent body. Progress tracking is automatic and cross-repo linking is supported.
-
Automate status transitions - Configure built-in workflows: PR merged → item status set to Done. Issue closed as not-planned → item archived. This removes manual housekeeping.
-
Use the
.githubmeta-repo - A.githubrepo in the org stores default issue templates, PR templates,CONTRIBUTING.md, and Actions workflows that apply to all repos with no files.
Recommended custom fields for an org-level project:
| Field Name | Type | Values / Notes |
|---|---|---|
| Status | Single Select | Triage, Backlog, In Progress, In Review, Done, Blocked |
| Priority | Single Select | Critical, High, Medium, Low |
| Sprint / Iteration | Iteration | 2-week cadence |
| Effort | Single Select | XS, S, M, L, XL |
| Component | Single Select | Per-repo or per-area (e.g., Core, Docs, CLI, API) |
| Target Release | Single Select | v1.0, v1.1, Backlog |
| Repo | Text | Auto-populated via automation (helps when filtering Table view) |
name: PR Opened - Set In Progress
on:
pull_request:
types: [opened, reopened]
jobs:
update-project:
runs-on: ubuntu-latest
steps:
- name: Move linked issues to In Progress
uses: actions/github-script@v7
with:
github-token: ${{ secrets.PROJECT_PAT }}
script: |
// Use GraphQL to find project item for this PR and update status
// Implementation varies by project ID and field IDs# Run in the .github meta-repo
name: Sync Labels
on:
push:
paths: ['labels.yml']
schedule:
- cron: '0 2 * * 1' # Weekly Monday 2am
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: EndBug/label-sync@v2
with:
config-file: labels.yml
delete-other-labels: false
token: ${{ secrets.LABEL_SYNC_PAT }}
# Applies to all repos accessible to the PAT| Resource | Type | Why Recommended |
|---|---|---|
| GitHub Projects Docs | Official Docs | Canonical reference for all Projects v2 features |
| GitHub's Public Roadmap | Live Example | See how GitHub itself manages a public org project |
| actions/add-to-project | GitHub Action | Official action for cross-repo auto-add |
| Kubernetes SIG structure | Reference | How Kubernetes scales to 100+ repos with SIGs |
| withastro/roadmap | Reference | Astro's RFC and roadmap coordination model |
| GitHub Issues API (GraphQL) | API Docs | GraphQL mutations for project automation |
| EndBug/label-sync | GitHub Action | Sync labels across all org repos |
This guide was synthesized from research on GitHub Projects v2, Issue Types, Sub-Issues, GraphQL API, and real-world org patterns (Rust-lang, Kubernetes, Astro, GitHub). See resources/github-org-project-management-sources.json for full source list.