Skip to content

Instantly share code, notes, and snippets.

@andrialexandrou
Last active December 17, 2024 18:45
Show Gist options
  • Save andrialexandrou/0e49af3fb7f5c4dac2ff457869f4fe02 to your computer and use it in GitHub Desktop.
Save andrialexandrou/0e49af3fb7f5c4dac2ff457869f4fe02 to your computer and use it in GitHub Desktop.
#!/usr/bin/env node
/**
* Pull Request Search Script
*
* Usage: node script.js <target_directory> [initial_commit]
*
* Required Arguments:
* - target_directory: Relative path to the directory to search for PRs
* Example: ./src/components
*
* Optional Arguments:
* - initial_commit: Commit hash to stop searching at (oldest commit to process)
*
* Prerequisites:
* - Node.js installed
* - GitHub CLI (gh) installed and authenticated
*
* Installation:
* 1. Ensure you're in your project's root directory
* 2. Save this script as 'pr-search.js'
* 3. Make script executable (optional on Unix-like systems):
* - Run 'chmod +x pr-search.js'
*
* IMPORTANT:
* - DO NOT COMMIT THE GENERATED OUTPUT FILE TO YOUR PROJECT
*
* Example Commands:
* - Basic usage: node pr-search.js ./src/components
* - With commit limit: node pr-search.js ./src/components abcd123
*
* Output:
* - Creates 'pr_search_<directory_name>.md'
* - Contains list of unique PR numbers with hyperlinks
* - File is saved in the same directory as the script
*
* Troubleshooting:
* - Ensure you're in the correct git repository
* - Verify GitHub CLI is authenticated
* - Check that the directory path is correct
*/
const { exec } = require('child_process');
const fs = require('fs');
// Validate directory path from command line args
const targetDirectory = process.argv[2];
const initialCommit = process.argv[3]; // Optional initial commit to stop at
if (!targetDirectory) {
console.error('Error: Please provide the relative path, in the pattern of ./your/desired/subdirectory/root/');
process.exit(1);
}
console.log(`Searching in directory: ${targetDirectory}`);
if (initialCommit) {
console.log(`Stopping at initial commit: ${initialCommit}`);
}
// Function to execute a shell command and return it as a Promise
const execShellCommand = (cmd) => {
return new Promise((resolve, reject) => {
exec(cmd, (error, stdout, stderr) => {
if (error) {
console.error(`Error executing command: ${cmd}`);
console.error(`stderr: ${stderr}`);
console.error('Full error:', error);
reject(error);
}
if (stderr) {
console.error(`stderr: ${stderr}`);
}
resolve(stdout ? stdout : stderr);
});
});
};
// Main function to get commit logs and view PR details
const main = async () => {
try {
console.log('Starting the procedure...');
// Construct git log command with optional initial commit
let gitLogCommand = initialCommit
? `git log --oneline ${initialCommit}..HEAD -- "${targetDirectory}"`
: `git log --oneline -- "${targetDirectory}"`;
// Get the commit logs with configurable directory
const logOutput = await execShellCommand(gitLogCommand);
const commits = logOutput.split('\n').map(line => line.split(' ')[0]).filter(Boolean);
const totalCommits = commits.length;
console.log(`Found ${totalCommits} commits to process`);
const uniquePrNumbers = new Set();
const allPrDetails = new Map();
let output = '# Pull Requests for Directory\n\n';
let currentCommit = 0;
// Iterate over each commit and get PR details
for (const commit of commits) {
currentCommit++;
const prListOutput = await execShellCommand(`gh pr list --state all --search ${commit}`);
console.log('PR list output:', prListOutput);
const prNumbers = prListOutput.split('\n')
.filter(Boolean) // Remove empty lines
.map(line => {
const [number, title] = line.split('\t');
return { number, title };
})
.filter(pr => pr.number && pr.title);
console.log('Extracted PR info:', prNumbers);
prNumbers.forEach(pr => {
uniquePrNumbers.add(pr.number);
allPrDetails.set(pr.number, pr.title); // Store PR details for later use
});
console.log(`Progress: ${currentCommit}/${totalCommits} commits processed`);
}
console.log('\nUnique PR numbers found:', Array.from(uniquePrNumbers));
// TODO: IMPORTANT - Replace with your actual repository details
// Use allPrDetails instead of prNumbers
for (const prNumber of uniquePrNumbers) {
console.log(`\nAdding PR #${prNumber} to output`);
const prInfo = `- [#${prNumber}: ${allPrDetails.get(prNumber) || ''}](https://github.com/YOUR_REPO_OWNER/YOUR_REPO_NAME/pull/${prNumber})\n`;
output += prInfo;
console.log('PR Info:', prInfo);
}
// Create a generic output filename based on the target directory
const sanitizedDirectoryName = targetDirectory
.replace(/[^a-z0-9]/gi, '_') // Replace non-alphanumeric characters with underscores
.replace(/(^_|_$)/g, '') // Remove leading/trailing underscores
.toLowerCase();
const outputFilename = `pr_search_${sanitizedDirectoryName}.md`;
// Write output to file
fs.writeFileSync(outputFilename, output);
console.log(`\nOutput written to ${outputFilename}`);
} catch (error) {
console.error('Full error stack trace:');
console.error(error);
}
};
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment