From db0e88131a1b42db9957bcdb41615febd68e9b62 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Tue, 8 Oct 2024 20:22:47 -0700 Subject: [PATCH] add bug template --- dev/src/Command/ListBrokenXrefsCommand.php | 103 +++++++++++++++++++-- 1 file changed, 96 insertions(+), 7 deletions(-) diff --git a/dev/src/Command/ListBrokenXrefsCommand.php b/dev/src/Command/ListBrokenXrefsCommand.php index 1033f8acbbf1..90908218d93f 100644 --- a/dev/src/Command/ListBrokenXrefsCommand.php +++ b/dev/src/Command/ListBrokenXrefsCommand.php @@ -20,6 +20,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\Process; @@ -31,16 +32,45 @@ class ListBrokenXrefsCommand extends Command { const BROKEN_REFS_REGEX = '/\[(\w+)\] Broken xref in (.*) \((.*)\): (.*)/'; + const MIN_REFS_PER_BUG = 10; + const BUG_TEMPLATE=<<setName('list-broken-xrefs') ->setDescription('List all the broken xrefs in the documentation using ".kokoro/docs/publish.sh"') + ->addOption('write-bugs', null, InputOption::VALUE_REQUIRED, 'write the bug to the given directory') ; } protected function execute(InputInterface $input, OutputInterface $output) { + $bugDir = $input->getOption('write-bugs'); + if ($bugDir) { + $this->sha = $this->determineGoogleapisSha(); + } + $brokenReferences = []; foreach (Component::getComponents() as $component) { $input = new ArrayInput($f = [ 'command' => 'docfx', @@ -49,19 +79,78 @@ protected function execute(InputInterface $input, OutputInterface $output) $buffer = new BufferedOutput(OutputInterface::VERBOSITY_DEBUG); $returnCode = $this->getApplication()->doRun($input, $buffer); + $componentBrokenRefs = []; foreach (explode("\n", $buffer->fetch()) as $line) { if (preg_match(self::BROKEN_REFS_REGEX, $line, $matches)) { - list(, $component, $file, $ref, $brokenText) = $matches; - $link = sprintf( - '"=HYPERLINK(""https://github.com/googleapis/googleapis/blob/master/%s"", ""%s"")"', - $file, - $file - ); - $output->writeln(implode(',', [$component, $link, $ref, $brokenText])); + list(, $componentName, $file, $ref, $brokenText) = $matches; + if (false === strpos($file, '#L')) { + // If there are no line numbers, assume this is a PHP bug, and skip it + continue; + } + if ($bugDir) { + $componentBrokenRefs[] = ['file' => $file, 'text' => $brokenText]; + } else { + $link = sprintf( + '"=HYPERLINK(""https://github.com/googleapis/googleapis/blob/master/%s"", ""%s"")"', + $file, + $file + ); + $output->writeln(implode(',', [$componentName, $link, $brokenText])); + } + } + } + if ($bugDir) { + if (count($componentBrokenRefs) > self::MIN_REFS_PER_BUG) { + $file = $this->writeBuggerFile([$component->getName() => $componentBrokenRefs], $bugDir); + $output->writeln(sprintf('Wrote %s references to %s', count($componentBrokenRefs), $file)); + } else { + if (count($componentBrokenRefs) > 0) { + $brokenReferences[$component->getName()] = $componentBrokenRefs; + } + if (self::MIN_REFS_PER_BUG < $count = array_sum(array_map('count', $brokenReferences))) { + $file = $this->writeBuggerFile($brokenReferences, $bugDir); + $output->writeln(sprintf('Wrote %s references to %s', $count, $file)); + // reset broken references + $brokenReferences = []; + } } } } return 0; } + + private function writeBuggerFile(array $brokenReferences, string $bugDir): string + { + $components = array_keys($brokenReferences); + if (strlen($componentNames = implode(', ', $components)) > 80) { + $componentNames = substr($componentNames, 0, 78) . '...'; + } + $references = array_merge(...array_values($brokenReferences)); + $bugFile = sprintf('%s/broken-refs-%s.txt', $bugDir, implode('-', $components)); + $bugText = sprintf( + self::BUG_TEMPLATE, + $componentNames, + implode("\n", array_map( + fn ($ref) => sprintf( + self::BROKEN_REF_TEMPLATE, + $ref['file'], + $this->sha, + $ref['file'], + $ref['text'] + ), + $references + )) + ); + file_put_contents($bugFile, $bugText); + + return $bugFile; + } + + private function determineGoogleapisSha(): string + { + $process = new Process(['git', 'rev-parse', 'HEAD'], realpath(__DIR__ . '/../../vendor/googleapis/googleapis')); + $process->run(); + return trim($process->getOutput()); + } }