Script to change the status of a pull request in a GitHub project. On macOS, when the script is run and any pull requests have their project status changed, a desktop notification will appear with the count of how many PRs were moved.
The script gets the list of pull requests in the specified project, iterates through them, and updates the status field you specify based on the PR's state.
Install the gh
command line tool. gh
will be used to authenticate with the GitHub API.
You'll also need Ruby installed; I built this script
with Ruby version 2.7.1p83.
In GraphiQL, run a GraphQL query like this one to get IDs for the options in your project's "Status"-like column:
query {
organization(login: "yourOrg") {
projectV2(number: 123) { # e.g., https://github.com/orgs/yourOrg/projects/123
field(name: "Status") { ... on ProjectV2SingleSelectField { options { name id } } }
}
}
}
You'll use the option IDs from the GraphQL query to tell project_pull_mover where to move your pull requests in your project.
Download the .gem file from the latest release. Install it via:
gem install project_pull_mover.gem
There should now be a project_pull_mover
executable in your path.
Usage: project_pull_mover [options]
-p, --project-number NUM Project number (required), e.g., 123 for https://github.com/orgs/someorg/projects/123
-o, --project-owner OWNER Project owner login (required), e.g., someorg for https://github.com/orgs/someorg/projects/123
-t, --project-owner-type TYPE Project owner type (required), either 'user' or 'organization'
-s, --status-field STATUS Status field name (required), name of a single-select field in the project
-i, --in-progress ID Option ID of 'In progress' column for status field
-a, --not-against-main ID Option ID of 'Not against main' column for status field
-n, --needs-review ID Option ID of 'Needs review' column for status field
-r, --ready-to-deploy ID Option ID of 'Ready to deploy' column for status field
-c, --conflicting ID Option ID of 'Conflicting' column for status field
-g, --ignored IDS Optional comma-separated list of option IDs of columns like 'Blocked' or 'On hold' for status field
-q, --quiet Quiet mode, suppressing all output except errors
-h, --gh-path PATH Path to gh executable
-f, --failing-test-label LABEL Name of the label to apply to a pull request that has failing required builds
-u, --author AUTHOR Specify a username so that only PRs in the project authored by that user are changed
-m, --mark-draft Also mark pull requests as a draft when setting them to In Progress, Not Against Main, or Conflicting status.
-v, --version Print version and exit
Run the script with:
project_pull_mover
Follow instructions about required options and run suggested gh auth
commands to get the right permissions, e.g.,
error: your authentication token is missing required scopes [project]
To request it, run: gh auth refresh -s project
Example use:
project_pull_mover -p 123 -o myOrg -t organization -i 123abc -a zyx987 -n ab123cd -r a1b2c3 -c z9y8x7 -g "idkfa1,iddqd2" -s "Status"
Example no-op output:
⏳ Authenticating with GitHub...
✅ Authenticated as GitHub user @cheshire137
ℹ️ 'Status' options enabled: In progress, Not against main, Needs review, Ready to deploy, Conflicting, Ignored
⏳ Looking up items in project 123 owned by @myOrg...
✅ Found 20 pull requests in project
ℹ️ Found pull requests in 4 unique repositories by @someRepoOwner
⏳ Looking up more info about each pull request in project...
✅ Loaded extra pull request info
ℹ️ No pull requests needed a different status
Example output when some pull requests had the wrong 'Status':
⏳ Authenticating with GitHub...
✅ Authenticated as GitHub user @cheshire137
⏳ Looking up items in project 123 owned by @myOrg...
✅ Found 20 pull requests in project
ℹ️ Found pull requests in 4 unique repositories by @someRepoOwner
⏳ Looking up more info about each pull request in project...
✅ Loaded extra pull request info
⏳ Moving someRepoOwner/repo1#330751 out of In progress ✏️ column to 'Conflicting'...
⏳ Moving someRepoOwner/repo2#335443 out of In progress ✏️ column to 'Conflicting'...
⏳ Moving someRepoOwner/repo2#337389 out of In progress ✏️ column to 'Conflicting'...
ℹ️ Updated status for 3 pull requests
Make a directory for holding logs from the script. Here is an example config for crontab:
# Runs every 30 minutes, Monday through Friday, between 9am and 5pm:
*/31,*/1 9-17 * * 1-5 /path/to/this/repo/project_pull_mover.rb -p 123 -o myOrg -t organization -i 123abc -a zyx987 -n ab123cd -r a1b2c3 -c z9y8x7 -g "idkfa1,iddqd2" -s "Status" -q -h "/usr/local/bin/gh" >/path/to/your/log/directory/stdout.log 2>/path/to/your/log/directory/stderr.log
If you have problems with gh
not being authenticated, try a cron line like:
# Runs every 30 minutes, Monday through Friday, between 9am and 5pm:
*/30 9-17 * * 1-5 echo "YOUR_TOKEN_HERE" | /usr/local/bin/gh auth login --with-token && /path/to/this/repo/project_pull_mover.rb -p 123 -o myOrg -t organization -i 123abc -a zyx987 -n ab123cd -r a1b2c3 -c z9y8x7 -g "idkfa1,iddqd2" -s "Status" -q -h "/usr/local/bin/gh" >/path/to/your/log/directory/stdout.log 2>/path/to/your/log/directory/stderr.log
To get the token to use, try running gh auth refresh -s project
first and go through the interactive authentication
flow. Once complete, you can run gh auth token
to get your GitHub API token.
Install dependencies:
bundle install
Check types:
bundle exec srb tc
Run tests:
bundle exec rake test
Run a single test file with a command like ruby -Ilib:test PATH_TO_TEST
, for example:
ruby -Ilib:test test/lib/project_pull_mover/utils_test.rb
Update VERSION
in version.rb.
git tag v0.0.x main # use the same version as in `VERSION`
git push origin tag v0.0.x
This will trigger a workflow that builds the gem and creates a new release.
gem build project_pull_mover.gemspec
This will create a file like project_pull_mover-0.0.1.gem which you can then install:
gem install project_pull_mover-0.0.1.gem
project_pull_mover
should then be an executable available to you.