From 4764c4e2df95e8fa36e5b8b554281358fa6f67a1 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 24 Sep 2025 11:43:21 +1000 Subject: [PATCH 1/6] list released versions --- src/Console/Application/Application.php | 2 + .../Release/AbstractReleaseCommand.php | 72 +++++++++++++++ src/Console/Command/Release/PeclCommand.php | 10 ++- .../Command/Release/PeclTagCommand.php | 13 --- .../Command/Release/ReleaseCommand.php | 81 +++++------------ .../Command/Release/ReleaseListCommand.php | 90 +++++++++++++++++++ 6 files changed, 193 insertions(+), 75 deletions(-) create mode 100644 src/Console/Command/Release/ReleaseListCommand.php diff --git a/src/Console/Application/Application.php b/src/Console/Application/Application.php index 7ac8c34..1024b37 100644 --- a/src/Console/Application/Application.php +++ b/src/Console/Application/Application.php @@ -9,6 +9,7 @@ use OpenTelemetry\DevTools\Console\Command\Release\PeclCommand; use OpenTelemetry\DevTools\Console\Command\Release\PeclTagCommand; use OpenTelemetry\DevTools\Console\Command\Release\ReleaseCommand; +use OpenTelemetry\DevTools\Console\Command\Release\ReleaseListCommand; use OpenTelemetry\DevTools\Package\Composer\MultiRepositoryInfoResolver; use OpenTelemetry\DevTools\Package\Composer\PackageAttributeResolverFactory; use OpenTelemetry\DevTools\Package\GitSplit\ConfigResolver; @@ -38,6 +39,7 @@ private function initCommands(): void ) ), new ReleaseCommand(), + new ReleaseListCommand(), new PeclCommand(), new PeclTagCommand(), ]); diff --git a/src/Console/Command/Release/AbstractReleaseCommand.php b/src/Console/Command/Release/AbstractReleaseCommand.php index 50c6552..54d3653 100644 --- a/src/Console/Command/Release/AbstractReleaseCommand.php +++ b/src/Console/Command/Release/AbstractReleaseCommand.php @@ -7,16 +7,40 @@ use Nyholm\Psr7\Request; use OpenTelemetry\DevTools\Console\Command\BaseCommand; use OpenTelemetry\DevTools\Console\Release\Commit; +use OpenTelemetry\DevTools\Console\Release\Filter; +use OpenTelemetry\DevTools\Console\Release\Project; use OpenTelemetry\DevTools\Console\Release\PullRequest; use OpenTelemetry\DevTools\Console\Release\Release; use OpenTelemetry\DevTools\Console\Release\Repository; use Psr\Http\Client\ClientInterface; use Psr\Http\Message\ResponseInterface; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Yaml\Parser; abstract class AbstractReleaseCommand extends BaseCommand { + protected const AVAILABLE_REPOS = [ + 'core' => 'open-telemetry/opentelemetry-php', + 'contrib' => 'open-telemetry/opentelemetry-php-contrib', + ]; protected ClientInterface $client; + protected Parser $parser; protected ?string $token = null; + protected array $sources = []; + + protected function interact(InputInterface $input, OutputInterface $output) + { + if (!$input->getOption('token')) { + $token = getenv('GITHUB_TOKEN'); + if ($token !== false) { + $input->setOption('token', $token); + } + } + if (!$input->getOption('token')) { + throw new \RuntimeException('No github token provided (via --token or GITHUB_TOKEN env)'); + } + } protected function headers(): array { @@ -164,4 +188,52 @@ protected function get_sha_for_branch(Repository $repository, string $branch): s return $ref->object->sha; } + + /** + * @throws \Exception + * @return array + */ + protected function find_repositories(?string $filter = null): array + { + $repositories = []; + foreach ($this->sources as $key => $repo) { + $this->output->isVerbose() && $this->output->writeln("Fetching .gitsplit.yaml for {$key} ({$repo})"); + $repositories = array_merge($repositories, $this->get_gitsplit_repositories($repo, $filter)); + } + + return $repositories; + } + + private function get_gitsplit_repositories(string $repo, ?string $filter): array + { + $url = "https://raw.githubusercontent.com/{$repo}/main/.gitsplit.yml"; + $response = $this->fetch($url); + if ($response->getStatusCode() !== 200) { + throw new \Exception("Error fetching {$url}"); + } + + $yaml = $this->parser->parse($response->getBody()->getContents()); + $repositories = []; + $this->output->isVeryVerbose() && $this->output->writeln('[RESPONSE]' . json_encode($yaml['splits'])); + foreach ($yaml['splits'] as $entry) { + $prefix = $entry['prefix']; + if ($filter && !stripos($prefix, $filter) !== false) { + $this->output->isVerbose() && $this->output->writeln(sprintf('[SKIP] %s does not match filter: %s', $prefix, $filter)); + + continue; + } + $repository = new Repository(); + $repository->upstream = new Project($repo); + $repository->upstream->path = $prefix; + $target = $entry['target']; + $repository->downstream = new Project(str_replace(['https://${GH_TOKEN}@github.com/', '.git'], ['',''], $target)); + $repositories[] = $repository; + } + + if ($this->output->isVeryVerbose()) { + $this->output->writeln('[FOUND]' . json_encode($repositories)); + } + + return $repositories; + } } diff --git a/src/Console/Command/Release/PeclCommand.php b/src/Console/Command/Release/PeclCommand.php index 18f797c..3980773 100644 --- a/src/Console/Command/Release/PeclCommand.php +++ b/src/Console/Command/Release/PeclCommand.php @@ -23,7 +23,6 @@ class PeclCommand extends AbstractReleaseCommand private const OWNER = 'open-telemetry'; private const REPO = 'opentelemetry-php-instrumentation'; private const REPOSITORY = self::OWNER . '/' . self::REPO; - private bool $force; protected function configure(): void { @@ -34,9 +33,14 @@ protected function configure(): void ; } + protected function interact(InputInterface $input, OutputInterface $output): void + { + //no-op + } + protected function execute(InputInterface $input, OutputInterface $output): int { - $this->force = $input->getOption('force'); + $force = $input->getOption('force'); $this->client = Psr18ClientDiscovery::find(); $this->registerInputAndOutput($input, $output); $project = new Project(self::REPOSITORY); @@ -52,7 +56,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $repository->commits = $this->get_downstream_unreleased_commits($repository); if (count($repository->commits) === 0) { $this->output->writeln("No unreleased commits since {$repository->latestRelease->version}"); - if (!$this->force) { + if (!$force) { return Command::SUCCESS; } } diff --git a/src/Console/Command/Release/PeclTagCommand.php b/src/Console/Command/Release/PeclTagCommand.php index 57b378e..889852c 100644 --- a/src/Console/Command/Release/PeclTagCommand.php +++ b/src/Console/Command/Release/PeclTagCommand.php @@ -30,19 +30,6 @@ protected function configure(): void ; } - protected function interact(InputInterface $input, OutputInterface $output) - { - if (!$input->getOption('token')) { - $token = getenv('GITHUB_TOKEN'); - if ($token !== false) { - $input->setOption('token', $token); - } - } - if (!$input->getOption('token')) { - throw new \RuntimeException('No github token provided (via --token or GITHUB_TOKEN env)'); - } - } - /** * @psalm-suppress PossiblyNullPropertyFetch */ diff --git a/src/Console/Command/Release/ReleaseCommand.php b/src/Console/Command/Release/ReleaseCommand.php index 320d7df..391206b 100644 --- a/src/Console/Command/Release/ReleaseCommand.php +++ b/src/Console/Command/Release/ReleaseCommand.php @@ -11,9 +11,11 @@ use OpenTelemetry\DevTools\Console\Release\Release; use OpenTelemetry\DevTools\Console\Release\Repository; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\Question; @@ -21,12 +23,6 @@ class ReleaseCommand extends AbstractReleaseCommand { - private const AVAILABLE_REPOS = [ - 'core' => 'open-telemetry/opentelemetry-php', - 'contrib' => 'open-telemetry/opentelemetry-php-contrib', - ]; - private array $sources = []; - private Parser $parser; private string $source_branch; private bool $dry_run; private bool $force; @@ -59,6 +55,7 @@ protected function interact(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output): int { + assert($output instanceof ConsoleOutputInterface); $this->token = $input->getOption('token'); $this->source_branch = $input->getOption('branch') ?? 'main'; $this->dry_run = $input->getOption('dry-run'); @@ -72,7 +69,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int $this->sources = $source ? [$source => self::AVAILABLE_REPOS[$source]] : self::AVAILABLE_REPOS; $this->client = Psr18ClientDiscovery::find(); $this->parser = new Parser(); - $this->registerInputAndOutput($input, $output); + $progress_section = $output->section(); + $main_section = $output->section(); + $this->registerInputAndOutput($input, $main_section); $repositories = []; @@ -88,68 +87,26 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::FAILURE; } - foreach ($found as $rep) { - $repository = $this->populate_release_details($rep); + $bar = new ProgressBar($progress_section, count($found)); + $bar->start(); + foreach ($found as $repository) { + $bar->setMessage($repository->downstream->project); + $repository = $this->populate_release_details($repository); if ($this->compare_diffs_to_unreleased($repository) === false) { $this->output->writeln("[SKIP] Skipping {$repository->downstream} due to differences"); } else { $repositories[] = $repository; } + $bar->advance(); + } + $bar->finish(); $this->publish_repositories($repositories); return Command::SUCCESS; } - /** - * @throws \Exception - * @return array - */ - private function find_repositories(?string $filter): array - { - $repositories = []; - foreach ($this->sources as $key => $repo) { - $this->output->isVerbose() && $this->output->writeln("Fetching .gitsplit.yaml for {$key} ({$repo})"); - $repositories = array_merge($repositories, $this->get_gitsplit_repositories($repo, $filter)); - } - - return $repositories; - } - - private function get_gitsplit_repositories(string $repo, ?string $filter): array - { - $url = "https://raw.githubusercontent.com/{$repo}/main/.gitsplit.yml"; - $response = $this->fetch($url); - if ($response->getStatusCode() !== 200) { - throw new \Exception("Error fetching {$url}"); - } - - $yaml = $this->parser->parse($response->getBody()->getContents()); - $repositories = []; - $this->output->isVeryVerbose() && $this->output->writeln('[RESPONSE]' . json_encode($yaml['splits'])); - foreach ($yaml['splits'] as $entry) { - $prefix = $entry['prefix']; - if ($filter && !str_contains($prefix, $filter)) { - $this->output->isVerbose() && $this->output->writeln(sprintf('[SKIP] %s does not match filter: %s', $prefix, $filter)); - - continue; - } - $repository = new Repository(); - $repository->upstream = new Project($repo); - $repository->upstream->path = $prefix; - $target = $entry['target']; - $repository->downstream = new Project(str_replace(['https://${GH_TOKEN}@github.com/', '.git'], ['',''], $target)); - $repositories[] = $repository; - } - - if ($this->output->isVeryVerbose()) { - $this->output->writeln('[FOUND]' . json_encode($repositories)); - } - - return $repositories; - } - /** * For a given repository, populate: * 1. latest release @@ -194,9 +151,15 @@ private function compare_diffs_to_unreleased(Repository $repository): bool $differences = array_diff($diffCommits, $foundCommits); if (count($differences) !== 0) { - $this->output->writeln('Downstream compare contains commit differences to upstream search'); + $this->output->writeln('⚠️ Warning: The following commits are present downstream but not found upstream:'); + foreach ($differences as $diff) { + $this->output->writeln(' • ' . $diff . ''); + } + $this->output->writeln('Please review these differences before continuing.'); - return false; + $helper = new QuestionHelper(); + $question = new ConfirmationQuestion('Do you want to continue despite these differences? (y/N): ', false); + return $helper->ask($this->input, $this->output, $question); } return true; diff --git a/src/Console/Command/Release/ReleaseListCommand.php b/src/Console/Command/Release/ReleaseListCommand.php new file mode 100644 index 0000000..b4dbeca --- /dev/null +++ b/src/Console/Command/Release/ReleaseListCommand.php @@ -0,0 +1,90 @@ +setName('release:list') + ->setDescription('List the latest version of each package') + ->addOption('token', ['t'], InputOption::VALUE_OPTIONAL, 'github token') + ->addOption('stable', null, InputOption::VALUE_NONE, 'only show versions with a 1.0 release') + ->addOption('unstable', null, InputOption::VALUE_NONE, 'only show versions without a 1.0 release') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $stable = $input->getOption('stable'); + $unstable = $input->getOption('unstable'); + if ($stable && $unstable) { + throw new \InvalidArgumentException('Can only use one of stable/unstable'); + } + $this->token = $input->getOption('token'); + $this->sources = self::AVAILABLE_REPOS; + $this->client = Psr18ClientDiscovery::find(); + $this->parser = new Parser(); + $this->registerInputAndOutput($input, $output); + + try { + $found = $this->find_repositories(); + } catch (\Exception $e) { + $this->output->writeln("{$e->getCode()} {$e->getMessage()}"); + + return Command::FAILURE; + } + if (count($found) === 0) { + $this->output->writeln('No repositories found!'); + + return Command::FAILURE; + } + $table = new Table($this->output); + $table->setHeaders(['Repository', 'Latest Version']); + $bar = new ProgressBar($this->output, count($found)); + $bar->start(); + foreach ($found as $repository) { + $repository->latestRelease = $this->get_latest_release($repository); + $bar->advance(); + if ($this->show($repository->latestRelease, $unstable, $stable)) { + $table->addRow([$repository->downstream->project, $repository->latestRelease->version]); + } + } + $bar->finish(); + $table->render(); + + return Command::SUCCESS; + } + + private function show(Release $release, ?bool $unstable, ?bool $stable): bool + { + if ($unstable === false && $stable === false) { + return true; + }; + if ($stable) { + return version_compare($release->version, '1.0.0', 'ge'); + } + return version_compare($release->version, '1.0.0', 'lt'); + } +} From 0fd8c853cc368e56a019202d3ddae478cbb4409a Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 24 Sep 2025 14:22:05 +1000 Subject: [PATCH 2/6] fix CI complaints --- Makefile | 3 ++- composer.json | 2 +- docker-compose.yaml | 1 - .../Behavior/UsesThirdPartyCommandTrait.php | 4 ++-- .../Packages/ValidateInstallationCommand.php | 2 +- .../Command/Release/AbstractReleaseCommand.php | 1 - src/Console/Command/Release/ReleaseCommand.php | 5 ++--- .../Command/Release/ReleaseListCommand.php | 18 +++++++----------- .../Composer/ValueObject/RepositoryFactory.php | 1 + src/Package/GitSplit/ConfigResolver.php | 2 +- 10 files changed, 17 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 3c24724..2f917da 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,8 @@ PHP_VERSION ?= 8.1 DC_RUN_PHP = docker compose run --rm php PSALM_THREADS ?= 1 -all: update style phan psalm phpstan test +all: update all-checks +all-checks: style phan psalm phpstan test install: $(DC_RUN_PHP) env XDEBUG_MODE=off composer install update: diff --git a/composer.json b/composer.json index 51f9024..059be79 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^7.4|^8.0", + "php": "^8.1", "ext-json": "*", "ext-simplexml": "*", "composer/composer": "^2.3", diff --git a/docker-compose.yaml b/docker-compose.yaml index 8a71e4f..f9ba953 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,4 +1,3 @@ -version: '3.7' services: php: image: ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base:${PHP_VERSION:-8.1} diff --git a/src/Console/Command/Packages/Behavior/UsesThirdPartyCommandTrait.php b/src/Console/Command/Packages/Behavior/UsesThirdPartyCommandTrait.php index 401ad45..b525e95 100644 --- a/src/Console/Command/Packages/Behavior/UsesThirdPartyCommandTrait.php +++ b/src/Console/Command/Packages/Behavior/UsesThirdPartyCommandTrait.php @@ -28,7 +28,7 @@ protected function createAndRunCommand( string $commandClass, InputInterface $input, OutputInterface $output, - string $workingDirectory = null + ?string $workingDirectory = null ): int { return $this->runCommand( $this->createCommand($commandClass), @@ -42,7 +42,7 @@ protected function runCommand( Command $command, InputInterface $input, OutputInterface $output, - string $workingDirectory = null + ?string $workingDirectory = null ): int { $oldWorkingDir = WorkingDirectoryResolver::create()->resolve(); diff --git a/src/Console/Command/Packages/ValidateInstallationCommand.php b/src/Console/Command/Packages/ValidateInstallationCommand.php index ab8f533..3729f79 100644 --- a/src/Console/Command/Packages/ValidateInstallationCommand.php +++ b/src/Console/Command/Packages/ValidateInstallationCommand.php @@ -265,7 +265,7 @@ private static function resolveBranchOptionValue(InputInterface $input): ?string : null; } - private function runUpdateCommand(string $workingDirectory = null): int + private function runUpdateCommand(?string $workingDirectory = null): int { return $this->createAndRunCommand( UpdateCommand::class, diff --git a/src/Console/Command/Release/AbstractReleaseCommand.php b/src/Console/Command/Release/AbstractReleaseCommand.php index 54d3653..faba1df 100644 --- a/src/Console/Command/Release/AbstractReleaseCommand.php +++ b/src/Console/Command/Release/AbstractReleaseCommand.php @@ -7,7 +7,6 @@ use Nyholm\Psr7\Request; use OpenTelemetry\DevTools\Console\Command\BaseCommand; use OpenTelemetry\DevTools\Console\Release\Commit; -use OpenTelemetry\DevTools\Console\Release\Filter; use OpenTelemetry\DevTools\Console\Release\Project; use OpenTelemetry\DevTools\Console\Release\PullRequest; use OpenTelemetry\DevTools\Console\Release\Release; diff --git a/src/Console/Command/Release/ReleaseCommand.php b/src/Console/Command/Release/ReleaseCommand.php index 391206b..e631646 100644 --- a/src/Console/Command/Release/ReleaseCommand.php +++ b/src/Console/Command/Release/ReleaseCommand.php @@ -7,7 +7,6 @@ use Http\Discovery\Psr18ClientDiscovery; use OpenTelemetry\DevTools\Console\Release\Commit; use OpenTelemetry\DevTools\Console\Release\Diff; -use OpenTelemetry\DevTools\Console\Release\Project; use OpenTelemetry\DevTools\Console\Release\Release; use OpenTelemetry\DevTools\Console\Release\Repository; use Symfony\Component\Console\Command\Command; @@ -99,7 +98,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $repositories[] = $repository; } $bar->advance(); - } $bar->finish(); $this->publish_repositories($repositories); @@ -151,7 +149,7 @@ private function compare_diffs_to_unreleased(Repository $repository): bool $differences = array_diff($diffCommits, $foundCommits); if (count($differences) !== 0) { - $this->output->writeln('⚠️ Warning: The following commits are present downstream but not found upstream:'); + $this->output->writeln('Warning: The following commits are present downstream but not found upstream:'); foreach ($differences as $diff) { $this->output->writeln(' • ' . $diff . ''); } @@ -159,6 +157,7 @@ private function compare_diffs_to_unreleased(Repository $repository): bool $helper = new QuestionHelper(); $question = new ConfirmationQuestion('Do you want to continue despite these differences? (y/N): ', false); + return $helper->ask($this->input, $this->output, $question); } diff --git a/src/Console/Command/Release/ReleaseListCommand.php b/src/Console/Command/Release/ReleaseListCommand.php index b4dbeca..65499d8 100644 --- a/src/Console/Command/Release/ReleaseListCommand.php +++ b/src/Console/Command/Release/ReleaseListCommand.php @@ -5,21 +5,13 @@ namespace OpenTelemetry\DevTools\Console\Command\Release; use Http\Discovery\Psr18ClientDiscovery; -use OpenTelemetry\DevTools\Console\Release\Commit; -use OpenTelemetry\DevTools\Console\Release\Diff; -use OpenTelemetry\DevTools\Console\Release\Filter; -use OpenTelemetry\DevTools\Console\Release\Project; use OpenTelemetry\DevTools\Console\Release\Release; -use OpenTelemetry\DevTools\Console\Release\Repository; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\ProgressBar; -use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Question\ConfirmationQuestion; -use Symfony\Component\Console\Question\Question; use Symfony\Component\Yaml\Parser; class ReleaseListCommand extends AbstractReleaseCommand @@ -68,7 +60,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $repository->latestRelease = $this->get_latest_release($repository); $bar->advance(); if ($this->show($repository->latestRelease, $unstable, $stable)) { - $table->addRow([$repository->downstream->project, $repository->latestRelease->version]); + $table->addRow([$repository->downstream->project, $repository->latestRelease->version ?? 'none']); } } $bar->finish(); @@ -77,14 +69,18 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::SUCCESS; } - private function show(Release $release, ?bool $unstable, ?bool $stable): bool + private function show(?Release $release, ?bool $unstable, ?bool $stable): bool { + if (!$release || !$release->version) { + return true; + } if ($unstable === false && $stable === false) { return true; - }; + } if ($stable) { return version_compare($release->version, '1.0.0', 'ge'); } + return version_compare($release->version, '1.0.0', 'lt'); } } diff --git a/src/Package/Composer/ValueObject/RepositoryFactory.php b/src/Package/Composer/ValueObject/RepositoryFactory.php index 38cc6c4..70576d8 100644 --- a/src/Package/Composer/ValueObject/RepositoryFactory.php +++ b/src/Package/Composer/ValueObject/RepositoryFactory.php @@ -49,6 +49,7 @@ public function buildRepository(string $url, string $type, array $packages = []) } $repositoryClass = self::TYPES[$type]; + /** @phpstan-ignore-next-line */ return new $repositoryClass( $url, diff --git a/src/Package/GitSplit/ConfigResolver.php b/src/Package/GitSplit/ConfigResolver.php index c557c83..0d42658 100644 --- a/src/Package/GitSplit/ConfigResolver.php +++ b/src/Package/GitSplit/ConfigResolver.php @@ -20,7 +20,7 @@ class ConfigResolver implements ConfigResolverInterface private string $configFile; - public function __construct(string $configFile = null) + public function __construct(?string $configFile = null) { $this->configFile = $configFile ?? $this->getDefaultConfigPath(); } From efe411cc96008b6ff0e15f3e68f3cf25739f6070 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 24 Sep 2025 14:32:37 +1000 Subject: [PATCH 3/6] dont use old workflows repo nothing else uses it, and it's got some bitrot --- .github/workflows/php.yaml | 78 +++++++++++++++++++++++++++++++++++--- Makefile | 2 - 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/.github/workflows/php.yaml b/.github/workflows/php.yaml index b904e97..6666b3d 100644 --- a/.github/workflows/php.yaml +++ b/.github/workflows/php.yaml @@ -5,10 +5,78 @@ on: branches: [ main ] pull_request: branches: [ main ] - workflow_dispatch: + +permissions: + contents: read jobs: - deploy: - uses: opentelemetry-php/gh-workflows/.github/workflows/php.yml@main - with: - matrix_extension: '["ast, json"]' + php: + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + strategy: + fail-fast: false + matrix: + php-version: ['8.1', '8.2', '8.3', '8.4'] + experimental: [false] + + env: + extensions: ast + + steps: + - uses: actions/checkout@v5 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + extensions: ${{ env.extensions }} + + - name: Validate composer.json + run: composer validate + + - name: Install dependencies + id: composer + if: steps.composer-cache.outputs.cache-hit != 'true' + run: | + composer --version + composer install --prefer-dist --no-progress + + - name: Check Style + id: style + continue-on-error: ${{ matrix.experimental }} + env: + PHP_CS_FIXER_IGNORE_ENV: 1 + run: | + vendor/php-cs-fixer/vendor/bin/php-cs-fixer --version + vendor/php-cs-fixer/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --dry-run --stop-on-violation --using-cache=no -vvv + + - name: Run Phan + id: phan + continue-on-error: ${{ matrix.experimental }} + env: + XDEBUG_MODE: off + PHAN_DISABLE_XDEBUG_WARN: 1 + run: | + vendor/phan/vendor/bin/phan --version + vendor/phan/vendor/bin/phan + + - name: Run Psalm + id: psalm + continue-on-error: ${{ matrix.experimental }} + run: | + vendor/psalm/vendor/bin/psalm --version + vendor/psalm/vendor/bin/psalm --output-format=github + + - name: Run Phpstan + id: phpstan + continue-on-error: ${{ matrix.experimental }} + run: | + vendor/bin/phpstan --version + vendor/bin/phpstan analyse --error-format=github + + - name: Run PHPUnit + id: phpunit + continue-on-error: ${{ matrix.experimental }} + run: | + vendor/bin/phpunit --version + php -dzend.assertions=1 vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover diff --git a/Makefile b/Makefile index 2f917da..b23d51b 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,4 @@ bash: $(DC_RUN_PHP) bash style: $(DC_RUN_PHP) env XDEBUG_MODE=off vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --using-cache=no -vvv -phpmetrics: - $(DC_RUN_PHP) env XDEBUG_MODE=off vendor/bin/phpmetrics --config=./phpmetrics.json --junit=junit.xml FORCE: From d3fcd7131e97366afc1c5817670d15131ca42e1d Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 24 Sep 2025 15:11:32 +1000 Subject: [PATCH 4/6] fixing checks --- .php-cs-fixer.php | 6 +- Makefile | 8 +-- composer.json | 22 +++++- docker-compose.yaml | 2 +- psalm.xml.dist | 72 ++++++++++++++++++- .../Packages/ValidateInstallationCommand.php | 2 + .../Packages/ValidatePackagesCommand.php | 2 + .../Release/AbstractReleaseCommand.php | 1 + src/Console/Command/Release/PeclCommand.php | 3 + .../Command/Release/PeclTagCommand.php | 2 + .../Command/Release/ReleaseCommand.php | 3 + .../Command/Release/ReleaseListCommand.php | 2 + src/Package/Composer/TestConfig.php | 1 + .../ValueObject/AbstractCollection.php | 6 ++ .../Composer/ValueObject/Dependency.php | 3 + .../ValueObject/DependencyCollection.php | 2 + .../Composer/ValueObject/GenericPackage.php | 1 + .../Composer/ValueObject/LibraryPackage.php | 1 + .../Composer/ValueObject/LocalRepository.php | 1 + .../ValueObject/RepositoryCollection.php | 2 + .../Composer/ValueObject/VcsRepository.php | 1 + src/Package/GitSplit/ConfigResolver.php | 1 + .../Unit/Console/Command/BaseCommandTest.php | 1 + .../Console/Command/CommandRunnerTest.php | 1 + .../UsesThirdPartyCommandTraitTest.php | 3 + .../MultiRepositoryInfoResolverTest.php | 1 + .../Composer/PackageAttributeResolverTest.php | 1 + .../Composer/TestInstallationFactoryTest.php | 1 + .../Package/Composer/TestInstallationTest.php | 1 + .../Package/Composer/TestInstallerTest.php | 2 + .../ValueObject/AbstractCollectionTest.php | 3 + .../Composer/ValueObject/DependencyTest.php | 1 + .../Composer/ValueObject/PackageTraitTest.php | 1 + .../ValueObject/RepositoryFactoryTest.php | 1 + .../ValueObject/SingleRepositoryTraitTest.php | 2 + .../ValueObject/ValueObjectTraitTest.php | 1 + .../Package/GitSplit/ConfigResolverTest.php | 1 + .../Util/RecursiveDirectoryRemoverTest.php | 1 + .../Util/WorkingDirectoryResolverTest.php | 1 + vendor-bin/phan/composer.json | 5 ++ vendor-bin/php-cs-fixer/composer.json | 5 ++ vendor-bin/psalm/composer.json | 7 ++ 42 files changed, 170 insertions(+), 14 deletions(-) create mode 100644 vendor-bin/phan/composer.json create mode 100644 vendor-bin/php-cs-fixer/composer.json create mode 100644 vendor-bin/psalm/composer.json diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index d50f68b..8be6ab0 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -21,10 +21,10 @@ 'blank_line_before_statement' => true, 'cast_spaces' => true, 'declare_strict_types' => true, - 'function_typehint_space' => true, + 'type_declaration_spaces' => true, 'include' => true, 'lowercase_cast' => true, - 'new_with_braces' => true, + 'new_with_parentheses' => true, 'no_extra_blank_lines' => true, 'no_leading_import_slash' => true, 'echo_tag_syntax' => true, @@ -35,7 +35,7 @@ 'phpdoc_scalar' => true, 'phpdoc_types' => true, 'short_scalar_cast' => true, - 'single_blank_line_before_namespace' => true, + 'blank_lines_before_namespace' => true, 'single_quote' => true, 'trailing_comma_in_multiline' => true, ]) diff --git a/Makefile b/Makefile index b23d51b..abda59d 100644 --- a/Makefile +++ b/Makefile @@ -21,15 +21,15 @@ test-integration: test-coverage: $(DC_RUN_PHP) env XDEBUG_MODE=coverage vendor/bin/phpunit --colors=always --testdox --testsuite unit --coverage-html=tests/coverage/html phan: - $(DC_RUN_PHP) env XDEBUG_MODE=off env PHAN_DISABLE_XDEBUG_WARN=1 vendor/bin/phan + $(DC_RUN_PHP) env XDEBUG_MODE=off env PHAN_DISABLE_XDEBUG_WARN=1 vendor-bin/phan/vendor/bin/phan psalm: - $(DC_RUN_PHP) env XDEBUG_MODE=off vendor/bin/psalm --threads=${PSALM_THREADS} --no-cache --php-version=${PHP_VERSION} + $(DC_RUN_PHP) env XDEBUG_MODE=off vendor-bin/psalm/vendor/bin/psalm --threads=${PSALM_THREADS} --no-cache --php-version=${PHP_VERSION} psalm-info: - $(DC_RUN_PHP) env XDEBUG_MODE=off vendor/bin/psalm --show-info=true --threads=${PSALM_THREADS} + $(DC_RUN_PHP) env XDEBUG_MODE=off vendor-bin/psalm/vendor/bin/psalm --show-info=true --threads=${PSALM_THREADS} phpstan: $(DC_RUN_PHP) env XDEBUG_MODE=off vendor/bin/phpstan analyse --memory-limit=256M bash: $(DC_RUN_PHP) bash style: - $(DC_RUN_PHP) env XDEBUG_MODE=off vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --using-cache=no -vvv + $(DC_RUN_PHP) env XDEBUG_MODE=off vendor-bin/php-cs-fixer/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --using-cache=no -vvv FORCE: diff --git a/composer.json b/composer.json index 059be79..e053909 100644 --- a/composer.json +++ b/composer.json @@ -21,6 +21,9 @@ "kriswallsmith/buzz": "^1.2", "nyholm/psr7": "^1.4", "php-http/discovery": "^1.19", + "symfony/polyfill-php82": "^1.26", + "symfony/polyfill-php83": "^1.32", + "symfony/polyfill-php84": "^1.32", "symfony/runtime": "^5.0|^6.0", "symfony/service-contracts": "^1|^2.5", "symfony/yaml": "^4.4|^5.3|^6.0" @@ -36,7 +39,12 @@ } }, "require-dev": { - "open-telemetry/dev-common-metapackage": "dev-main" + "bamarni/composer-bin-plugin": "^1.8", + "mikey179/vfsstream": "^1.6", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-mockery": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.3" }, "scripts": { "post-install-cmd": [ @@ -52,9 +60,17 @@ "config": { "sort-packages": true, "allow-plugins": { + "bamarni/composer-bin-plugin": true, "composer/package-versions-deprecated": true, - "symfony/runtime": true, - "php-http/discovery": false + "php-http/discovery": false, + "symfony/runtime": true + } + }, + "extra": { + "bamarni-bin": { + "bin-links": false, + "target-directory": "vendor-bin", + "forward-command": true } } } diff --git a/docker-compose.yaml b/docker-compose.yaml index f9ba953..da7588d 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,6 +1,6 @@ services: php: - image: ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base:${PHP_VERSION:-8.1} + image: ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base:${PHP_VERSION:-8.2} volumes: - ./:/usr/src/myapp user: "${PHP_USER}:root" diff --git a/psalm.xml.dist b/psalm.xml.dist index 35c1e1a..c8f537e 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -7,7 +7,6 @@ xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"> - @@ -16,9 +15,76 @@ - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Console/Command/Packages/ValidateInstallationCommand.php b/src/Console/Command/Packages/ValidateInstallationCommand.php index 3729f79..f67b25f 100644 --- a/src/Console/Command/Packages/ValidateInstallationCommand.php +++ b/src/Console/Command/Packages/ValidateInstallationCommand.php @@ -74,6 +74,7 @@ public function __construct( $this->initWorkingDirectory(); } + #[\Override] protected function configure(): void { $this->setDescription(self::DESCRIPTION); @@ -97,6 +98,7 @@ protected function configure(): void ); } + #[\Override] protected function execute(InputInterface $input, OutputInterface $output): int { $this->registerInputAndOutput($input, $output); diff --git a/src/Console/Command/Packages/ValidatePackagesCommand.php b/src/Console/Command/Packages/ValidatePackagesCommand.php index 3fdd8d9..dad4c49 100644 --- a/src/Console/Command/Packages/ValidatePackagesCommand.php +++ b/src/Console/Command/Packages/ValidatePackagesCommand.php @@ -34,11 +34,13 @@ public function __construct(ConfigResolverInterface $resolver, ?CommandRunner $c $this->commandRunner = $commandRunner ?? CommandRunner::create(); } + #[\Override] protected function configure(): void { $this->setDescription(self::DESCRIPTION); } + #[\Override] protected function execute(InputInterface $input, OutputInterface $output): int { $this->registerInputAndOutput($input, $output); diff --git a/src/Console/Command/Release/AbstractReleaseCommand.php b/src/Console/Command/Release/AbstractReleaseCommand.php index faba1df..59c693d 100644 --- a/src/Console/Command/Release/AbstractReleaseCommand.php +++ b/src/Console/Command/Release/AbstractReleaseCommand.php @@ -28,6 +28,7 @@ abstract class AbstractReleaseCommand extends BaseCommand protected ?string $token = null; protected array $sources = []; + #[\Override] protected function interact(InputInterface $input, OutputInterface $output) { if (!$input->getOption('token')) { diff --git a/src/Console/Command/Release/PeclCommand.php b/src/Console/Command/Release/PeclCommand.php index 3980773..d980f2d 100644 --- a/src/Console/Command/Release/PeclCommand.php +++ b/src/Console/Command/Release/PeclCommand.php @@ -24,6 +24,7 @@ class PeclCommand extends AbstractReleaseCommand private const REPO = 'opentelemetry-php-instrumentation'; private const REPOSITORY = self::OWNER . '/' . self::REPO; + #[\Override] protected function configure(): void { $this @@ -33,11 +34,13 @@ protected function configure(): void ; } + #[\Override] protected function interact(InputInterface $input, OutputInterface $output): void { //no-op } + #[\Override] protected function execute(InputInterface $input, OutputInterface $output): int { $force = $input->getOption('force'); diff --git a/src/Console/Command/Release/PeclTagCommand.php b/src/Console/Command/Release/PeclTagCommand.php index 889852c..bb48950 100644 --- a/src/Console/Command/Release/PeclTagCommand.php +++ b/src/Console/Command/Release/PeclTagCommand.php @@ -19,6 +19,7 @@ class PeclTagCommand extends AbstractReleaseCommand private const REPOSITORY = 'open-telemetry/opentelemetry-php-instrumentation'; private bool $dry_run; + #[\Override] protected function configure(): void { $this @@ -33,6 +34,7 @@ protected function configure(): void /** * @psalm-suppress PossiblyNullPropertyFetch */ + #[\Override] protected function execute(InputInterface $input, OutputInterface $output): int { $this->token = $input->getOption('token'); diff --git a/src/Console/Command/Release/ReleaseCommand.php b/src/Console/Command/Release/ReleaseCommand.php index e631646..4b427ef 100644 --- a/src/Console/Command/Release/ReleaseCommand.php +++ b/src/Console/Command/Release/ReleaseCommand.php @@ -26,6 +26,7 @@ class ReleaseCommand extends AbstractReleaseCommand private bool $dry_run; private bool $force; + #[\Override] protected function configure(): void { $this @@ -39,6 +40,7 @@ protected function configure(): void ->addOption('force', ['f'], InputOption::VALUE_NONE, 'force new releases even if no changes') ; } + #[\Override] protected function interact(InputInterface $input, OutputInterface $output) { if (!$input->getOption('token')) { @@ -52,6 +54,7 @@ protected function interact(InputInterface $input, OutputInterface $output) } } + #[\Override] protected function execute(InputInterface $input, OutputInterface $output): int { assert($output instanceof ConsoleOutputInterface); diff --git a/src/Console/Command/Release/ReleaseListCommand.php b/src/Console/Command/Release/ReleaseListCommand.php index 65499d8..d0906ba 100644 --- a/src/Console/Command/Release/ReleaseListCommand.php +++ b/src/Console/Command/Release/ReleaseListCommand.php @@ -16,6 +16,7 @@ class ReleaseListCommand extends AbstractReleaseCommand { + #[\Override] protected function configure(): void { $this @@ -27,6 +28,7 @@ protected function configure(): void ; } + #[\Override] protected function execute(InputInterface $input, OutputInterface $output): int { $stable = $input->getOption('stable'); diff --git a/src/Package/Composer/TestConfig.php b/src/Package/Composer/TestConfig.php index 79996f2..cf0f651 100644 --- a/src/Package/Composer/TestConfig.php +++ b/src/Package/Composer/TestConfig.php @@ -112,6 +112,7 @@ public function toArray(): array return $config; } + #[\Override] #[\ReturnTypeWillChange] public function jsonSerialize() { diff --git a/src/Package/Composer/ValueObject/AbstractCollection.php b/src/Package/Composer/ValueObject/AbstractCollection.php index 791435e..3946e5c 100644 --- a/src/Package/Composer/ValueObject/AbstractCollection.php +++ b/src/Package/Composer/ValueObject/AbstractCollection.php @@ -12,10 +12,12 @@ abstract class AbstractCollection extends ArrayObject implements CollectionInter { use ValueObjectTrait; + #[\Override] abstract public function getItemClass(): string; abstract public static function create($array = [], $flags = 0, $iteratorClass = ArrayIterator::class): AbstractCollection; + #[\Override] public function offsetExists($key): bool { $this->ensureOffsetType($key); @@ -23,6 +25,7 @@ public function offsetExists($key): bool return parent::offsetExists($key); } + #[\Override] public function offsetGet($key): ValueObjectInterface { $this->ensureOffsetType($key); @@ -30,6 +33,7 @@ public function offsetGet($key): ValueObjectInterface return parent::offsetGet($key); } + #[\Override] public function offsetSet($key, $value): void { $this->ensureOffsetType($key); @@ -38,6 +42,7 @@ public function offsetSet($key, $value): void parent::offsetSet($key, $value); } + #[\Override] public function offsetUnset($key): void { $this->ensureOffsetType($key); @@ -45,6 +50,7 @@ public function offsetUnset($key): void parent::offsetUnset($key); } + #[\Override] public function toArray(): array { $result = []; diff --git a/src/Package/Composer/ValueObject/Dependency.php b/src/Package/Composer/ValueObject/Dependency.php index bd711f1..28763a7 100644 --- a/src/Package/Composer/ValueObject/Dependency.php +++ b/src/Package/Composer/ValueObject/Dependency.php @@ -22,16 +22,19 @@ public static function create(string $getVersionConstraint, PackageInterface $pa return new self($getVersionConstraint, $package); } + #[\Override] public function getVersionConstraint(): string { return $this->versionConstraint; } + #[\Override] public function getPackage(): PackageInterface { return $this->package; } + #[\Override] public function toArray(): array { return [ diff --git a/src/Package/Composer/ValueObject/DependencyCollection.php b/src/Package/Composer/ValueObject/DependencyCollection.php index ee2ad1c..9588caf 100644 --- a/src/Package/Composer/ValueObject/DependencyCollection.php +++ b/src/Package/Composer/ValueObject/DependencyCollection.php @@ -8,11 +8,13 @@ class DependencyCollection extends AbstractCollection { + #[\Override] public static function create($array = [], $flags = 0, $iteratorClass = ArrayIterator::class): DependencyCollection { return new self($array, $flags, $iteratorClass); } + #[\Override] public function getItemClass(): string { return DependencyInterface::class; diff --git a/src/Package/Composer/ValueObject/GenericPackage.php b/src/Package/Composer/ValueObject/GenericPackage.php index cfc4e25..e5bf7fc 100644 --- a/src/Package/Composer/ValueObject/GenericPackage.php +++ b/src/Package/Composer/ValueObject/GenericPackage.php @@ -21,6 +21,7 @@ public static function create(string $name, string $type): self return new self($name, $type); } + #[\Override] public function getType(): string { return $this->type; diff --git a/src/Package/Composer/ValueObject/LibraryPackage.php b/src/Package/Composer/ValueObject/LibraryPackage.php index 684bad1..561f3e8 100644 --- a/src/Package/Composer/ValueObject/LibraryPackage.php +++ b/src/Package/Composer/ValueObject/LibraryPackage.php @@ -20,6 +20,7 @@ public static function create(string $path): self return new self($path); } + #[\Override] public function getType(): string { return PackageTypes::LIBRARY_TYPE; diff --git a/src/Package/Composer/ValueObject/LocalRepository.php b/src/Package/Composer/ValueObject/LocalRepository.php index 1f0d324..052190c 100644 --- a/src/Package/Composer/ValueObject/LocalRepository.php +++ b/src/Package/Composer/ValueObject/LocalRepository.php @@ -10,6 +10,7 @@ class LocalRepository implements SingleRepositoryInterface { use SingleRepositoryTrait; + #[\Override] protected function setType(): void { $this->type = RepositoryTypes::PATH_TYPE; diff --git a/src/Package/Composer/ValueObject/RepositoryCollection.php b/src/Package/Composer/ValueObject/RepositoryCollection.php index 8bc26b3..666379f 100644 --- a/src/Package/Composer/ValueObject/RepositoryCollection.php +++ b/src/Package/Composer/ValueObject/RepositoryCollection.php @@ -6,11 +6,13 @@ class RepositoryCollection extends AbstractCollection { + #[\Override] public static function create($array = [], $flags = 0, $iteratorClass = 'ArrayIterator'): RepositoryCollection { return new self($array, $flags, $iteratorClass); } + #[\Override] public function getItemClass(): string { return RepositoryInterface::class; diff --git a/src/Package/Composer/ValueObject/VcsRepository.php b/src/Package/Composer/ValueObject/VcsRepository.php index 64eb6d3..8740005 100644 --- a/src/Package/Composer/ValueObject/VcsRepository.php +++ b/src/Package/Composer/ValueObject/VcsRepository.php @@ -10,6 +10,7 @@ class VcsRepository implements SingleRepositoryInterface { use SingleRepositoryTrait; + #[\Override] protected function setType(): void { $this->type = RepositoryTypes::VCS_TYPE; diff --git a/src/Package/GitSplit/ConfigResolver.php b/src/Package/GitSplit/ConfigResolver.php index 0d42658..0388e61 100644 --- a/src/Package/GitSplit/ConfigResolver.php +++ b/src/Package/GitSplit/ConfigResolver.php @@ -25,6 +25,7 @@ public function __construct(?string $configFile = null) $this->configFile = $configFile ?? $this->getDefaultConfigPath(); } + #[\Override] public function resolve(): iterable { $gitSplitConfig = self::parseGitSplitFile($this->configFile); diff --git a/tests/Unit/Console/Command/BaseCommandTest.php b/tests/Unit/Console/Command/BaseCommandTest.php index 2e38c09..41954e7 100644 --- a/tests/Unit/Console/Command/BaseCommandTest.php +++ b/tests/Unit/Console/Command/BaseCommandTest.php @@ -31,6 +31,7 @@ class BaseCommandTest extends TestCase private OutputInterface $output; private SymfonyStyle $style; + #[\Override] protected function setUp(): void { $this->instance = new ConcreteCommand(); diff --git a/tests/Unit/Console/Command/CommandRunnerTest.php b/tests/Unit/Console/Command/CommandRunnerTest.php index 6f7c434..8ec035e 100644 --- a/tests/Unit/Console/Command/CommandRunnerTest.php +++ b/tests/Unit/Console/Command/CommandRunnerTest.php @@ -19,6 +19,7 @@ class CommandRunnerTest extends TestCase { private CommandRunner $instance; + #[\Override] protected function setUp(): void { $this->instance = CommandRunner::create(); diff --git a/tests/Unit/Console/Command/Packages/Behavior/UsesThirdPartyCommandTraitTest.php b/tests/Unit/Console/Command/Packages/Behavior/UsesThirdPartyCommandTraitTest.php index 11d5eab..5090fcf 100644 --- a/tests/Unit/Console/Command/Packages/Behavior/UsesThirdPartyCommandTraitTest.php +++ b/tests/Unit/Console/Command/Packages/Behavior/UsesThirdPartyCommandTraitTest.php @@ -25,6 +25,7 @@ class UsesThirdPartyCommandTraitTest extends TestCase private object $instance; private Application $application; + #[\Override] protected function setUp(): void { $this->instance = $this->createInstance(); @@ -202,6 +203,7 @@ public function doEnsureCommandClass(string $commandClass) return self::ensureCommandClass($commandClass); } + #[\Override] public function getApplication(): Application { return $this->application; @@ -234,6 +236,7 @@ public function __construct(int $runResult = Command::SUCCESS, bool $throwExcept parent::__construct('test/command'); } + #[\Override] public function run(InputInterface $input, OutputInterface $output): int { if ($this->throwException) { diff --git a/tests/Unit/Package/Composer/MultiRepositoryInfoResolverTest.php b/tests/Unit/Package/Composer/MultiRepositoryInfoResolverTest.php index 321739f..88c5c6b 100644 --- a/tests/Unit/Package/Composer/MultiRepositoryInfoResolverTest.php +++ b/tests/Unit/Package/Composer/MultiRepositoryInfoResolverTest.php @@ -43,6 +43,7 @@ class MultiRepositoryInfoResolverTest extends TestCase ]; private const ROOT_PATH = 'vfs://root/'; + #[\Override] protected function setUp(): void { $this->setUpVcs(); diff --git a/tests/Unit/Package/Composer/PackageAttributeResolverTest.php b/tests/Unit/Package/Composer/PackageAttributeResolverTest.php index 0a11c73..e92cd6d 100644 --- a/tests/Unit/Package/Composer/PackageAttributeResolverTest.php +++ b/tests/Unit/Package/Composer/PackageAttributeResolverTest.php @@ -60,6 +60,7 @@ class PackageAttributeResolverTest extends TestCase private const COMPOSER_FILE_NAME = 'composer.json'; + #[\Override] public function setUp(): void { $this->setUpVcs(); diff --git a/tests/Unit/Package/Composer/TestInstallationFactoryTest.php b/tests/Unit/Package/Composer/TestInstallationFactoryTest.php index a3db364..7c41676 100644 --- a/tests/Unit/Package/Composer/TestInstallationFactoryTest.php +++ b/tests/Unit/Package/Composer/TestInstallationFactoryTest.php @@ -23,6 +23,7 @@ class TestInstallationFactoryTest extends TestCase private TestInstallationFactory $instance; private TestConfigFactory $testConfigFactory; + #[\Override] protected function setUp(): void { $this->testConfigFactory = $this->createMock(TestConfigFactory::class); diff --git a/tests/Unit/Package/Composer/TestInstallationTest.php b/tests/Unit/Package/Composer/TestInstallationTest.php index e15ebbb..12f0fc9 100644 --- a/tests/Unit/Package/Composer/TestInstallationTest.php +++ b/tests/Unit/Package/Composer/TestInstallationTest.php @@ -41,6 +41,7 @@ class TestInstallationTest extends TestCase private vfsStreamDirectory $root; private string $testDirectory; + #[\Override] protected function setUp(): void { $this->root = vfsStream::setup(self::ROOT_DIR); diff --git a/tests/Unit/Package/Composer/TestInstallerTest.php b/tests/Unit/Package/Composer/TestInstallerTest.php index cb66563..4b94701 100644 --- a/tests/Unit/Package/Composer/TestInstallerTest.php +++ b/tests/Unit/Package/Composer/TestInstallerTest.php @@ -27,6 +27,7 @@ class TestInstallerTest extends TestCase private RecursiveDirectoryRemover $directoryRemover; private vfsStreamDirectory $root; + #[\Override] protected function setUp(): void { $this->root = vfsStream::setup(self::ROOT_DIR); @@ -39,6 +40,7 @@ protected function setUp(): void ); } + #[\Override] protected function tearDown(): void { TestInstaller::setDirectoryRemover(null); diff --git a/tests/Unit/Package/Composer/ValueObject/AbstractCollectionTest.php b/tests/Unit/Package/Composer/ValueObject/AbstractCollectionTest.php index a7f03e4..fb7692a 100644 --- a/tests/Unit/Package/Composer/ValueObject/AbstractCollectionTest.php +++ b/tests/Unit/Package/Composer/ValueObject/AbstractCollectionTest.php @@ -20,6 +20,7 @@ class AbstractCollectionTest extends TestCase private const OFFSET_KEY = 'foo'; + #[\Override] protected function setUp(): void { $this->instance = $this->createInstance(); @@ -153,11 +154,13 @@ public function provideInvalidValueTypes(): array private function createInstance(): AbstractCollection { return new class() extends AbstractCollection { + #[\Override] public static function create($array = [], $flags = 0, $iteratorClass = ArrayIterator::class): AbstractCollection { return new self($array, $flags, $iteratorClass); } + #[\Override] public function getItemClass(): string { return ValueObjectInterface::class; diff --git a/tests/Unit/Package/Composer/ValueObject/DependencyTest.php b/tests/Unit/Package/Composer/ValueObject/DependencyTest.php index 4223147..088c978 100644 --- a/tests/Unit/Package/Composer/ValueObject/DependencyTest.php +++ b/tests/Unit/Package/Composer/ValueObject/DependencyTest.php @@ -25,6 +25,7 @@ class DependencyTest extends TestCase private Dependency $instance; private PackageInterface $package; + #[\Override] public function setUp(): void { $this->instance = Dependency::create( diff --git a/tests/Unit/Package/Composer/ValueObject/PackageTraitTest.php b/tests/Unit/Package/Composer/ValueObject/PackageTraitTest.php index 02db10b..7662607 100644 --- a/tests/Unit/Package/Composer/ValueObject/PackageTraitTest.php +++ b/tests/Unit/Package/Composer/ValueObject/PackageTraitTest.php @@ -65,6 +65,7 @@ public function __construct() $this->name = PackageTraitTest::ATTRIBUTES[PackageInterface::NAME_ATTRIBUTE]; } + #[\Override] public function getType(): string { return PackageTraitTest::ATTRIBUTES[PackageInterface::TYPE_ATTRIBUTE]; diff --git a/tests/Unit/Package/Composer/ValueObject/RepositoryFactoryTest.php b/tests/Unit/Package/Composer/ValueObject/RepositoryFactoryTest.php index eddfed0..91725cf 100644 --- a/tests/Unit/Package/Composer/ValueObject/RepositoryFactoryTest.php +++ b/tests/Unit/Package/Composer/ValueObject/RepositoryFactoryTest.php @@ -20,6 +20,7 @@ class RepositoryFactoryTest extends AbstractRepositoryTest private RepositoryFactory $instance; private PackageInterface $package; + #[\Override] public function setUp(): void { $this->instance = RepositoryFactory::create( diff --git a/tests/Unit/Package/Composer/ValueObject/SingleRepositoryTraitTest.php b/tests/Unit/Package/Composer/ValueObject/SingleRepositoryTraitTest.php index cb39f11..c14b09e 100644 --- a/tests/Unit/Package/Composer/ValueObject/SingleRepositoryTraitTest.php +++ b/tests/Unit/Package/Composer/ValueObject/SingleRepositoryTraitTest.php @@ -19,6 +19,7 @@ class SingleRepositoryTraitTest extends AbstractRepositoryTest private SingleRepositoryInterface $repository; + #[\Override] public function setUp(): void { $this->repository = $this->createInstance(); @@ -77,6 +78,7 @@ class SingleRepositoryTraitImplementation implements SingleRepositoryInterface { use SingleRepositoryTrait; + #[\Override] protected function setType(): void { $this->type = SingleRepositoryTraitTest::REPOSITORY_TYPE; diff --git a/tests/Unit/Package/Composer/ValueObject/ValueObjectTraitTest.php b/tests/Unit/Package/Composer/ValueObject/ValueObjectTraitTest.php index db8e068..82b239b 100644 --- a/tests/Unit/Package/Composer/ValueObject/ValueObjectTraitTest.php +++ b/tests/Unit/Package/Composer/ValueObject/ValueObjectTraitTest.php @@ -31,6 +31,7 @@ private function createInstance(): ValueObjectInterface return new class() implements ValueObjectInterface { use ValueObjectTrait; + #[\Override] public function toArray(): array { return ValueObjectTraitTest::ATTRIBUTES; diff --git a/tests/Unit/Package/GitSplit/ConfigResolverTest.php b/tests/Unit/Package/GitSplit/ConfigResolverTest.php index 0cc819f..ba5acfc 100644 --- a/tests/Unit/Package/GitSplit/ConfigResolverTest.php +++ b/tests/Unit/Package/GitSplit/ConfigResolverTest.php @@ -29,6 +29,7 @@ class ConfigResolverTest extends TestCase 'C' => 'src/C', ]; + #[\Override] public function setUp(): void { $this->setUpVcs(); diff --git a/tests/Unit/Util/RecursiveDirectoryRemoverTest.php b/tests/Unit/Util/RecursiveDirectoryRemoverTest.php index 5818e01..21e0123 100644 --- a/tests/Unit/Util/RecursiveDirectoryRemoverTest.php +++ b/tests/Unit/Util/RecursiveDirectoryRemoverTest.php @@ -34,6 +34,7 @@ class RecursiveDirectoryRemoverTest extends TestCase private RecursiveDirectoryRemover $remover; private vfsStreamDirectory $root; + #[\Override] public function setUp(): void { $this->remover = RecursiveDirectoryRemover::create(); diff --git a/tests/Unit/Util/WorkingDirectoryResolverTest.php b/tests/Unit/Util/WorkingDirectoryResolverTest.php index f0ae136..4b57fbd 100644 --- a/tests/Unit/Util/WorkingDirectoryResolverTest.php +++ b/tests/Unit/Util/WorkingDirectoryResolverTest.php @@ -14,6 +14,7 @@ class WorkingDirectoryResolverTest extends TestCase { private const TEST_WORKING_DIRECTORY = __DIR__ . '/../../../'; + #[\Override] public function tearDown(): void { WorkingDirectoryResolver::setCwdTestResponse(null); diff --git a/vendor-bin/phan/composer.json b/vendor-bin/phan/composer.json new file mode 100644 index 0000000..b0a5d45 --- /dev/null +++ b/vendor-bin/phan/composer.json @@ -0,0 +1,5 @@ +{ + "require-dev": { + "phan/phan": "^5.4" + } +} diff --git a/vendor-bin/php-cs-fixer/composer.json b/vendor-bin/php-cs-fixer/composer.json new file mode 100644 index 0000000..08156aa --- /dev/null +++ b/vendor-bin/php-cs-fixer/composer.json @@ -0,0 +1,5 @@ +{ + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.54" + } +} diff --git a/vendor-bin/psalm/composer.json b/vendor-bin/psalm/composer.json new file mode 100644 index 0000000..1603814 --- /dev/null +++ b/vendor-bin/psalm/composer.json @@ -0,0 +1,7 @@ +{ + "require-dev": { + "vimeo/psalm": "^6", + "psalm/plugin-mockery": "^1", + "psalm/plugin-phpunit": "^0.19" + } +} From 71c492ac13d5af701f1b15b076b8d19d3e8d1bcb Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 24 Sep 2025 15:12:40 +1000 Subject: [PATCH 5/6] fix tools locations --- .github/workflows/php.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/php.yaml b/.github/workflows/php.yaml index 6666b3d..e5e3593 100644 --- a/.github/workflows/php.yaml +++ b/.github/workflows/php.yaml @@ -47,8 +47,8 @@ jobs: env: PHP_CS_FIXER_IGNORE_ENV: 1 run: | - vendor/php-cs-fixer/vendor/bin/php-cs-fixer --version - vendor/php-cs-fixer/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --dry-run --stop-on-violation --using-cache=no -vvv + vendor-bin/php-cs-fixer/vendor/bin/php-cs-fixer --version + vendor-bin/php-cs-fixer/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --dry-run --stop-on-violation --using-cache=no -vvv - name: Run Phan id: phan @@ -57,15 +57,15 @@ jobs: XDEBUG_MODE: off PHAN_DISABLE_XDEBUG_WARN: 1 run: | - vendor/phan/vendor/bin/phan --version - vendor/phan/vendor/bin/phan + vendor-bin/phan/vendor/bin/phan --version + vendor-bin/phan/vendor/bin/phan - name: Run Psalm id: psalm continue-on-error: ${{ matrix.experimental }} run: | - vendor/psalm/vendor/bin/psalm --version - vendor/psalm/vendor/bin/psalm --output-format=github + vendor-bin/psalm/vendor/bin/psalm --version + vendor-bin/psalm/vendor/bin/psalm --output-format=github - name: Run Phpstan id: phpstan From 1f11b5e7ad37f2bc558b3ec6078a739a26f310f2 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 24 Sep 2025 15:17:07 +1000 Subject: [PATCH 6/6] fix phpstan --- .../Packages/Behavior/UsesThirdPartyCommandTraitTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Console/Command/Packages/Behavior/UsesThirdPartyCommandTraitTest.php b/tests/Unit/Console/Command/Packages/Behavior/UsesThirdPartyCommandTraitTest.php index 5090fcf..2df7388 100644 --- a/tests/Unit/Console/Command/Packages/Behavior/UsesThirdPartyCommandTraitTest.php +++ b/tests/Unit/Console/Command/Packages/Behavior/UsesThirdPartyCommandTraitTest.php @@ -160,7 +160,7 @@ public function doCreateAndRunCommand( string $commandClass, InputInterface $input, OutputInterface $output, - string $workingDirectory = null + ?string $workingDirectory = null ): int { return $this->createAndRunCommand( $commandClass, @@ -174,7 +174,7 @@ public function doRunCommand( Command $command, InputInterface $input, OutputInterface $output, - string $workingDirectory = null + ?string $workingDirectory = null ): int { return $this->runCommand( $command,