Reusable GitHub Action to automate cross-repo PR + Issue + Projects V2 workflows. This repo is set up for Sneha first, but the action is configurable for other repo pairs through .github/automation.yml.
- On PR
review_requestedorready_for_review- Add label
Ready For Reviewto the PR (if missing) - Parse
Targets: coloredcow-admin/sneha-lms#<issue_id>from PR body - Move Issue to
In reviewin Project V2SNEHA LMS - Audit comments on the Issue for changes that occurred
- Add label
- On PR review
submittedwith stateapprovedorchanges_requested- Remove any configured ready-for-review label from the PR
- Add reviewed label
status : reviewed(if missing)
- On PR
openedorsynchronize- Optionally self-assign the targeted issue to the PR author (without removing existing assignees)
- Move Issue to
In Progressif not already at/afterIn review - Audit comments only if status changed
- If Issue is not in the Project, add it first
- No spam: comments are only posted when an actual change occurred
- If a matched rule needs issue/project actions and Targets is missing/invalid, comment on the PR and exit
- A pull request template that includes a Targets line:
Targets: owner/repo#<issue_id>(cross-repo)Targets: #<issue_id>(same-repo)
- A GitHub Project V2 with a single-select Status field and options matching your config.
- Repository files:
.github/automation.yml.github/workflows/pr_automation.yml
- Create a classic PAT (recommended, works reliably with Projects V2):
- Settings -> Developer settings -> Personal access tokens -> Tokens (classic)
- Scopes:
reporead:projectwrite:projectNote: We tried fine-grained PATs, but Projects permissions are not always available there. Classic PATs work consistently for Projects V2.
- Add the token as a secret in the PR repo:
- Secret name:
GH_AUTOMATION_TOKEN
- Secret name:
- Add
.github/automation.ymland.github/workflows/pr_automation.yml(examples below).
name: PR Automation
on:
pull_request:
types: [opened, synchronize, ready_for_review, review_requested]
pull_request_review:
types: [submitted]
permissions:
contents: read
pull-requests: write
issues: write
jobs:
pr-automation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run automation
uses: ColoredCow/github-project-automation@v1
with:
token: ${{ secrets.GH_AUTOMATION_TOKEN }}
config-path: .github/automation.ymlCreate .github/automation.yml in the consuming repo:
issue_repo:
owner: coloredcow-admin
name: sneha-lms
project:
owner: coloredcow-admin
name: SNEHA LMS
status_field: Status
status_order:
- Backlog
- Ready
- On Hold
- In Progress
- In review
- QA
- Completed
labels:
ready_for_review: Ready For Review
ready_for_review_any:
- Ready For Review
- "status: ready for review"
reviewed: "status : reviewed"
reviewed_any:
- "status : reviewed"
- Reviewed
rules:
- on:
event: pull_request
actions: [opened]
do:
- assign_issue_to_pr_author: true
- on:
event: pull_request
actions: [opened, synchronize]
do:
- ensure_issue_in_project: true
- ensure_status_at_least: In Progress
- audit_on_change: true
- on:
event: pull_request
actions: [review_requested, ready_for_review]
do:
- add_pr_label_if_missing: Ready For Review
- ensure_issue_in_project: true
- ensure_status_at_least: In review
- audit_on_change: true
- on:
event: pull_request_review
actions: [submitted]
do:
- remove_pr_labels_if_present:
- Ready For Review
- "status: ready for review"
- add_pr_label_if_missing: "status : reviewed"assign_issue_to_pr_author adds the PR author to the issue assignees list only if not already assigned. Existing assignees are preserved.
token(required): Token with cross-repo + Projects V2 permissionsconfig-path(optional): Defaults to.github/automation.ymldry-run(optional): Defaults tofalseand skips writes when true
did_label_changedid_status_changeissue_number(set only when issue/project/audit behavior is executed)target_status
Required when matched rules include issue/project/audit behavior:
Targets: coloredcow-admin/sneha-lms#123
This format is intentionally strict. The action will only accept a Targets line that matches the repo configured under issue_repo in .github/automation.yml. This keeps cross-repo automation explicit and safe.
Supported whitespace variants:
Targets:coloredcow-admin/sneha-lms#123Targets: coloredcow-admin/sneha-lms #123For same-repo cases, a short format is also accepted:Targets: #123
If missing or invalid for those rules, the action comments on the PR and exits.
GITHUB_TOKEN often lacks cross-repo + Projects V2 permissions. Use a secret token input named GH_AUTOMATION_TOKEN.
Required scopes:
repo(read/write issues + PRs)read:projectandwrite:project(Projects V2)
Grant access to both repos and:
- Issues: Read & write on
coloredcow-admin/sneha-lms - Pull requests: Read & write on
coloredcow-admin/sneha - Projects: Read & write (organization-level Projects V2)
Grant installation to both repos and add:
- Issues: write
- Pull requests: write
- Projects: read/write
This action is bundled via esbuild (CJS output) and committed to dist/index.js.
Runtime: Node.js 24 (set in action.yml).
npm run build
npm run bundle- Project not found: Ensure
project.ownerandproject.namematch exactly, or setproject.number. - Status option mismatch: Ensure
status_orderentries exactly match the Project Status options. - Missing Targets: Add
Targets: coloredcow-admin/sneha-lms#<issue_id>to the PR body. - Permissions errors: Use a token with cross-repo issue/PR write and Projects V2 read/write scopes.
See examples/coloredcow-admin-sneha/.github/workflows/pr_automation.yml and examples/coloredcow-admin-sneha/.github/automation.yml.