Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-enable Roave/BackwardCompatibilityCheck using filter script #240

Merged
merged 3 commits into from
Oct 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 18 additions & 19 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,21 @@ jobs:
- name: "Run Psalm"
run: "vendor/bin/psalm"

# Disabled for now... - see https://github.com/scoutapp/scout-apm-php/issues/209
# roave-backwards-compatibility-check:
# name: "Check for Backward Compatibility breaks"
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v2
# with:
# fetch-depth: 0
# - name: "Install PHP"
# uses: shivammathur/setup-php@v2
# with:
# coverage: "none"
# php-version: "7.4" # https://github.com/Roave/BackwardCompatibilityCheck/issues/283
# - name: "Require Roave/BackwardCompatibilityCheck"
# run: "composer require --no-update --no-interaction --prefer-dist --prefer-stable --dev roave/backward-compatibility-check"
# - name: "Composer update with new requirements"
# run: "composer update --no-interaction --prefer-dist --prefer-stable"
# - name: "Check for BC breaks"
# run: "vendor/bin/roave-backward-compatibility-check --format=markdown"
roave-backwards-compatibility-check:
name: "Check for Backward Compatibility breaks"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: "Install PHP"
uses: shivammathur/setup-php@v2
with:
coverage: "none"
php-version: "7.4" # https://github.com/Roave/BackwardCompatibilityCheck/issues/283
- name: "Require Roave/BackwardCompatibilityCheck"
run: "composer require --no-update --no-interaction --prefer-dist --prefer-stable --dev roave/backward-compatibility-check:dev-allow-dev-deps-to-be-installed"
- name: "Composer update with new requirements"
run: "composer update --no-interaction --prefer-dist --prefer-stable"
- name: "Check for BC breaks"
run: ".github/workflows/roave-backwards-compatibility-check.sh"
44 changes: 44 additions & 0 deletions .github/workflows/roave-backwards-compatibility-check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash

set -uo pipefail

cd "$(dirname "$0")/../.." || exit 2

# This file is a hack to suppress warnings from Roave BC check
# Based on: https://github.com/guzzle/guzzle/blob/7a30f3bc91b3ab57860efbe8272649cc23dbbcc2/.github/workflows/bc.entrypoint

echo "Running BC check, please wait..."

# Capture output to variable AND print it
OUTPUT=$(vendor/bin/roave-backward-compatibility-check --format=markdown --install-development-dependencies 2>&1)

# Remove rows we want to suppress
OUTPUT=`echo "$OUTPUT" | sed '/Roave\\\BetterReflection\\\Reflection\\\ReflectionClass "Symfony\\\Component\\\HttpKernel\\\Event\\\FilterControllerEvent" could not be found in the located source/'d`
OUTPUT=`echo "$OUTPUT" | sed '/Roave\\\BetterReflection\\\Reflection\\\ReflectionClass "Scoutapm\\\ScoutApmBundle\\\Twig\\\TwigMethods" could not be found in the located source/'d`

# Number of rows we found with "[BC]" in them
BC_BREAKS=`echo "$OUTPUT" | grep -o '\[BC\]' | wc -l | awk '{ print $1 }'`

# The last row of the output is "X backwards-incompatible changes detected". Find X.
STATED_BREAKS=`echo "$OUTPUT" | tail -n 1 | awk -F' ' '{ print $1 }'`

EXPECTED_STATED_BREAKS=18

echo "$OUTPUT"
echo "Lines with [BC] not filtered: $BC_BREAKS"
echo "Stated breaks: $STATED_BREAKS out of expected $EXPECTED_STATED_BREAKS"

# If
# We found "[BC]" in the command output after we removed suppressed lines
# OR
# We have suppressed X number of BC breaks. If $STATED_BREAKS is larger than X
# THEN
# exit 1
if [ $BC_BREAKS -gt 0 ] || [ $STATED_BREAKS -gt $EXPECTED_STATED_BREAKS ]; then
echo "EXIT 1"
exit 1
fi

# No BC breaks found
echo "EXIT 0"
exit 0
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file, in reverse
### Added

- [#238](https://github.com/scoutapp/scout-apm-php/pull/238) Add scheduled CI run every month to ensure compatibility with dependency updates
- [#240](https://github.com/scoutapp/scout-apm-php/pull/240) Add support for psr/log ^1.0|^2.0|^3.0, and added Roave/BackwardCompatibilityCheck to CI

### Changed

Expand Down
3 changes: 1 addition & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"ext-openssl": "*",
"ext-sockets": "*",
"ext-zlib": "*",
"psr/log": "^1.0",
"psr/log": "^1.0|^2.0|^3.0",
"psr/simple-cache": "^1.0",
"ralouphie/getallheaders": "^2.0.5|^3.0",
"ramsey/uuid": "^3.0|^4.0",
Expand All @@ -26,7 +26,6 @@
"monolog/monolog": "^1.26|^2.2.0",
"phpunit/phpunit": "^7.5.20|^8.5.14|^9.5.2",
"psalm/plugin-phpunit": "^0.15.1",
"psr/log": "^1.1",
"symfony/config": "^4.0 || ^5.0",
"symfony/dependency-injection": "^4.0 || ^5.0",
"symfony/event-dispatcher": "^4.0 || ^5.0",
Expand Down
16 changes: 8 additions & 8 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/Integration/AgentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
use MongoDB\Driver\Manager;
use MongoDB\Driver\Query;
use PHPUnit\Framework\TestCase;
use Psr\Log\Test\TestLogger;
use Scoutapm\Agent;
use Scoutapm\Config;
use Scoutapm\Config\ConfigKey;
use Scoutapm\Connector\ConnectionAddress;
use Scoutapm\Connector\SocketConnector;
use Scoutapm\Events\Span\SpanReference;
use Scoutapm\Extension\PotentiallyAvailableExtensionCapabilities;
use Scoutapm\UnitTests\TestLogger;

use function assert;
use function extension_loaded;
Expand Down
1 change: 0 additions & 1 deletion tests/Unit/AgentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LogLevel;
use Psr\Log\Test\TestLogger;
use Scoutapm\Agent;
use Scoutapm\Cache\DevNullCache;
use Scoutapm\Config;
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/CoreAgent/LauncherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
namespace Scoutapm\UnitTests\CoreAgent;

use PHPUnit\Framework\TestCase;
use Psr\Log\Test\TestLogger;
use Scoutapm\Config;
use Scoutapm\Connector\ConnectionAddress;
use Scoutapm\CoreAgent\Launcher;
use Scoutapm\UnitTests\TestLogger;

/** @covers \Scoutapm\CoreAgent\Launcher */
final class LauncherTest extends TestCase
Expand Down
173 changes: 173 additions & 0 deletions tests/Unit/TestLogger.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<?php

declare(strict_types=1);

namespace Scoutapm\UnitTests;

use BadMethodCallException;
use Psr\Log\AbstractLogger;

use function call_user_func_array;
use function is_string;
use function method_exists;
use function preg_match;
use function strpos;
use function strtolower;

/**
* Used for testing purposes.
*
* It records all records and gives you access to them for verification.
*
* @method bool hasEmergency($record)
* @method bool hasAlert($record)
* @method bool hasCritical($record)
* @method bool hasError($record)
* @method bool hasWarning($record)
* @method bool hasNotice($record)
* @method bool hasInfo($record)
* @method bool hasDebug($record)
* @method bool hasEmergencyRecords()
* @method bool hasAlertRecords()
* @method bool hasCriticalRecords()
* @method bool hasErrorRecords()
* @method bool hasWarningRecords()
* @method bool hasNoticeRecords()
* @method bool hasInfoRecords()
* @method bool hasDebugRecords()
* @method bool hasEmergencyThatContains($message)
* @method bool hasAlertThatContains($message)
* @method bool hasCriticalThatContains($message)
* @method bool hasErrorThatContains($message)
* @method bool hasWarningThatContains($message)
* @method bool hasNoticeThatContains($message)
* @method bool hasInfoThatContains($message)
* @method bool hasDebugThatContains($message)
* @method bool hasEmergencyThatMatches($message)
* @method bool hasAlertThatMatches($message)
* @method bool hasCriticalThatMatches($message)
* @method bool hasErrorThatMatches($message)
* @method bool hasWarningThatMatches($message)
* @method bool hasNoticeThatMatches($message)
* @method bool hasInfoThatMatches($message)
* @method bool hasDebugThatMatches($message)
* @method bool hasEmergencyThatPasses($message)
* @method bool hasAlertThatPasses($message)
* @method bool hasCriticalThatPasses($message)
* @method bool hasErrorThatPasses($message)
* @method bool hasWarningThatPasses($message)
* @method bool hasNoticeThatPasses($message)
* @method bool hasInfoThatPasses($message)
* @method bool hasDebugThatPasses($message)
* @psalm-type LogRecord = array{level: string, message: string, context: array}
*/
class TestLogger extends AbstractLogger
{
/** @psalm-var list<LogRecord> */
public $records = [];

/** @psalm-var array<string,list<LogRecord>> */
public $recordsByLevel = [];

/**
* @inheritdoc
*/
public function log($level, $message, array $context = [])
{
$record = [
'level' => (string) $level,
'message' => $message,
'context' => $context,
];

$this->recordsByLevel[$record['level']][] = $record;
$this->records[] = $record;
}

public function hasRecords(string $level): bool
{
return isset($this->recordsByLevel[$level]);
}

/**
* @param string|array{message:string, context?: mixed} $record
*/
public function hasRecord($record, string $level): bool
{
if (is_string($record)) {
$record = ['message' => $record];
}

return $this->hasRecordThatPasses(
/** @psalm-param LogRecord $rec */
static function ($rec) use ($record): bool {
if ($rec['message'] !== $record['message']) {
return false;
}

return ! isset($record['context']) || $rec['context'] === $record['context'];
},
$level
);
}

public function hasRecordThatContains(string $message, string $level): bool
{
return $this->hasRecordThatPasses(
/** @psalm-param LogRecord $rec */
static function ($rec) use ($message): bool {
return strpos($rec['message'], $message) !== false;
},
$level
);
}

public function hasRecordThatMatches(string $regex, string $level): bool
{
return $this->hasRecordThatPasses(
/** @psalm-param LogRecord $rec */
static function ($rec) use ($regex): bool {
return preg_match($regex, $rec['message']) > 0;
},
$level
);
}

/** @psalm-param callable(LogRecord):bool $predicate */
public function hasRecordThatPasses(callable $predicate, string $level): bool
{
if (! isset($this->recordsByLevel[$level])) {
return false;
}

foreach ($this->recordsByLevel[$level] as $rec) {
if ($predicate($rec)) {
return true;
}
}

return false;
}

/** @param array<array-key, mixed> $args */
public function __call(string $method, array $args): bool
{
if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
$genericMethod = $matches[1] . ($matches[3] !== 'Records' ? 'Record' : '') . $matches[3];
$level = strtolower($matches[2]);
if (method_exists($this, $genericMethod)) {
$args[] = $level;

return (bool) call_user_func_array([$this, $genericMethod], $args);
}
}

throw new BadMethodCallException('Call to undefined method ' . static::class . '::' . $method . '()');
}

public function reset(): void
{
$this->records = [];
$this->recordsByLevel = [];
}
}
2 changes: 1 addition & 1 deletion tests/isolated-memory-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

declare(strict_types=1);

use Psr\Log\Test\TestLogger;
use Scoutapm\Agent;
use Scoutapm\Config;
use Scoutapm\Events\Span\SpanReference;
use Scoutapm\Extension\PotentiallyAvailableExtensionCapabilities;
use Scoutapm\UnitTests\TestLogger;

require __DIR__ . '/../vendor/autoload.php';

Expand Down