diff --git a/CHANGELOG.md b/CHANGELOG.md index ddced8f..8a3f4cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,9 @@ # Changelog -All notable changes to `swisnl/phpstan-bitbucket` will be documented in this file. +All notable changes to `swisnl/bitbucket-reports` will be documented in this file. Updates should follow the [Keep a CHANGELOG](https://keepachangelog.com/) principles. ## [Unreleased] - Nothing - -## [0.2.0] - 2022-11-04 - -This release lists changes compared to [alxt/phpstan-bitbucket:0.1.0](https://github.com/modprobe/phpstan-bitbucket/releases/tag/v0.1.0). - -### Changed - -- Bumped minimum PHP version to 7.4 and add support for PHP 8. -- Bumped dependencies. -- This error formatter will now also report errors using the default table error formatter. -- Changed package name to `swisnl/phpstan-bitbucket` and namespace to `Swis\PHPStan\ErrorFormatter`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e24d509..2d2f8de 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Contributions are **welcome** and will be fully **credited**. -We accept contributions via Pull Requests on [GitHub](https://github.com/swisnl/phpstan-bitbucket). +We accept contributions via Pull Requests on [GitHub](https://github.com/swisnl/bitbucket-reports). ## Pull Requests diff --git a/README.md b/README.md index 930e17d..bc833a0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# PHPStan Bitbucket error formatter +# Bitbucket reports [![Latest Version on Packagist][ico-version]][link-packagist] [![Software License][ico-license]](LICENSE.md) @@ -6,40 +6,19 @@ [![Total Downloads][ico-downloads]][link-downloads] [![Maintained by SWIS][ico-swis]][link-swis] -This PHPStan error formatter will add annotations in Bitbucket, for example in pull requests, similar to the built-in GitHub formatting. +Helper classes for Bitbucket reports. ## Installation Via Composer ```bash -composer require --dev swisnl/phpstan-bitbucket +composer require swisnl/bitbucket-reports ``` -If you also have [phpstan/extension-installer](https://github.com/phpstan/extension-installer) installed, then you're all set! - -
- Manual installation - -If you don't want to use `phpstan/extension-installer`, include extension.neon in your project's PHPStan config: - -```neon -includes: - - vendor/swisnl/phpstan-bitbucket/extension.neon -``` -
- ## Usage -To use this custom error formatter you need to run PHPStan with `--error-format=bitbucket` option. For example: -```shell -vendor/bin/phpstan analyse src -l8 --error-format=bitbucket -``` - -## Screenshots - -![Annotations](img/annotations.png) -![Report](img/report.png) +This is a collection of helper classes for Bitbucket reports, used by several of our projects. Please refer to these projects for usage examples. ## Changelog @@ -55,9 +34,9 @@ If you discover any security related issues, please email security@swis.nl inste ## Credits -This package is a fork of [alxt/phpstan-bitbucket][link-fork] with some updates. +This package contains files from [alxt/phpstan-bitbucket][link-fork]. -- [Alexander Timmermann][link-author] +- [Jasper Zonneveld][link-author] - [All Contributors][link-contributors] ## License @@ -70,16 +49,16 @@ This package is [Treeware](https://treeware.earth). If you use it in production, [SWIS][link-swis] is a web agency from Leiden, the Netherlands. We love working with open source software. -[ico-version]: https://img.shields.io/packagist/v/swisnl/phpstan-bitbucket.svg?style=flat-square +[ico-version]: https://img.shields.io/packagist/v/swisnl/bitbucket-reports.svg?style=flat-square [ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square [ico-treeware]: https://img.shields.io/badge/Treeware-%F0%9F%8C%B3-lightgreen.svg?style=flat-square -[ico-downloads]: https://img.shields.io/packagist/dt/swisnl/phpstan-bitbucket.svg?style=flat-square +[ico-downloads]: https://img.shields.io/packagist/dt/swisnl/bitbucket-reports.svg?style=flat-square [ico-swis]: https://img.shields.io/badge/%F0%9F%9A%80-maintained%20by%20SWIS-%230737A9.svg?style=flat-square -[link-packagist]: https://packagist.org/packages/swisnl/phpstan-bitbucket -[link-downloads]: https://packagist.org/packages/swisnl/phpstan-bitbucket -[link-treeware]: https://plant.treeware.earth/swisnl/phpstan-bitbucket +[link-packagist]: https://packagist.org/packages/swisnl/bitbucket-reports +[link-downloads]: https://packagist.org/packages/swisnl/bitbucket-reports +[link-treeware]: https://plant.treeware.earth/swisnl/bitbucket-reports [link-fork]: https://github.com/modprobe/phpstan-bitbucket -[link-author]: https://github.com/modprobe +[link-author]: https://github.com/JaZo [link-contributors]: ../../contributors [link-swis]: https://www.swis.nl diff --git a/composer.json b/composer.json index 94b71a0..2638f3f 100644 --- a/composer.json +++ b/composer.json @@ -1,16 +1,14 @@ { - "name": "swisnl/phpstan-bitbucket", - "type": "phpstan-extension", - "description": "PHPStan error formatter for Bitbucket Pipeline Reports", + "name": "swisnl/bitbucket-reports", + "type": "library", + "description": "Helper classes for Bitbucket Pipeline Reports", "keywords": [ - "phpstan", - "error-formatter", "bitbucket", "pipeline", "reports", "testing" ], - "homepage": "https://github.com/swisnl/phpstan-bitbucket", + "homepage": "https://github.com/swisnl/bitbucket-reports", "license": "MIT", "authors": [ { @@ -25,10 +23,9 @@ } ], "require": { - "php": "^7.4|^8.0", + "php": "^8.0", "ext-json": "*", "guzzlehttp/guzzle": "^7.0", - "phpstan/phpstan": "^1.0", "ramsey/uuid": "^4.0" }, "require-dev": { @@ -36,18 +33,10 @@ }, "autoload": { "psr-4": { - "Swis\\PHPStan\\ErrorFormatter\\": "src" - } - }, - "extra": { - "phpstan": { - "includes": [ - "extension.neon" - ] + "Swis\\Bitbucket\\Reports\\": "src" } }, "scripts": { - "analyse": "vendor/bin/phpstan analyse", "format": "vendor/bin/pint" }, "config": { diff --git a/img/annotations.png b/img/annotations.png deleted file mode 100644 index c4c5581..0000000 Binary files a/img/annotations.png and /dev/null differ diff --git a/img/report.png b/img/report.png deleted file mode 100644 index 750a049..0000000 Binary files a/img/report.png and /dev/null differ diff --git a/phpstan.neon b/phpstan.neon deleted file mode 100644 index 32d0f9e..0000000 --- a/phpstan.neon +++ /dev/null @@ -1,12 +0,0 @@ -includes: - - ./extension.neon - -parameters: - paths: - - src - - level: 8 - - ignoreErrors: - - excludePaths: diff --git a/src/BitbucketApiClient.php b/src/BitbucketApiClient.php index 4038a34..d52704e 100644 --- a/src/BitbucketApiClient.php +++ b/src/BitbucketApiClient.php @@ -1,6 +1,8 @@ httpClient = new Client([ 'base_uri' => $baseUrl, RequestOptions::PROXY => $proxyUrl, ]); + $this->relativePathHelper = new ParentDirectoryRelativePathHelper(BitbucketConfig::cloneDir()); } - public function createReport(int $numberOfIssues = 0): UuidInterface + public function createReport(string $title, int $numberOfIssues = 0): UuidInterface { $payload = $numberOfIssues > 0 ? [ - 'title' => self::REPORT_TITLE, + 'title' => $title, 'details' => sprintf('This PR introduces %d new issue(s).', $numberOfIssues), 'report_type' => 'BUG', 'result' => 'FAILED', ] : [ - 'title' => self::REPORT_TITLE, + 'title' => $title, 'details' => 'This PR introduces no new issues.', 'report_type' => 'BUG', 'result' => 'PASSED', @@ -65,7 +68,7 @@ public function addAnnotation( ]; if ($filePath !== null) { - $payload['path'] = $filePath; + $payload['path'] = $this->relativePathHelper->getRelativePath($filePath); } if ($line !== null) { diff --git a/src/BitbucketConfig.php b/src/BitbucketConfig.php index 0eec834..ed66653 100644 --- a/src/BitbucketConfig.php +++ b/src/BitbucketConfig.php @@ -1,6 +1,8 @@ tableErrorFormatter = $tableErrorFormatter; - // @phpstan-ignore-next-line - $this->relativePathHelper = new ParentDirectoryRelativePathHelper(BitbucketConfig::cloneDir()); - $this->apiClient = new BitbucketApiClient(); - } - - public function formatErrors(AnalysisResult $analysisResult, Output $output): int - { - $this->tableErrorFormatter->formatErrors($analysisResult, $output); - - $reportUuid = $this->apiClient->createReport($analysisResult->getTotalErrorsCount()); - - foreach ($analysisResult->getFileSpecificErrors() as $error) { - $this->apiClient->addAnnotation( - $reportUuid, - $error->getMessage(), - // @phpstan-ignore-next-line - $this->relativePathHelper->getRelativePath($error->getFile()), - $error->getLine() - ); - } - - foreach ($analysisResult->getNotFileSpecificErrors() as $error) { - $this->apiClient->addAnnotation( - $reportUuid, - $error, - null, - null - ); - } - - return (int) $analysisResult->hasErrors(); - } -} diff --git a/src/ParentDirectoryRelativePathHelper.php b/src/ParentDirectoryRelativePathHelper.php new file mode 100644 index 0000000..5221e14 --- /dev/null +++ b/src/ParentDirectoryRelativePathHelper.php @@ -0,0 +1,55 @@ +getFilenameParts($filename)); + } + + /** + * @return string[] + */ + public function getFilenameParts(string $filename): array + { + $schemePosition = strpos($filename, '://'); + if ($schemePosition !== \false) { + $filename = substr($filename, $schemePosition + 3); + } + $parentParts = explode('/', trim(str_replace('\\', '/', $this->parentDirectory), '/')); + $parentPartsCount = count($parentParts); + $filenameParts = explode('/', trim(str_replace('\\', '/', $filename), '/')); + $filenamePartsCount = count($filenameParts); + $i = 0; + for (; $i < $filenamePartsCount; $i++) { + if ($parentPartsCount < $i + 1) { + break; + } + $parentPath = implode('/', array_slice($parentParts, 0, $i + 1)); + $filenamePath = implode('/', array_slice($filenameParts, 0, $i + 1)); + if ($parentPath !== $filenamePath) { + break; + } + } + if ($i === 0) { + return [$filename]; + } + $dotsCount = $parentPartsCount - $i; + if ($dotsCount < 0) { + throw new \RuntimeException('This should not happen.'); + } + + return array_merge(array_fill(0, $dotsCount, '..'), array_slice($filenameParts, $i)); + } +}