All.sync gh projects.how to guide
GitHub Project Sync Tool#
This guide explains how the
sync_gh_projects.py tool
works, what it's designed to do, and the known limitations due to GitHub's
Projects (Beta) API constraints. This tool has many limitations currently due to
restricted GraphQL API support for ProjectV2, especially around views, layout,
and ordering.
Purpose#
This tool synchronizes the structure of a GitHub Project from a source
template project to a target destination project. It helps teams quickly align
project configuration without manually replicating fields.
What It Actually Syncs#
Fields: These are the global columns in your project (e.g., Status, Assignees, Labels). When created via the API, they are automatically visible in all views. There is no API support to add fields specifically to one view or to hide them from othersViews: These are saved layouts (e.g., "Backlog", "Current sprint"). However, the API currently does not support creating views, so this script only compares view names and logs a warning if any are missing in the destination
Features:#
- Adds
missing global fieldsfrom the template into the destination project - Logs a warning about any
missing viewsin the destination project - Supports a
dry-run mode(--dry-run) to preview intended changes without modifying anything - Supports a
verbose mode(--verbose) to display detailed command logs
How It Works#
Step-by-Step:#
- Lists all Projects V2 for the specified GitHub
--ownerusinggh project list - Locates the source (
--src-template) and destination (--dst-project) by title - Queries each project's structure using GraphQL to fetch:
- Global
fields -
Global
views(names only) -
Compares structures:
- If a field is in the source but not in the destination, it is added using
addProjectV2Field. - If a view is in the source but not in the destination, it is not created but logged with a warning.
Limitations#
| Capability | Supported | Notes |
|---|---|---|
| Create missing global fields | Yes | Done via GraphQL addProjectV2Field mutation |
| Detect and warn about missing views | Yes | Logs missing view names, but cannot recreate them |
| Delete extra fields/views | No | Not implemented (non-destructive by design) |
| Reorder fields or views | No | API does not expose position or ordering mutations |
| View-specific field visibility | No | GraphQL only exposes global field presence |
| View filters, sort orders, layout | No | Not accessible via GitHub's GraphQL API |
Current State & Technical Insights#
All fields in GitHub Projects are global- They are shared across views. While you can hide fields per view in the UI, this cannot be accessed or modified via the API.There is no GraphQL mutation to create or configure views(addProjectV2Viewdoes not exist) - Hence, the tool only checks for view names and alerts when missing.The script avoids destructive behavior- It does not delete fields or views that appear extra in the destination project.Newly added fields will be visible across all viewsunless manually hidden in the UI.You must still manually create views or configure filters, grouping, and sorting, as none of that is available through GitHub's API.
Recommended Usage#
1. To preview what changes would be made:#
sync_gh_projects.py \
--owner causify-ai \
--src-template "[TEMPLATE] Causify Project" \
--dst-project "Buildmeister" \
--dry-run --verbose
This will output:
- Fields in both source and destination
- Views in both source and destination
- Fields that would be created
- Views that are missing but cannot be added via script
2. To apply changes:#
sync_gh_projects.py \
--owner causify-ai \
--src-template "[TEMPLATE] Causify Project" \
--dst-project "Buildmeister"
This will:
- Add any missing fields that are present in the source template and absent in the destination.
- Warn about any views missing in the destination.
- Not reorder, delete, or modify any existing structure.
Example Scenario#
Source Project [TEMPLATE] Causify Project#
Fields:
- Title, Assignees, Status, Labels, Milestone, Repository, Estimate
Views:
- Backlog, Current sprint, All issues
Destination Project Buildmeister#
Fields:
- Title, Assignees, Status, Labels, Milestone
Views:
- Backlog, Current sprint
What the Script Will Do:#
- It will
addthe missing fields:Repository,Estimate - It will
log a warningthat the viewAll issuesis missing - It will
notremove or alter any other structure
Example output from script#
-
The source project is
[TEMPLATE] Causify Projectand dst project isTest_Shaunak- The dst project does not contain
All issuesview which is a req according to the template - The dst project also does not have
Assigneesfield inBacklogview - The fields are calculated globally as git does not allow to see fileds for a certain view yet
- The dst project does not contain
-
The output is displayed below:
15:11:14 - INFO sync_gh_projects.py main:304 Syncing '[TEMPLATE] Causify Project' ➔ 'Test_Shaunak' 15:11:14 - INFO sync_gh_projects.py _get_structure:180 Project #92 ([TEMPLATE] Causify Project) structure: 15:11:14 - INFO sync_gh_projects.py _get_structure:181 Fields: ['Title', 'Assignees', 'Status', 'Labels', 'Linked pull requests', 'Milestone', 'Repository', 'Reviewers', 'Parent issue', 'Sub-issues progress', 'Estimate', 'Sprint'] 15:11:14 - INFO sync_gh_projects.py _get_structure:182 Views: ['All issues', 'Current sprint', 'Next sprint', 'Backlog', 'Team capacity '] 15:11:14 - WARN sync_gh_projects.py _get_structure:183 This script cannot detect per-view visibility, filters, grouping or ordering, since GitHubs GraphQL API does not expose them. 15:11:14 - INFO sync_gh_projects.py _get_structure:180 Project #95 (Test_Shaunak) structure: 15:11:14 - INFO sync_gh_projects.py _get_structure:181 Fields: ['Title', 'Assignees', 'Status', 'Labels', 'Linked pull requests', 'Milestone', 'Repository', 'Reviewers', 'Parent issue', 'Sub-issues progress', 'Estimate', 'Sprint'] 15:11:14 - INFO sync_gh_projects.py _get_structure:182 Views: ['Current sprint', 'Next sprint', 'Backlog', 'Team capacity '] 15:11:14 - WARN sync_gh_projects.py _get_structure:183 This script cannot detect per-view visibility, filters, grouping or ordering, since GitHubs GraphQL API does not expose them. 15:11:14 - WARN sync_gh_projects.py _sync_structure:245 View 'All issues' is missing in destination. GitHub API does not currently support view creation. Please add manually. 15:11:14 - INFO sync_gh_projects.py _sync_structure:250 Structure sync complete.- The script displayes the missing fields or views in the dst project when
compared to the source.
Githubhas not introduced a way to automate view creation yet.
- The script displayes the missing fields or views in the dst project when
compared to the source.
Final Notes#
This tool is ideal for aligning the structure of GitHub Projects across teams or environments where a base template is used. It helps reduce manual setup effort and avoids configuration drift.
Because GitHub's ProjectV2 API is still limited, this tool takes a conservative approach:
- It only creates fields
- It does not delete or modify
- It only checks for view presence by name
When GitHub adds support for:#
- View creation
- View filters and layout configuration
- Field ordering
...this tool can be extended to do more complete synchronization.