Last active
May 8, 2025 07:04
-
-
Save JarrydLong/1c86334e4730b63a429ba8fa34dd8375 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
//Run this via php pmpro-get-all-open-issues-across-repos.php or similar. | |
/** | |
* This recipe loops through all of the Stranger Studios Repos and checks for Open issues | |
* It then filters them and only records issues that are: | |
* - Tagged Good First Bug | |
* - Are not tagged Needs Thought | |
* - Body or Title contain the word bug in them | |
*/ | |
$org = "strangerstudios"; | |
$token = "GITHUB_TOKEN"; //Get this from https://github.com/settings/personal-access-tokens | |
$baseUrl = "https://api.github.com"; | |
$outputFile = "issues.csv"; | |
function githubRequest($url, $token) { | |
$ch = curl_init(); | |
curl_setopt($ch, CURLOPT_URL, $url); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |
curl_setopt($ch, CURLOPT_USERAGENT, "PHP Script"); | |
curl_setopt($ch, CURLOPT_HTTPHEADER, [ | |
"Authorization: token $token", | |
"Accept: application/vnd.github+json" | |
]); | |
$response = curl_exec($ch); | |
curl_close($ch); | |
return json_decode($response, true); | |
} | |
function fetchAllRepos($org, $token) { | |
$repos = githubRequest("https://api.github.com/orgs/$org/repos?per_page=100", $token); | |
return array_map(fn($r) => $r['name'], $repos); | |
} | |
function fetchMatchingIssues($org, $repo, $token) { | |
$url = "https://api.github.com/repos/$org/$repo/issues?state=open&per_page=100"; | |
$issues = githubRequest($url, $token); | |
$results = []; | |
foreach ($issues as $issue) { | |
if (isset($issue['pull_request'])) continue; | |
$labels = array_map('strtolower', array_column($issue['labels'], 'name')); | |
// Skip if "needs thought" label is present | |
if (in_array('needs thought', $labels)) continue; | |
$title = strtolower($issue['title']); | |
$body = isset($issue['body']) ? strtolower($issue['body']) : ''; | |
if ( | |
strpos($title, 'bug') !== false || | |
strpos($body, 'bug') !== false || | |
// in_array('bug', $labels) || | |
in_array('good first bug', $labels) | |
) { | |
$results[] = $issue; | |
} | |
} | |
return $results; | |
} | |
function hasPRLinked($org, $repo, $issueNumber, $token) { | |
$url = "https://api.github.com/repos/$org/$repo/issues/$issueNumber/events"; | |
$events = githubRequest($url, $token); | |
foreach ($events as $event) { | |
if ( | |
($event['event'] === 'connected' && !empty($event['commit_id'])) || | |
($event['event'] === 'cross-referenced' && isset($event['source']['issue']['pull_request'])) | |
) { | |
return true; | |
} | |
} | |
return false; | |
} | |
// Run script | |
$repos = fetchAllRepos($org, $token); | |
$csvRows = ["plugin_slug,issue_number,issue_name,issue_url,has_pr"]; | |
foreach ($repos as $repo) { | |
$issues = fetchMatchingIssues($org, $repo, $token); | |
foreach ($issues as $issue) { | |
$hasPr = hasPRLinked($org, $repo, $issue['number'], $token) ? "yes" : "no"; | |
$row = sprintf( | |
'%s,%d,"%s",%s,%s', | |
$repo, | |
$issue['number'], | |
str_replace('"', '""', $issue['title']), | |
$issue['html_url'], | |
$hasPr | |
); | |
$csvRows[] = $row; | |
} | |
} | |
file_put_contents($outputFile, implode(PHP_EOL, $csvRows)); | |
echo "✅ Exported issues to $outputFile\n"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment