GitHub Projects integration
IssueSuite can automatically add created/updated issues to a GitHub Projects (v2) board and update custom fields based on your issue metadata.
Architecture
Section titled “Architecture”graph TB subgraph "IssueSuite" SPEC[ISSUES.md<br/>Specs with metadata] SYNC[Sync Engine] PROJ_MOD[project.py<br/>Projects Integration] end
subgraph "Configuration" CONFIG[github.project.enable: true<br/>github.project.number: N<br/>field_mappings] end
subgraph "GitHub API" ISSUES[Issues API<br/>Create/Update] PROJECTS[Projects v2 API<br/>Add items & fields] end
subgraph "Cache" CACHE[.issuesuite_cache/<br/>Cached field metadata] end
SPEC --> SYNC CONFIG --> SYNC SYNC --> ISSUES SYNC --> PROJ_MOD PROJ_MOD --> PROJECTS PROJ_MOD <--> CACHE
style SPEC fill:#e1f5ff style CONFIG fill:#fff3cd style CACHE fill:#d4edda
Prerequisites
Section titled “Prerequisites”- A GitHub Projects (v2) board in your repository or organization
- Project number (visible in project URL:
github.com/users/USER/projects/NUMBER
) - Token or GitHub App with
project
scope - Custom fields defined in your project (if using field mappings)
Configuration
Section titled “Configuration”Basic setup
Section titled “Basic setup”Add to your issue_suite.config.yaml
:
github: repo: owner/repo project: enable: true number: 42 # Your project number
This adds all synced issues to the project without setting custom fields.
Field mappings
Section titled “Field mappings”Map issue metadata to project custom fields:
github: repo: owner/repo project: enable: true number: 42 field_mappings: Priority: priority # Map 'priority' from spec to 'Priority' field Status: status # Map 'status' to 'Status' field Sprint: milestone # Map milestone to 'Sprint' field
In your ISSUES.md
:
## [slug: api-timeout-fix]
\`\`\`yamltitle: Fix API timeout handlingpriority: Highstatus: In Progressmilestone: Sprint 3body: |Implementation details...\`\`\`
Field types
Section titled “Field types”Projects API supports these field types:
Type | Example Values | Notes |
---|---|---|
Single select | High , Medium , Low | Must match project field options exactly |
Text | Any string | Free-form text |
Number | 1 , 5.5 | Numeric values |
Date | 2025-10-15 | ISO 8601 date format |
Iteration | Sprint 3 | Must match iteration name |
Field caching
Section titled “Field caching”IssueSuite caches project field metadata in .issuesuite_cache/
to reduce API calls:
.issuesuite_cache/└── project_42_fields.json
Cache behavior
Section titled “Cache behavior”-
TTL: Default 3600 seconds (1 hour)
-
Invalidation: Automatic on TTL expiry or manual deletion
-
Configuration:
Terminal window # Custom TTLexport ISSUESUITE_PROJECT_CACHE_TTL=7200# Disable caching (always fetch fresh)export ISSUESUITE_PROJECT_CACHE_DISABLE=1
Cache structure
Section titled “Cache structure”{ "project_id": "PVT_kwDOAbc123", "fields": [ { "id": "PVTF_lADOAbc123zgAbc", "name": "Priority", "dataType": "SINGLE_SELECT", "options": [ { "id": "opt1", "name": "High" }, { "id": "opt2", "name": "Medium" }, { "id": "opt3", "name": "Low" } ] } ], "cached_at": "2025-10-10T12:00:00Z"}
Workflow
Section titled “Workflow”sequenceDiagram participant User participant Sync as Sync Engine participant Cache participant GitHub as GitHub API participant Project as Projects API
User->>Sync: issuesuite sync --update Sync->>GitHub: Create/update issue GitHub-->>Sync: Issue #123
Sync->>Cache: Check field cache
alt Cache valid Cache-->>Sync: Cached field data else Cache expired/missing Sync->>Project: Fetch field metadata Project-->>Sync: Field IDs & options Sync->>Cache: Store metadata end
Sync->>Project: Add issue to project Project-->>Sync: Item ID
Sync->>Project: Update custom fields Project-->>Sync: Success
Sync-->>User: Summary with project updates
Frontier Apex automation
Section titled “Frontier Apex automation”IssueSuite ships CLI harnesses that mirror the nightly governance dashboards. Use issuesuite projects-sync
to render the JSON payload that powers the GitHub Projects status item alongside the Markdown comment that surfaces in async updates:
issuesuite projects-sync \ --next-steps Next_Steps.md \ --coverage coverage_projects_payload.json \ --project-owner acme \ --project-number 7 \ --status-field Status \ --plan-output projects_sync_plan.json \ --comment-output projects_sync_comment.md
- The command is idempotent. In dry-run mode (
--apply
omitted) it reports the calculated status without mutating GitHub. - When
--apply
is present, the sync automatically creates the dashboard draft item if it does not already exist, then updates the configured status, coverage, and summary fields. - The CLI emits a structured payload on stdout and prints
created_item=True
when a new draft item is provisioned so automated checks can detect onboarding scenarios. - Pair the CLI with
issuesuite projects-status
to export the same summary without contacting GitHub.
Error handling
Section titled “Error handling”Missing field options
Section titled “Missing field options”If you specify a value not in the field’s options:
priority: Critical # But only High/Medium/Low exist
IssueSuite logs a warning and skips that field update:
WARN: Option 'Critical' not found in field 'Priority' (api-timeout-fix)
Field not found
Section titled “Field not found”If a mapped field doesn’t exist in the project:
field_mappings: Nonexistent: priority
The sync logs an error and continues:
ERROR: Field 'Nonexistent' not found in project 42
Permission errors
Section titled “Permission errors”If your token lacks project access:
ERROR: Failed to fetch project fields: Resource not accessible by integration
Solution: Ensure token has project
scope (classic tokens) or GitHub App has Projects
read/write permissions.
Troubleshooting
Section titled “Troubleshooting”Cache issues
Section titled “Cache issues”Clear the cache and retry:
rm -rf .issuesuite_cache/issuesuite sync --dry-run # Refreshes cache without mutations
Field mapping validation
Section titled “Field mapping validation”Test field mappings with a dry-run:
issuesuite sync --dry-run --update
Check logs for field resolution warnings.
Performance
Section titled “Performance”For large projects (>1000 issues), enable concurrency:
concurrency: enabled: true max_workers: 4
This parallelizes project API calls.
Best practices
Section titled “Best practices”- Start with dry-run: Always test field mappings with
--dry-run
first - Cache strategy: Use default TTL (1 hour) unless fields change frequently
- Field naming: Keep field names consistent between projects for reusable configs
- Error monitoring: Check logs for field mapping warnings after syncs
- Selective sync: Use field mappings only for metadata that truly belongs in project views
Examples
Section titled “Examples”Minimal project integration
Section titled “Minimal project integration”github: repo: myorg/myrepo project: enable: true number: 5
Full field mapping
Section titled “Full field mapping”github: repo: myorg/myrepo project: enable: true number: 5 field_mappings: Priority: priority Status: status Sprint: milestone Team: team Estimate: estimate
With specs:
## [slug: feature-x]
\`\`\`yamltitle: Implement feature Xpriority: Highstatus: In Progressmilestone: Sprint 5team: Backendestimate: 5body: |Feature implementation...\`\`\`
Next steps
Section titled “Next steps”- Configuration reference for all project settings
- Architecture overview for integration details
- Automation CI for project sync in CI/CD