From 186ebd5b5bda1cf3a2f9ee39cebe4f48dde41a66 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Mon, 22 Jul 2024 14:45:48 -0700 Subject: [PATCH 01/10] feat(dev): add created at and gt/lt operators --- dev/src/Command/ComponentInfoCommand.php | 18 ++++++++++++----- dev/src/Component.php | 25 +++++++++--------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/dev/src/Command/ComponentInfoCommand.php b/dev/src/Command/ComponentInfoCommand.php index 5cb53e94fb22..cd9cf1db5cd3 100644 --- a/dev/src/Command/ComponentInfoCommand.php +++ b/dev/src/Command/ComponentInfoCommand.php @@ -36,7 +36,7 @@ class ComponentInfoCommand extends Command 'component_name' => 'Component Name', 'package_name' => 'Package Name', 'package_version' => 'Package Version', - 'api_versions' => 'API Version', + 'api_version' => 'API Version', 'release_level' => 'Release Level', 'migration_mode' => 'Migration Mode', 'php_namespaces' => 'Php Namespace', @@ -45,15 +45,17 @@ class ComponentInfoCommand extends Command 'service_address' => 'Service Address', 'api_shortname' => 'API Shortname', 'description' => 'Description', + 'created_at' => 'Created At', 'available_api_versions' => 'Availble API Versions', ]; private static $defaultFields = [ 'component_name', 'package_name', 'package_version', - 'api_versions', + 'api_version', 'release_level', 'migration_mode', + 'created_at', 'api_shortname', ]; @@ -130,6 +132,10 @@ protected function execute(InputInterface $input, OutputInterface $output) '!=' => ($row[$field] !== $value), '~=' => strpos($row[$field], $value) !== false, '!~=' => strpos($row[$field], $value) === false, + '>' => version_compare($row[$field], $value, '>'), + '<' => version_compare($row[$field], $value, '<'), + '>=' => version_compare($row[$field], $value, '>='), + '<=' => version_compare($row[$field], $value, '<='), }) { continue 3; } @@ -201,7 +207,7 @@ private function getComponentDetails(Component $component, array $requestedField 'component_name' => $component->getName() . "\\" . $pkg->getName(), 'package_name' => $component->getPackageName(), 'package_version' => $component->getPackageVersion(), - 'api_versions' => $pkg->getName(), + 'api_version' => $pkg->getName(), 'release_level' => $component->getReleaseLevel(), 'migration_mode' => $pkg->getMigrationStatus(), 'php_namespaces' => implode("\n", array_keys($component->getNamespaces())), @@ -209,6 +215,7 @@ private function getComponentDetails(Component $component, array $requestedField 'proto_path' => $pkg->getProtoPackage(), 'service_address' => $pkg->getServiceAddress(), 'api_shortname' => $pkg->getApiShortname(), + 'created_at' => $component->getCreatedAt(), 'description' => $component->getDescription(), 'available_api_versions' => $availableApiVersions, ], $requestedFields)); @@ -220,7 +227,7 @@ private function getComponentDetails(Component $component, array $requestedField 'component_name' => $component->getName(), 'package_name' => $component->getPackageName(), 'package_version' => $component->getPackageVersion(), - 'api_versions' => implode("\n", $component->getApiVersions()), + 'api_version' => implode("\n", $component->getApiVersions()), 'release_level' => $component->getReleaseLevel(), 'migration_mode' => implode("\n", $component->getMigrationStatuses()), 'php_namespaces' => implode("\n", array_keys($component->getNamespaces())), @@ -228,6 +235,7 @@ private function getComponentDetails(Component $component, array $requestedField 'proto_path' => implode("\n", $component->getProtoPackages()), 'service_address' => implode("\n", $component->getServiceAddresses()), 'api_shortname' => implode("\n", array_filter($component->getApiShortnames())), + 'created_at' => $component->getCreatedAt()->format('Y-m-d'), 'description' => $component->getDescription(), ], $requestedFields)); @@ -271,7 +279,7 @@ private function parseFilters(string $filterString): array { $filters = []; foreach (array_filter(explode(',', $filterString)) as $filter) { - if (!preg_match('/^(\w+?)(!~=|~=|!=|=)(.+)$/', $filter, $matches)) { + if (!preg_match('/^(\w+?)(!~=|~=|!=|>=|<=|=|<|>)(.+)$/', $filter, $matches)) { throw new \InvalidArgumentException(sprintf('Invalid filter: %s', $filter)); } $filters[] = [$matches[1], $matches[3], $matches[2]]; diff --git a/dev/src/Component.php b/dev/src/Component.php index 2fc16efffb12..5432ad75a3e2 100644 --- a/dev/src/Component.php +++ b/dev/src/Component.php @@ -20,6 +20,7 @@ use Symfony\Component\Finder\Exception\DirectoryNotFoundException; use Symfony\Component\Finder\Finder; use RuntimeException; +use DateTime; /** * @internal @@ -262,29 +263,21 @@ public function getApiVersions(): array return array_map(fn($pkg) => $pkg->getName(), $this->getComponentPackages()); } + public function getCreatedAt(): DateTime + { + exec('git log --reverse --pretty=format:"%cd" ApigeeRegistry/ | head -1', $output); + return new DateTime($output[0]); + } + private function getPackagePaths(): array { $result = (new Finder())->directories()->in($this->path . '/src/')->name(self::VERSION_REGEX); $paths = array_map(fn ($file) => $file->getRelativePathname(), iterator_to_array($result)); $paths = array_reverse(array_values($paths)); - usort($paths, [$this, 'versionCompare']); + usort($paths, 'version_compare'); if (empty($paths)) { $paths = ['']; } - return $paths; - } - - private static function versionCompare(string $v1, string $v2) - { - // First, sort by API number (e.g. V1 vs V2) - $sort = substr($v1, strrpos($v1, 'V')) <=> substr($v2, strrpos($v2, 'V')); - if ($sort === 0) { - // If same API version, sort by if one is in a subdirectory - return strpos($v1, '/') <=> strpos($v2, '/'); - } - // Else, sort by release level (e.g. beta vs alpha vs GA) - $v1Sort = strpos($v1, 'beta') ? 0 : (strpos($v1, 'alpha') ? -1 : 1); - $v2Sort = strpos($v2, 'beta') ? 0 : (strpos($v2, 'alpha') ? -1 : 1); - return $v2Sort <=> $v1Sort; + return array_reverse($paths); } } From e792b8b8bc9c8f3ee7283cd07bd5e740cd216716 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Mon, 22 Jul 2024 15:23:16 -0700 Subject: [PATCH 02/10] exclude created at by default --- dev/src/Command/ComponentInfoCommand.php | 32 ++++++++++++++++-------- dev/src/Component.php | 6 ++++- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/dev/src/Command/ComponentInfoCommand.php b/dev/src/Command/ComponentInfoCommand.php index cd9cf1db5cd3..5afa8c786d0d 100644 --- a/dev/src/Command/ComponentInfoCommand.php +++ b/dev/src/Command/ComponentInfoCommand.php @@ -55,7 +55,6 @@ class ComponentInfoCommand extends Command 'api_version', 'release_level', 'migration_mode', - 'created_at', 'api_shortname', ]; @@ -87,6 +86,12 @@ protected function configure() InputOption::VALUE_NONE, 'Show available API versions for each component. Requires an API call' ) + ->addOption( + 'show-created-at', + '', + InputOption::VALUE_NONE, + 'Show when the components were created. Requires shelling out to git.' + ) ->addOption('expanded', '', InputOption::VALUE_NONE, 'Break down each component by packages') ; } @@ -102,6 +107,10 @@ protected function execute(InputInterface $input, OutputInterface $output) if ($input->getOption('show-available-api-versions')) { $fields[] = 'available_api_versions'; } + + if ($input->getOption('show-created-at')) { + $fields[] = 'created_at'; + } $this->token = $input->getOption('token'); // Parse filters @@ -197,13 +206,9 @@ private function getComponentDetails(Component $component, array $requestedField $rows = []; if ($expanded) { foreach ($component->getComponentPackages() as $pkg) { - $availableApiVersions = ''; - if (array_key_exists('available_api_versions', $requestedFields)) { - $availableApiVersions = $this->getAvailableApiVersions($component); - } // use "array_intersect_key" to filter out fields that were not requested. // use "array_replace" to sort the fields in the order they were requested. - $rows[] = array_replace($requestedFields, array_intersect_key([ + $details = array_replace($requestedFields, array_intersect_key([ 'component_name' => $component->getName() . "\\" . $pkg->getName(), 'package_name' => $component->getPackageName(), 'package_version' => $component->getPackageVersion(), @@ -215,10 +220,15 @@ private function getComponentDetails(Component $component, array $requestedField 'proto_path' => $pkg->getProtoPackage(), 'service_address' => $pkg->getServiceAddress(), 'api_shortname' => $pkg->getApiShortname(), - 'created_at' => $component->getCreatedAt(), 'description' => $component->getDescription(), - 'available_api_versions' => $availableApiVersions, ], $requestedFields)); + if (array_key_exists('available_api_versions', $requestedFields)) { + $availableApiVersions = $this->getAvailableApiVersions($component); + } + if (array_key_exists('created_at', $requestedFields)) { + $details['created_at'] = $component->getCreatedAt()->format('Y-m-d'); + } + $rows[] = $details; } } else { // use "array_intersect_key" to filter out fields that were not requested. @@ -235,14 +245,14 @@ private function getComponentDetails(Component $component, array $requestedField 'proto_path' => implode("\n", $component->getProtoPackages()), 'service_address' => implode("\n", $component->getServiceAddresses()), 'api_shortname' => implode("\n", array_filter($component->getApiShortnames())), - 'created_at' => $component->getCreatedAt()->format('Y-m-d'), 'description' => $component->getDescription(), ], $requestedFields)); - if (array_key_exists('available_api_versions', $requestedFields)) { $details['available_api_versions'] = $this->getAvailableApiVersions($component); } - + if (array_key_exists('created_at', $requestedFields)) { + $details['created_at'] = $component->getCreatedAt()->format('Y-m-d'); + } $rows[] = $details; } diff --git a/dev/src/Component.php b/dev/src/Component.php index 5432ad75a3e2..feb9cac32914 100644 --- a/dev/src/Component.php +++ b/dev/src/Component.php @@ -265,7 +265,11 @@ public function getApiVersions(): array public function getCreatedAt(): DateTime { - exec('git log --reverse --pretty=format:"%cd" ApigeeRegistry/ | head -1', $output); + exec(sprintf( + 'git log --reverse --pretty=format:"%%cd" %s/ | head -1', + $this->name, + ), $output); + return new DateTime($output[0]); } From 096a9862bacf3e4635de3966dc9a9ac156633ddb Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Fri, 2 Aug 2024 10:51:06 -0700 Subject: [PATCH 03/10] add downloads, faster filtering --- dev/src/Command/ComponentInfoCommand.php | 170 ++++++++++++----------- dev/src/Packagist.php | 7 + 2 files changed, 93 insertions(+), 84 deletions(-) diff --git a/dev/src/Command/ComponentInfoCommand.php b/dev/src/Command/ComponentInfoCommand.php index 5afa8c786d0d..27d9e5304abf 100644 --- a/dev/src/Command/ComponentInfoCommand.php +++ b/dev/src/Command/ComponentInfoCommand.php @@ -18,6 +18,8 @@ namespace Google\Cloud\Dev\Command; use Google\Cloud\Dev\Component; +use Google\Cloud\Dev\ComponentPackage; +use Google\Cloud\Dev\Packagist; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputInterface; @@ -47,6 +49,7 @@ class ComponentInfoCommand extends Command 'description' => 'Description', 'created_at' => 'Created At', 'available_api_versions' => 'Availble API Versions', + 'downloads' => 'Downloads', ]; private static $defaultFields = [ 'component_name', @@ -59,6 +62,7 @@ class ComponentInfoCommand extends Command ]; private string $token; + private Packagist $packagist; protected function configure() { @@ -68,8 +72,8 @@ protected function configure() ->addOption('csv', '', InputOption::VALUE_OPTIONAL, 'export findings to csv.', false) ->addOption('fields', 'f', InputOption::VALUE_REQUIRED, sprintf( "Comma-separated list of fields, \"all\" for all fields. The following fields are available: \n - %s\n" . - "NOTE: \"available_api_versions\" are omited by default because they take a long time to load.\n" . - "Use --show-available-api-versions to include them.\n", + "NOTE: \"available_api_versions\", \"created_at\", and \"downloads\" are omited by default because they ". + "take a long time to load.\n", implode("\n - ", array_keys(self::$allFields)) )) ->addOption('filter', '', InputOption::VALUE_REQUIRED, @@ -80,18 +84,6 @@ protected function configure() 'field to sort by (with optional ASC/DESC suffix. e.g. "component_name DESC"' ) ->addOption('token', 't', InputOption::VALUE_REQUIRED, 'Github token to use for authentication', '') - ->addOption( - 'show-available-api-versions', - '', - InputOption::VALUE_NONE, - 'Show available API versions for each component. Requires an API call' - ) - ->addOption( - 'show-created-at', - '', - InputOption::VALUE_NONE, - 'Show when the components were created. Requires shelling out to git.' - ) ->addOption('expanded', '', InputOption::VALUE_NONE, 'Break down each component by packages') ; } @@ -100,18 +92,15 @@ protected function execute(InputInterface $input, OutputInterface $output) { $fields = match($input->getOption('fields')) { null => self::$defaultFields, - 'all' => array_keys(array_diff_key(self::$allFields, ['available_api_versions' => ''])), + 'all' => array_keys(array_diff_key( + self::$allFields, + ['available_api_versions' => '', 'created_at' => '', 'downloads' => ''] + )), default => explode(',', $input->getOption('fields')), }; - if ($input->getOption('show-available-api-versions')) { - $fields[] = 'available_api_versions'; - } - - if ($input->getOption('show-created-at')) { - $fields[] = 'created_at'; - } $this->token = $input->getOption('token'); + $this->packagist = new Packagist(new Client(), '', ''); // Parse filters $filters = $this->parseFilters($input->getOption('filter') ?: ''); @@ -130,26 +119,10 @@ protected function execute(InputInterface $input, OutputInterface $output) $componentRows = $this->getComponentDetails( $component, $requestedFields, + $filters, $input->getOption('expanded') ); - foreach ($componentRows as $row) { - foreach ($filters as $filter) { - list($field, $value, $operator) = $filter; - if (!match ($operator) { - '=' => ($row[$field] === $value), - '!=' => ($row[$field] !== $value), - '~=' => strpos($row[$field], $value) !== false, - '!~=' => strpos($row[$field], $value) === false, - '>' => version_compare($row[$field], $value, '>'), - '<' => version_compare($row[$field], $value, '<'), - '>=' => version_compare($row[$field], $value, '>='), - '<=' => version_compare($row[$field], $value, '<='), - }) { - continue 3; - } - } - } $rows = array_merge($rows, $componentRows); } @@ -158,6 +131,7 @@ protected function execute(InputInterface $input, OutputInterface $output) usort($rows, function ($a, $b) use ($field) { return match ($field) { 'package_version' => version_compare($a[$field], $b[$field]), + 'downloads' => str_replace(',', '', $a[$field]) <=> str_replace(',', '', $b[$field]), default => strcmp($a[$field], $b[$field]), }; }); @@ -201,64 +175,71 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } - private function getComponentDetails(Component $component, array $requestedFields, bool $expanded): array + private function getComponentDetails(Component $component, array $requestedFields, array $filters, bool $expanded): array { $rows = []; if ($expanded) { foreach ($component->getComponentPackages() as $pkg) { - // use "array_intersect_key" to filter out fields that were not requested. - // use "array_replace" to sort the fields in the order they were requested. - $details = array_replace($requestedFields, array_intersect_key([ - 'component_name' => $component->getName() . "\\" . $pkg->getName(), - 'package_name' => $component->getPackageName(), - 'package_version' => $component->getPackageVersion(), - 'api_version' => $pkg->getName(), - 'release_level' => $component->getReleaseLevel(), - 'migration_mode' => $pkg->getMigrationStatus(), - 'php_namespaces' => implode("\n", array_keys($component->getNamespaces())), - 'github_repo' => $component->getRepoName(), - 'proto_path' => $pkg->getProtoPackage(), - 'service_address' => $pkg->getServiceAddress(), - 'api_shortname' => $pkg->getApiShortname(), - 'description' => $component->getDescription(), - ], $requestedFields)); - if (array_key_exists('available_api_versions', $requestedFields)) { - $availableApiVersions = $this->getAvailableApiVersions($component); - } - if (array_key_exists('created_at', $requestedFields)) { - $details['created_at'] = $component->getCreatedAt()->format('Y-m-d'); + if ($row = $this->getComponentDetailRow($component, $pkg, $requestedFields, $filters)) { + $rows[] = $row; } - $rows[] = $details; } } else { - // use "array_intersect_key" to filter out fields that were not requested. - // use "array_replace" to sort the fields in the order they were requested. - $details = array_replace($requestedFields, array_intersect_key([ - 'component_name' => $component->getName(), - 'package_name' => $component->getPackageName(), - 'package_version' => $component->getPackageVersion(), - 'api_version' => implode("\n", $component->getApiVersions()), - 'release_level' => $component->getReleaseLevel(), - 'migration_mode' => implode("\n", $component->getMigrationStatuses()), - 'php_namespaces' => implode("\n", array_keys($component->getNamespaces())), - 'github_repo' => $component->getRepoName(), - 'proto_path' => implode("\n", $component->getProtoPackages()), - 'service_address' => implode("\n", $component->getServiceAddresses()), - 'api_shortname' => implode("\n", array_filter($component->getApiShortnames())), - 'description' => $component->getDescription(), - ], $requestedFields)); - if (array_key_exists('available_api_versions', $requestedFields)) { - $details['available_api_versions'] = $this->getAvailableApiVersions($component); - } - if (array_key_exists('created_at', $requestedFields)) { - $details['created_at'] = $component->getCreatedAt()->format('Y-m-d'); + if ($row = $this->getComponentDetailRow($component, null, $requestedFields, $filters)) { + $rows[] = $row; } - $rows[] = $details; } return $rows; } + private function getComponentDetailRow( + Component $component, + ?ComponentPackage $package, + array $requestedFields, + array $filters, + ): ?array { + // use "array_intersect_key" to filter out fields that were not requested. + // use "array_replace" to sort the fields in the order they were requested. + $row = array_replace($requestedFields, array_intersect_key([ + 'component_name' => $component->getName() . ($package ? "/" . $package->getName() : ''), + 'package_name' => $component->getPackageName(), + 'package_version' => $component->getPackageVersion(), + 'api_version' => $package ? $package->getName() : implode("\n", $component->getApiVersions()), + 'release_level' => $component->getReleaseLevel(), + 'migration_mode' => $package ? $package->getMigrationStatus() : implode("\n", $component->getMigrationStatuses()), + 'php_namespaces' => implode("\n", array_keys($component->getNamespaces())), + 'github_repo' => $component->getRepoName(), + 'proto_path' => $package ? $package->getProtoPackage() : implode("\n", $component->getProtoPackages()), + 'service_address' => $package ? $package->getServiceAddress() : implode("\n", $component->getServiceAddresses()), + 'api_shortname' => $package ? $package->getApiShortname() : implode("\n", array_filter($component->getApiShortnames())), + 'description' => $component->getDescription(), + 'available_api_versions' => null, + 'created_at' => null, + 'downloads' => null, + ], $requestedFields)); + + // pre-filter so we don't perform excessive slow operations + if ($this->filterRow($row, $filters)) { + return null; + } + // Only add these if they've been requested (because they're slow) + if (array_key_exists('available_api_versions', $requestedFields)) { + $row['available_api_versions'] = $this->getAvailableApiVersions($component); + } + if (array_key_exists('created_at', $requestedFields)) { + $row['created_at'] = $component->getCreatedAt()->format('Y-m-d'); + } + if (array_key_exists('downloads', $requestedFields)) { + $row['downloads'] = number_format($this->packagist->getDownloads($component->getPackageName())); + } + // call again in case the filters were on the slow fields + if ($this->filterRow($row, $filters)) { + return null; + } + return $row; + } + private function getAvailableApiVersions(Component $component): string { $protos = $component->getProtoPackages(); @@ -302,4 +283,25 @@ private function parseFilters(string $filterString): array } return $filters; } + + private function filterRow(array $row, array $filters): bool + { + foreach ($filters as $filter) { + list($field, $value, $operator) = $filter; + if ($row[$field] === null) { + // bypass filter for now - these will be added later + continue; + } + if (!match ($operator) { + '=' => ($row[$field] === $value), + '!=' => ($row[$field] !== $value), + '~=' => strpos($row[$field], $value) !== false, + '!~=' => strpos($row[$field], $value) === false, + '>','<','>=','<=' => version_compare($row[$field], $value, $operator), + }) { + return true; // filter out the row + } + } + return false; + } } diff --git a/dev/src/Packagist.php b/dev/src/Packagist.php index ef4b4a98e456..fd0d037027c8 100644 --- a/dev/src/Packagist.php +++ b/dev/src/Packagist.php @@ -78,6 +78,13 @@ public function getApiToken(): string return $this->apiToken; } + public function getDownloads(string $packageName): int + { + $response = $this->client->get("https://packagist.org/packages/$packageName/stats.json"); + $data = json_decode($response->getBody()->getContents(), true); + return $data['downloads']['total'] ?? 0; + } + /** * Log an exception * From 264ffad155007756bb18cee1475e19e01b0cd7be Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Fri, 2 Aug 2024 10:54:06 -0700 Subject: [PATCH 04/10] remove clouddeploy from PHPstan --- phpstan.neon.dist | 2 -- 1 file changed, 2 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 6c6bc1b42034..26438e7a39d8 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -12,8 +12,6 @@ parameters: # Ignore Monolog3 for now, as these tests run using Monolog2 - Logging/src/LogMessageProcessor/MonologV3MessageProcessor.php - Logging/src/LogMessageProcessor/MonologV3MessageProcessor.php - # Ignore CloudDeployGrpcClient.php because it has a method name conflict - - Deploy/src/V1/CloudDeployGrpcClient.php ignoreErrors: # Problems with legacy namespaces (I'm not sure why these are throwing errors) - '#^Class Google\\[A-Za-z1-9\\]+_[A-Za-z1-9_]+ not found\.$#' From 65ad548a3454693e19b078694d46558af9ee3d47 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Fri, 2 Aug 2024 14:18:54 -0700 Subject: [PATCH 05/10] update owlbot template copyright --- dev/templates/owlbot.py.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/templates/owlbot.py.twig b/dev/templates/owlbot.py.twig index 0b8e27e4339b..16b483467945 100644 --- a/dev/templates/owlbot.py.twig +++ b/dev/templates/owlbot.py.twig @@ -1,4 +1,4 @@ -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From d42b78447797d9167477d945c72d5dd6d5f68621 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Fri, 9 Aug 2024 15:13:37 -0700 Subject: [PATCH 06/10] fix AddComponent tests --- dev/tests/fixtures/component/CustomInput/owlbot.py | 2 +- dev/tests/fixtures/component/SecretManager/owlbot.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/fixtures/component/CustomInput/owlbot.py b/dev/tests/fixtures/component/CustomInput/owlbot.py index ea6cff994433..ad31aff8ab45 100644 --- a/dev/tests/fixtures/component/CustomInput/owlbot.py +++ b/dev/tests/fixtures/component/CustomInput/owlbot.py @@ -1,4 +1,4 @@ -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/dev/tests/fixtures/component/SecretManager/owlbot.py b/dev/tests/fixtures/component/SecretManager/owlbot.py index e1e009cff500..b082607980c3 100644 --- a/dev/tests/fixtures/component/SecretManager/owlbot.py +++ b/dev/tests/fixtures/component/SecretManager/owlbot.py @@ -1,4 +1,4 @@ -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From f5352a257fdba06113b19618a80daf00e0530338 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Fri, 16 Aug 2024 10:34:05 -0700 Subject: [PATCH 07/10] fix download filter --- dev/src/Command/ComponentInfoCommand.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dev/src/Command/ComponentInfoCommand.php b/dev/src/Command/ComponentInfoCommand.php index 27d9e5304abf..0196425a0324 100644 --- a/dev/src/Command/ComponentInfoCommand.php +++ b/dev/src/Command/ComponentInfoCommand.php @@ -297,7 +297,13 @@ private function filterRow(array $row, array $filters): bool '!=' => ($row[$field] !== $value), '~=' => strpos($row[$field], $value) !== false, '!~=' => strpos($row[$field], $value) === false, - '>','<','>=','<=' => version_compare($row[$field], $value, $operator), + '>','<','>=','<=' => match($field) { + 'downloads' => version_compare( + str_replace(',' , '', $row[$field]), + $value, + $operator), + default => version_compare($row[$field], $value, $operator), + }, }) { return true; // filter out the row } From 39f8918f2a2474703020b3a95379781b7ee9500e Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Mon, 26 Aug 2024 12:07:30 -0700 Subject: [PATCH 08/10] add support for adding fields --- dev/src/Command/ComponentInfoCommand.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dev/src/Command/ComponentInfoCommand.php b/dev/src/Command/ComponentInfoCommand.php index 0196425a0324..947bb74a192e 100644 --- a/dev/src/Command/ComponentInfoCommand.php +++ b/dev/src/Command/ComponentInfoCommand.php @@ -99,6 +99,12 @@ protected function execute(InputInterface $input, OutputInterface $output) default => explode(',', $input->getOption('fields')), }; + // support "+" prefix to add requested field to the default fields + if (0 === strpos($fields[0], '+')) { + $fields[0] = substr($fields[0], 1); + $fields = array_merge(self::$defaultFields, $fields); + } + $this->token = $input->getOption('token'); $this->packagist = new Packagist(new Client(), '', ''); From 2131d0d5590a49da9a4c8376a1a143a01a2c4ada Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Mon, 26 Aug 2024 13:00:44 -0700 Subject: [PATCH 09/10] collapse rows --- dev/src/Command/ComponentInfoCommand.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/dev/src/Command/ComponentInfoCommand.php b/dev/src/Command/ComponentInfoCommand.php index 947bb74a192e..7067754e6d70 100644 --- a/dev/src/Command/ComponentInfoCommand.php +++ b/dev/src/Command/ComponentInfoCommand.php @@ -57,7 +57,6 @@ class ComponentInfoCommand extends Command 'package_version', 'api_version', 'release_level', - 'migration_mode', 'api_shortname', ]; @@ -211,14 +210,14 @@ private function getComponentDetailRow( 'component_name' => $component->getName() . ($package ? "/" . $package->getName() : ''), 'package_name' => $component->getPackageName(), 'package_version' => $component->getPackageVersion(), - 'api_version' => $package ? $package->getName() : implode("\n", $component->getApiVersions()), + 'api_version' => $package ? $package->getName() : implode(",", $component->getApiVersions()), 'release_level' => $component->getReleaseLevel(), - 'migration_mode' => $package ? $package->getMigrationStatus() : implode("\n", $component->getMigrationStatuses()), - 'php_namespaces' => implode("\n", array_keys($component->getNamespaces())), + 'migration_mode' => $package ? $package->getMigrationStatus() : implode(",", $component->getMigrationStatuses()), + 'php_namespaces' => implode(",", array_keys($component->getNamespaces())), 'github_repo' => $component->getRepoName(), - 'proto_path' => $package ? $package->getProtoPackage() : implode("\n", $component->getProtoPackages()), - 'service_address' => $package ? $package->getServiceAddress() : implode("\n", $component->getServiceAddresses()), - 'api_shortname' => $package ? $package->getApiShortname() : implode("\n", array_filter($component->getApiShortnames())), + 'proto_path' => $package ? $package->getProtoPackage() : implode(",", $component->getProtoPackages()), + 'service_address' => $package ? $package->getServiceAddress() : implode(",", $component->getServiceAddresses()), + 'api_shortname' => $package ? $package->getApiShortname() : implode(",", array_filter($component->getApiShortnames())), 'description' => $component->getDescription(), 'available_api_versions' => null, 'created_at' => null, From 04de6448a8c89f65ebf9e9fbf42b4c020eafb752 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Fri, 6 Sep 2024 10:43:43 -0700 Subject: [PATCH 10/10] add info alias --- dev/src/Command/ComponentInfoCommand.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/src/Command/ComponentInfoCommand.php b/dev/src/Command/ComponentInfoCommand.php index 7067754e6d70..82654e0184c6 100644 --- a/dev/src/Command/ComponentInfoCommand.php +++ b/dev/src/Command/ComponentInfoCommand.php @@ -66,6 +66,7 @@ class ComponentInfoCommand extends Command protected function configure() { $this->setName('component-info') + ->setAliases(['info']) ->setDescription('list info of a component or the whole library') ->addOption('component', 'c', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'get info for a single component', []) ->addOption('csv', '', InputOption::VALUE_OPTIONAL, 'export findings to csv.', false)