Repository navigation
chore: add a script that lists open pull requests from low risk to critical #1209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: production
Are you sure you want to change the base?
Changes from all commits
92dce56
ba0ee47
50e3eac
8462cee
661736c
70ef758
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # Lists open pull requests from low risk to critical, for a maintainer to run with their own gh sign-in. | ||
| # It never runs in a workflow, and it only reads: one GraphQL request per 50 open pull requests. | ||
| # | ||
| # Drafts, conflicts, failing CI and requested changes wait on their authors. The rest is split by | ||
| # what it touches, then each π on a description (not the author's) lifts it one size step. | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| gh api graphql --paginate --slurp -f query=' | ||
| query ($endCursor: String) { | ||
| repository(owner: "dev-null-sh", name: "dev-null.sh") { | ||
| pullRequests(states: OPEN, first: 50, after: $endCursor) { | ||
| pageInfo { hasNextPage endCursor } | ||
| nodes { | ||
| number title createdAt isDraft additions deletions changedFiles mergeable reviewDecision | ||
| author { login } | ||
| files(first: 100) { nodes { path } } | ||
| reactions(content: THUMBS_UP, first: 100) { nodes { user { login } } } | ||
| commits(last: 1) { nodes { commit { checkSuites(last: 20) { nodes { id conclusion app { slug } workflowRun { workflow { id } } } } } } } | ||
| } | ||
| } | ||
| } | ||
| }' | jq -r ' | ||
| [.[].data.repository.pullRequests.nodes[]] | ||
| | map( | ||
| (.additions + .deletions) as $lines | ||
| | [.files.nodes[].path] as $paths | ||
| | .size = ([10, 50, 250, 1000] | map(select($lines >= .)) | length) | ||
| | .votes = ([.reactions.nodes[].user.login // empty | select(endswith("[bot]") | not)] - [.author.login] | length) | ||
|
Comment on lines
+20
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Paginate the
Paginate the nested
|
||
| | ([.commits.nodes[].commit.checkSuites.nodes[]] | group_by(.workflowRun.workflow.id // .app.slug // .id) | map(last.conclusion)) as $suites | ||
| | .approval = any($suites[]; . == "ACTION_REQUIRED") | ||
| | .waiting = if .isDraft then "draft" | ||
| elif .mergeable == "CONFLICTING" then "merge conflicts" | ||
| elif any($suites[]; . == "FAILURE" or . == "TIMED_OUT" or . == "STARTUP_FAILURE") then "failing CI" | ||
| elif .reviewDecision == "CHANGES_REQUESTED" then "changes requested" | ||
| else null end | ||
| | .tier = if $lines >= 1000 or .changedFiles > 100 or any($paths[]; test("^(database/migrations|routes|bootstrap|config|patches|\\.github|app/Http/(Middleware|Requests))/|^app/Services/(SshSignatures|SignedRequests)\\.php$|^(composer\\.json|package\\.json|\\.npmrc|bunfig\\.toml|vet\\.json)$|\\.lock$")) then 2 | ||
| elif $lines < 250 and all($paths[]; test("^(resources/(js|css)|tests)/|\\.md$")) then 0 | ||
| else 1 end | ||
| ) | ||
| | (map(select(.waiting == null)) | sort_by(.tier, .size - .votes, .createdAt)) as $ready | ||
| | ( | ||
| ["π’ Low risk: only UI, docs or tests, under 250 lines", "π‘ Review: everything else", "π΄ Critical: data, routes, auth, config, CI or dependencies, or 1000+ lines or over 100 files"] as $titles | ||
| | range(0; 3) as $tier | ||
| | [$ready[] | select(.tier == $tier)] | ||
| | "\n\($titles[$tier]) (\(length))", | ||
| (.[] | " #\(.number) \(["XS", "S", "M", "L", "XL"][.size]) π\(.votes)\(if .approval then " needs CI approval" else "" end) \(.title)") | ||
| ), | ||
| (map(select(.waiting != null)) | "\nβΈ Waiting on the author (\(length))", (group_by(.waiting)[] | " \(.[0].waiting): \(map("#\(.number)") | join(" "))")) | ||
| ' | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Script executed:
Repository: dev-null-sh/dev-null.sh
Length of output: 3757
Script executed:
Repository: dev-null-sh/dev-null.sh
Length of output: 7137
Paginate
checkSuitesbefore evaluating CI.checkSuites(last: 20)can omit a workflow's latest suite when a commit has more than 20 suites. The grouping at line 32 only sees returned suites, so line 36 can miss an omittedFAILURE,TIMED_OUT, orSTARTUP_FAILUREand place the pull request in a ready tier.Use the connection cursor and
pageInfoto retrieve all suites before grouping them by workflow ID. CheckingtotalCountalone is not sufficient.Source: Learnings