[FEATURE] Add scheduled project status sync workflow - #69
[FEATURE] Add scheduled project status sync workflow#69John McCall (lowlydba) wants to merge 6 commits into
Conversation
Syncs the Status field for issues in multiple org projects (Overture #84, places-surge #78) every 3 hours. Most recently updated status wins. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: John McCall <john@overturemaps.org>
…ules Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: John McCall <john@overturemaps.org>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: John McCall <john@overturemaps.org>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: John McCall <john@overturemaps.org>
There was a problem hiding this comment.
Pull request overview
Adds a scheduled GitHub Actions workflow plus a new composite action (.github/actions/sync-project-status) to keep the Status field synchronized across multiple org-level ProjectsV2 for issues/PRs that appear in more than one project, using a “most recently updated wins” rule and supporting a dry-run mode.
Changes:
- Introduces a scheduled + manually-dispatchable workflow that assumes AWS OIDC credentials and retrieves a GitHub App PEM from AWS Secrets Manager before running the sync action.
- Adds a composite action implemented via
actions/github-script, split into GraphQL IO (src/projects.js) and pure planning logic (src/plan.js). - Documents behavior, setup requirements, and conflict resolution in an action README.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/sync-project-status.yml | New scheduled/dispatch workflow to run the sync action with AWS OIDC + Secrets Manager PEM fetch. |
| .github/actions/sync-project-status/action.yml | Composite action wiring: mask key, mint GitHub App token, execute sync via github-script. |
| .github/actions/sync-project-status/src/projects.js | GraphQL query/mutation layer for ProjectsV2 fetch + status updates. |
| .github/actions/sync-project-status/src/plan.js | Pure planning logic to compute which project items need status updates/skips. |
| .github/actions/sync-project-status/src/index.js | Orchestration: validate projects, log skipped items, apply or dry-run changes. |
| .github/actions/sync-project-status/README.md | Usage and behavior documentation for the action and its workflow integration. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| }`; | ||
|
|
||
| const UPDATE_STATUS_MUTATION = ` | ||
| mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) { |
There was a problem hiding this comment.
Not a bug: ProjectV2FieldValue.singleSelectOptionId is String in the schema, not ID, so String! is the correct variable type. Verified via introspection.
Hard-code the app client ID, OIDC role ARN, and Secrets Manager secret ID to match OvertureMaps/omf-github-terraform#91, same convention as safe-settings-sync. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: John McCall <john@overturemaps.org>
Eric Godwin (ericgodwin)
left a comment
There was a problem hiding this comment.
Copilot had a lot to say but I am good :)
Mask multi-line PEM line-by-line, validate projectNumbers input, and guard against null item nodes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: John McCall <john@overturemaps.org>
Closes OvertureMaps/tf-data-platform#4632
Adds a
sync-project-statuscomposite action plus a thin scheduled workflow (every 3 hours, plus manual dispatch with adry_runinput) that keeps theStatusfield in sync for issues belonging to multiple org projects. Currently wired to Overture (#84) and places-surge (#78).Statuswins (updatedAton the field value) and is copied to the othersThe action splits into discrete modules:
src/plan.jsis pure planning logic with no IO,src/projects.jsholds the GraphQL queries and mutation,src/index.jsorchestrates. See the action README for behavior and conflict resolution details.Setup
The default
GITHUB_TOKENcan't touch org ProjectsV2, so the workflow authenticates as theoverture-project-managerGitHub App. It assumes the narrowgha-project-manager-secrets-readerOIDC role and fetches the app PEM from Secrets Manager at runtime, same pattern assafe-settings-sync. The app, role, and secret are wired up in OvertureMaps/omf-github-terraform#91 (tracked by OvertureMaps/tf-data-platform#4658), which should merge and apply first. The client ID isn't sensitive and is hard-coded inline, likeSAFE_SETTINGS_APP_ID.Security
Ran a security review against the public-repo Actions threat model, no exploitable findings:
schedule+workflow_dispatchonly, so no fork-PR secret exposure; the dispatch input is a typed boolean into awith:valueproject_managerpersist-credentials: false, sparse checkout,contents: readTesting
Ran the action's modules locally against both live projects in dry-run mode (real
fetchProject/buildPlancode,gh-backed GraphQL stub): 44 shared items, 3 real mismatches found, all with sensible winners (two Overture-side edits winning over stale places-surge values, one status propagating to an unset Overture item). The mutation path and the OIDC/Secrets Manager fetch haven't run yet; the first scheduled run after the terraform PR applies will exercise them.zizmoris clean on the workflow and action.