24 Commits
0.1.0 ... main

Author SHA1 Message Date
91b50b08e2 trying to add version to app
bump php and composer version in docker image
2023-12-26 10:55:35 +07:00
3433be1e79 update readme 2023-10-10 11:39:43 +07:00
47505b0927 ci: fix tags build 2023-10-10 11:31:54 +07:00
a3c2e3fe9c ci: fix tags build 2023-10-10 11:27:57 +07:00
aafcf6a106 ci: move tags logic to separate workflow 2023-10-10 11:24:42 +07:00
1bf5abb10f ci: do not run tests for tags 2023-10-10 11:22:29 +07:00
5e2981a723 ci: fix 2023-10-10 11:20:27 +07:00
c2e9c9559d add changelog 0.2.0, update readme 2023-10-10 11:16:39 +07:00
6c94c20e30 ci: do not use variable inside copy --from 2023-10-10 11:08:35 +07:00
3debe8ed1a ci: env -> vars 2023-10-10 10:41:00 +07:00
450e07890e ci: fix build command 2023-10-10 10:36:19 +07:00
9ccb6e57a3 ci: trying to add build docker image 2023-10-10 10:33:08 +07:00
949dcc147d lock phpstan version in composer.json 2023-10-05 16:30:48 +07:00
49ee12e1f6 phpstan: add another rule to ignore 2023-10-05 16:25:36 +07:00
10e2d1408c ci: add analyze action 2023-10-05 16:20:31 +07:00
18359e6dec internal: fix phpstan errors 2023-10-05 16:10:30 +07:00
fd321739d8 internal: add phpstan to dev dependencies, create config 2023-10-05 16:10:06 +07:00
eb6f66a7b1 readme: add install paragraph 2023-10-04 11:15:03 +07:00
807fb08d54 ci: add lint action 2023-10-04 11:08:29 +07:00
682507dd77 ci: remove paths 2023-10-04 10:59:26 +07:00
d433412358 test: add missing example file 2023-10-04 10:57:26 +07:00
a87af35f4d ci: fix 2023-10-04 10:54:23 +07:00
dd502706d6 add quotes 2023-10-04 10:52:29 +07:00
99d434840a add ci workflow 2023-10-04 10:50:50 +07:00
16 changed files with 263 additions and 29 deletions

21
.github/Dockerfile vendored Normal file
View File

@@ -0,0 +1,21 @@
ARG PHP_VERSION=8.2.13
ARG COMPOSER_VERSION=2.6.6
ARG MERGER_VERSION=dev-master
FROM composer:${COMPOSER_VERSION} as composer
FROM php:${PHP_VERSION}-cli-alpine as runtime
COPY --from=composer /usr/bin/composer /usr/bin/composer
WORKDIR /app
COPY composer.json composer.json
RUN composer update --no-dev
COPY merger merger
COPY src src
ENV MERGER_VERSION=${MERGER_VERSION}
ENTRYPOINT ["/app/merger"]

33
.github/workflows/ci-tags.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
---
name: ci-tags
on:
workflow_dispatch:
push:
tags:
- '**'
jobs:
build-tag:
runs-on: ubuntu-22.04
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Build docker image
run: |
DOCKER_BUILDKIT=1 docker build \
--build-arg BUILDKIT_INLINE_CACHE=1 \
--build-arg PHP_VERSION=${{ vars.DOCKER_RUNTIME_PHP_VERSION }} \
--build-arg COMPOSER_VERSION=${{ vars.DOCKER_RUNTIME_COMPOSER_VERSION }} \
--build-arg MERGER_VERSION=${{ github.ref_name }} \
--target=runtime \
--tag=dannecron/coverage-merger:${{ github.ref_name }} \
--file=./.github/Dockerfile .
- name: Login to docker hub
uses: actions-hub/docker/login@master
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
- name: Push docker image to docker-hub
uses: actions-hub/docker@master
with:
args: push dannecron/coverage-merger:${{ github.ref_name }}

80
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,80 @@
---
name: ci
on:
workflow_dispatch:
push:
branches:
- '**'
jobs:
tests:
runs-on: ubuntu-22.04
strategy:
matrix:
php_version: ['8.1', '8.2']
prefer_lowest: ['yes', '']
container: dannecron/php-for-dev:${{ matrix.php_version }}
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Init composer.lock
run: |
composer update --no-install $(if [[ "${{ matrix.prefer_lowest }}" == 'yes' ]]; then echo '--prefer-lowest'; fi)
- name: Install dependencies
run: composer install
- name: Run tests
run: composer run pest-coverage
lint:
runs-on: ubuntu-22.04
strategy:
matrix:
php_version: ['80100', '80200']
container: dannecron/php-for-dev:8.2
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Init composer.lock and install dependencies
run: composer update
- name: Run phpcs
run: vendor/bin/phpcs --standard=phpcs.xml --report=full --config-set php_version ${{ matrix.php_version }} ./src ./tests
analyze:
runs-on: ubuntu-22.04
container: dannecron/php-for-dev:8.2
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Init composer.lock and install dependencies
run: composer update
- name: Run phpstan
run: vendor/bin/phpstan analyse src tests
build-main:
runs-on: ubuntu-22.04
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs:
- tests
- lint
- analyze
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Build docker image
run: |
DOCKER_BUILDKIT=1 docker build \
--build-arg BUILDKIT_INLINE_CACHE=1 \
--build-arg PHP_VERSION=${{ vars.DOCKER_RUNTIME_PHP_VERSION }} \
--build-arg COMPOSER_VERSION=${{ vars.DOCKER_RUNTIME_COMPOSER_VERSION }} \
--target=runtime \
--tag=dannecron/coverage-merger:latest \
--file=./.github/Dockerfile .
- name: Login to docker hub
uses: actions-hub/docker/login@master
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
- name: Push docker image to docker-hub
uses: actions-hub/docker@master
with:
args: push dannecron/coverage-merger:latest

View File

@@ -1,5 +1,13 @@
# Changelog
## 0.2.0 - 2023-10-10
### Added
* phpstan to dev-dependencies
* CI
* New stage for static analysis
* New stages for building and pushing docker images
## 0.1.0 - 2023-09-21
### Added

View File

@@ -8,14 +8,38 @@ Supported formats:
### Install
// todo
Available as composer-package on [packagist](https://packagist.org/packages/dannecron/coverage-merger)
and as docker-image on [docker-hub](https://hub.docker.com/r/dannecron/coverage-merger).
#### As global composer dependency
```shell
composer global require dannecron/coverage-merger
```
#### As local composer dev-dependency
```shell
composer require --dev dannecron/coverage-merger
```
#### As docker-container
```shell
docker pull dannecron/coverage-merger:latest
```
### Usage
It's cli-app with single access point:
```shell
./merger
# if installed globally
$COMPOSER_HOME/vendor/bin/merger
# if installed locally
./vendor/bin/merger
# if pulled from docker hub
docker run --rm dannecron/coverage-merger:latest
```
```text

View File

@@ -18,6 +18,7 @@
"require-dev": {
"mockery/mockery": "1.6.6",
"pestphp/pest": "2.18.2",
"phpstan/phpstan": "1.10.37",
"squizlabs/php_codesniffer": "3.7.2"
},
"autoload": {
@@ -37,5 +38,10 @@
"allow-plugins": {
"pestphp/pest-plugin": false
}
},
"scripts": {
"pest": "vendor/bin/pest",
"pest-coverage": "env XDEBUG_MODE=coverage vendor/bin/pest --coverage-html=./tests/data/coverage-html --coverage-text",
"pest-coverage-html": "env XDEBUG_MODE=coverage vendor/bin/pest --coverage-html=./tests/data/coverage-html"
}
}

7
merger
View File

@@ -27,7 +27,12 @@ if (isset($GLOBALS['_composer_autoload_path'])) {
unset($knownAutoloadPaths, $path);
}
$app = new \Ahc\Cli\Application('clover-merger', '0.1.0');
$appVersion = \getenv('MERGER_VERSION');
if ($appVersion === false) {
$appVersion = 'dev';
}
$app = new \Ahc\Cli\Application('clover-merger', $appVersion);
$app->onException(static function (\Throwable $exception, int $exitCode) use ($app): void {
$io = $app->io();

32
phpstan.neon Normal file
View File

@@ -0,0 +1,32 @@
parameters:
level: 8
paths:
- src
- tests
scanFiles:
# Pest handles loading custom helpers only when running tests
# @see https://pestphp.com/docs/helpers#usage
- tests/Pest.php
# Mockery doesn't autoload its helper functions
- vendor/mockery/mockery/library/helpers.php
ignoreErrors:
# Pest implicitly binds $this to the current test case
# @see https://pestphp.com/docs/underlying-test-case
- message: '#^Undefined variable: \$this$#'
paths:
- tests/*
# Pest custom expectations are dynamic and not conducive static analysis
# @see https://pestphp.com/docs/expectations#custom-expectations
- messages:
- '#Call to an undefined method Pest\\Expectation|Pest\\Support\\Extendable::#'
- '#Call to an undefined method Pest\\Mixins\\Expectation#'
- '#Call to an undefined method Pest\\PendingCalls\\TestCall|Pest\\Support\\HigherOrderTapProxy::#'
- '#Access to an undefined property Pest\\Mixins\\Expectation#'
paths:
- tests/*
# Some mockery errors
- messages:
- '#Call to an undefined method Mockery\\ExpectationInterface|Mockery\\HigherOrderMessage::#'
- '#Parameter .+ Mockery\\LegacyMockInterface given.#'
paths:
- tests/*

View File

@@ -14,6 +14,9 @@ class ClassDto
) {
}
/**
* @return array<string, string>
*/
public function getProperties(): array
{
return $this->properties;

View File

@@ -22,6 +22,9 @@ class LineDto
return $this->count;
}
/**
* @return array<string, string>
*/
public function getProperties(): array
{
return $this->properties;

View File

@@ -57,6 +57,10 @@ class Parser implements ElementsDictionary
return new LineDto($properties, (int) $count);
}
/**
* @param \SimpleXMLElement $xml
* @return array<array-key, \SimpleXMLElement>
*/
public function getAttributes(\SimpleXMLElement $xml): array
{
return ((array) $xml->attributes())['@attributes'] ?? [];

View File

@@ -14,7 +14,7 @@ class Renderer
{
/**
* @param Accumulator $accumulator
* @return array
* @return array{0: string, 1: Metrics}
* @throws \DOMException
*/
public function renderAccumulator(Accumulator $accumulator): array
@@ -71,7 +71,7 @@ class Renderer
$xmlProject->appendChild($this->renderMetricsProject($xmlDocument, $projectMetrics));
return [$xmlDocument->saveXML(), $projectMetrics];
return [(string) $xmlDocument->saveXML(), $projectMetrics];
}
/**

View File

@@ -56,6 +56,11 @@ final class CloverMergeCommand extends CliCommand
}
/**
* @param array<array-key, string> $files
* @param string $output
* @param string|null $workdir
* @param bool $stats
* @return int
* @throws ExecuteException
*/
public function execute(array $files, string $output, ?string $workdir, bool $stats): int

View File

@@ -10,11 +10,11 @@ use Dannecron\CoverageMerger\Clover\Parser;
\test('examples without files', function (string $exampleFilename): void {
$handler = new Handler(new Parser());
$cloverContents = \file_get_contents(\getExamplePath($exampleFilename));
$cloverContents = (string) \file_get_contents(\getExamplePath($exampleFilename));
/** @var \SimpleXMLElement $xml */
$xml = \simplexml_load_string($cloverContents);
$accumulator = $handler->handleSingleDocument(
\simplexml_load_string($cloverContents),
);
$accumulator = $handler->handleSingleDocument($xml);
$files = $accumulator->getFiles();
\expect($files)->toHaveCount(0);
@@ -34,11 +34,11 @@ use Dannecron\CoverageMerger\Clover\Parser;
): void {
$handler = new Handler(new Parser());
$cloverContents = \file_get_contents(\getExamplePath($exampleFilename));
$cloverContents = (string) \file_get_contents(\getExamplePath($exampleFilename));
/** @var \SimpleXMLElement $xml */
$xml = \simplexml_load_string($cloverContents);
$accumulator = $handler->handleSingleDocument(
\simplexml_load_string($cloverContents),
);
$accumulator = $handler->handleSingleDocument($xml);
$files = $accumulator->getFiles();
\expect($files)->toHaveCount(1)->toHaveKey($expectedFilename);
@@ -62,11 +62,11 @@ use Dannecron\CoverageMerger\Clover\Parser;
): void {
$handler = new Handler(new Parser());
$cloverContents = \file_get_contents(\getExamplePath($exampleFilename));
$cloverContents = (string) \file_get_contents(\getExamplePath($exampleFilename));
/** @var \SimpleXMLElement $xml */
$xml = \simplexml_load_string($cloverContents);
$accumulator = $handler->handleSingleDocument(
\simplexml_load_string($cloverContents),
);
$accumulator = $handler->handleSingleDocument($xml);
$files = $accumulator->getFiles();
\expect($files)->toHaveCount(2)
@@ -81,12 +81,12 @@ use Dannecron\CoverageMerger\Clover\Parser;
\test('examples with invalid structure', function (string $exampleFilename): void {
$handler = new Handler(new Parser());
$cloverContents = \file_get_contents(\getExamplePath($exampleFilename));
$cloverContents = (string) \file_get_contents(\getExamplePath($exampleFilename));
/** @var \SimpleXMLElement $xml */
$xml = \simplexml_load_string($cloverContents);
$this->expectException(HandleException::class);
$handler->handleSingleDocument(
\simplexml_load_string($cloverContents),
);
$handler->handleSingleDocument($xml);
})
->with([
'file-with-bad-line.xml',

View File

@@ -9,18 +9,27 @@ use Dannecron\CoverageMerger\Clover\Handler;
use Dannecron\CoverageMerger\Clover\Parser;
\test('merge multiple valid files', function (): void {
$fileWithPackage = \file_get_contents(\getExamplePath('file-with-package.xml'));
$fileWithoutPackage = \file_get_contents(\getExamplePath('file-without-package.xml'));
$fileWithDifferences = \file_get_contents(\getExamplePath('file-with-differences.xml'));
$metricsAndClasses = \file_get_contents(\getExamplePath('metrics-and-classes.xml'));
$fileWithPackage = (string) \file_get_contents(\getExamplePath('file-with-package.xml'));
$fileWithoutPackage = (string) \file_get_contents(\getExamplePath('file-without-package.xml'));
$fileWithDifferences = (string) \file_get_contents(\getExamplePath('file-with-differences.xml'));
$metricsAndClasses = (string) \file_get_contents(\getExamplePath('metrics-and-classes.xml'));
$handler = new Handler(new Parser());
/** @var \SimpleXMLElement $xmlFileWithPackage */
$xmlFileWithPackage = \simplexml_load_string($fileWithPackage);
/** @var \SimpleXMLElement $xmlFileWithoutPackage */
$xmlFileWithoutPackage = \simplexml_load_string($fileWithoutPackage);
/** @var \SimpleXMLElement $xmlFileWithDifferences */
$xmlFileWithDifferences = \simplexml_load_string($fileWithDifferences);
/** @var \SimpleXMLElement $xmlMetricsAndClasses */
$xmlMetricsAndClasses = \simplexml_load_string($metricsAndClasses);
$accumulator = $handler->handle(
\simplexml_load_string($fileWithPackage),
\simplexml_load_string($fileWithoutPackage),
\simplexml_load_string($fileWithDifferences),
\simplexml_load_string($metricsAndClasses),
$xmlFileWithPackage,
$xmlFileWithoutPackage,
$xmlFileWithDifferences,
$xmlMetricsAndClasses,
);
$files = $accumulator->getFiles();

View File

@@ -0,0 +1 @@
{"foo": "bar"}