Skip to content

Instantly share code, notes, and snippets.

@johnkary
Created November 29, 2018 14:47
Show Gist options
  • Save johnkary/d2d6452610623381ab7a6ace552f3cf9 to your computer and use it in GitHub Desktop.
Save johnkary/d2d6452610623381ab7a6ace552f3cf9 to your computer and use it in GitHub Desktop.
Search git repo for JIRA ticket numbers found in commit branch and message
#!/usr/bin/env bash
# Abort script if any command encounters an error
set -e
current_branch="$(git rev-parse --abbrev-ref HEAD)"
repo_root="$(git rev-parse --show-toplevel)"
# Get dir where this script lives
DIR="$( cd "$( dirname "$0" )" && pwd )"
php $DIR/print-remaining-jira-todos.php "$repo_root" "$current_branch" "$1"
<?php
/**
* Never forget pending TODOs!
*
* Finds JIRA tickets in the branch name and written commit message,
* then searches for each ticket across the codebase with `git grep`.
* Outputs any found lines.
*
* Usage:
*
* 1. Save `print-remaining-jira-todos.php` to your git repo root
* 2. Setup the following git hook:
*
* $ touch .git/hooks/commit-msg
* $ chmod +x .git/hooks/commit-msg
* $ vi .git/hooks/commit-msg
*
* #!/usr/bin/env bash
*
* # Abort script if any command encounters an error
* set -e
*
* current_branch="$(git rev-parse --abbrev-ref HEAD)"
* repo_root="$(git rev-parse --show-toplevel)"
*
* # Get dir where this script lives
* DIR="$( cd "$( dirname "$0" )" && pwd )"
*
* php $DIR/print-remaining-jira-todos.php "$repo_root" "$current_branch" "$1"
*/
$repoRoot = $argv[1];
$branchName = $argv[2];
$commitPath = $argv[3];
$commitMsg = getRelevantCommitText($repoRoot . '/' . $commitPath);
/**
* Isolates only written commit message that would show in the git log.
*
* @param string $commitMsgPath Path within repo where commit message is written
* @return string Commit text with line returns
*/
function getRelevantCommitText(string $commitMsgPath): string
{
$lines = [];
$foundEnd = false;
foreach (file($commitMsgPath) as $line) {
if ($foundEnd) {
return join("\n", $lines);
}
// Finds first comment line from standard git commit header
$foundEnd = strpos($line, '# Please enter the commit');
if (is_int($foundEnd)) {
$foundEnd = true;
} else {
$lines[] = $line;
}
}
return join("\n", $lines);
}
/**
* Finds JIRA tickets by regex pattern in the given text.
*
* @return string[] Found tickets
*/
function findTickets(string $pattern, string $inText): array
{
$numFound = preg_match_all($pattern, $inText, $matches);
// Report if a regex parse error occurred
if (false === $numFound) {
// Error Code lookup http://php.net/manual/en/pcre.constants.php
echo sprintf('Error searching for JIRA ticket numbers in commit. Regex Error Code: %d', preg_last_error());
exit(0);
}
if (0 === $numFound) {
return [];
}
return $matches;
};
/**
* Find ticket in given git branch name
*
* @return string[] Found tickets
*/
function findTicketsInBranch(string $branchName): array
{
// Expects branchName to be like "feature/SAMPLEMGMT-123"
$matches = findTickets('/\/([a-zA-Z]+-[\d]+)/', $branchName);
// "1" identifies the capture group in the regex above
return isset($matches[1]) ? $matches[1] : [];
}
/**
* Find ticket in given commit text
*
* @return string[] Found tickets
*/
function findTicketsInCommit(string $commitMsg): array
{
// Expects $commitMsg to be a multi-line text string
// Expects $commitMsg to not include any git comment lines beginning with "#"
$matches = findTickets('/([a-zA-Z]+-[\d]+)/', $commitMsg);
// "1" identifies the capture group in the regex above
return isset($matches[1]) ? $matches[1] : [];
}
$tickets = array_unique(array_merge(
findTicketsInCommit($commitMsg),
findTicketsInBranch($branchName)
));
foreach ($tickets as $ticket) {
$command = sprintf('cd %s && git grep --line-number %s', escapeshellarg($repoRoot), escapeshellarg($ticket));
exec($command, $outputLines);
foreach ($outputLines as $output) {
echo $output."\n\n";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment