Skip to content

Commit

Permalink
Add PHP8 support (#321)
Browse files Browse the repository at this point in the history
  • Loading branch information
PabloKowalczyk authored Oct 8, 2020
1 parent fc3dc08 commit 9a3e29c
Show file tree
Hide file tree
Showing 18 changed files with 184 additions and 49 deletions.
17 changes: 10 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,23 @@ php:
- 7.2
- 7.3
- 7.4
- nightly

env:
matrix:
- SYMFONY_VERSION="^v3.4.5" PHPUNIT_BRIDGE_VERSION="^v3.4.31" DEPENDENCIES="high"
- SYMFONY_VERSION="^v3.4.5" PHPUNIT_BRIDGE_VERSION="^v3.4.31" DEPENDENCIES="low"
- SYMFONY_VERSION="^v3.4.5" PHPUNIT_BRIDGE_VERSION="^v3.4.40" DEPENDENCIES="high"
- SYMFONY_VERSION="^v3.4.5" PHPUNIT_BRIDGE_VERSION="^v3.4.40" DEPENDENCIES="low"
- SYMFONY_VERSION="~v4.3.0" DEPENDENCIES="high"
- SYMFONY_VERSION="~v4.3.0" DEPENDENCIES="low"
- SYMFONY_VERSION="~v4.4.0" DEPENDENCIES="high"
- SYMFONY_VERSION="~v4.4.0" DEPENDENCIES="low"
- SYMFONY_VERSION="~v5.0.0" PHPUNIT_BRIDGE_VERSION="~v5.0.0" DEPENDENCIES="high"
- SYMFONY_VERSION="~v5.0.0" PHPUNIT_BRIDGE_VERSION="~v5.0.0" DEPENDENCIES="low"
- SYMFONY_VERSION="~v5.0.0" PHPUNIT_BRIDGE_VERSION="~v5.0.8" DEPENDENCIES="high"
- SYMFONY_VERSION="~v5.0.0" PHPUNIT_BRIDGE_VERSION="~v5.0.8" DEPENDENCIES="low"
- SYMFONY_VERSION="~v5.1.0" DEPENDENCIES="high"
- SYMFONY_VERSION="~v5.1.0" DEPENDENCIES="low"
global:
- DEFAULT_COMPOSER_FLAGS="--no-interaction --no-progress --prefer-dist"
- PHPUNIT_BRIDGE_VERSION="~v4.4.0"
- PHPUNIT_BRIDGE_VERSION="~v4.4.8"

jobs:
fast_finish: true
Expand All @@ -44,6 +45,9 @@ before_install:
- composer self-update --2 --preview

install:
- if [[ "$TRAVIS_PHP_VERSION" = 'nightly' ]]; then
composer config platform.php 7.4.99;
fi
- php ./composer-install.php "$SYMFONY_VERSION" "$DEPENDENCIES" "$DEFAULT_COMPOSER_FLAGS" "$PHPUNIT_BRIDGE_VERSION"
- composer show
- if [[ "$STATIC_CHECKS" = '1' ]]; then
Expand All @@ -53,7 +57,6 @@ install:

script:
- if [[ "$STATIC_CHECKS" = '1' ]]; then
composer crunz:analyze;
composer phpstan:check;
composer crunz:analyze && composer phpstan:check;
fi
- vendor/bin/phpunit
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,27 @@ To install it:
```bash
composer require lavary/crunz
```
If the installation is successful, a command-line utility named **crunz** is symlinked to the `vendor/bin` directory of your project.
If the installation is successful, a command-line utility named **crunz** is symlinked to the `vendor/bin` directory of your project.

## PHP 8 issues/limitations

### Trick Composer to allow installation

While Crunz itself is compatible with PHP 8, not all dependencies are, so Composer must be tricked to allow installation

```shell script
composer config platform.php 7.4.99
```

### Do not use primitive return types for Closures

Package https://github.com/opis/closure do not support
PHP 8 on `v3` branch and closures with primitive return types
resolves to root namespace which throws exception on deserialization.

### Still doesn't work

Please add new bug at https://github.com/lavary/crunz/issues/new/choose

## How It Works?

Expand Down
26 changes: 14 additions & 12 deletions composer-install.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@
$defaultComposerFlags = $_SERVER['argv'][3] ?? '';
$phpunitBridgeVersion = $_SERVER['argv'][4] ?? $version;
$composerFilePath = __DIR__ . DIRECTORY_SEPARATOR . 'composer.json';
$ignoredPackages = [
'symfony/error-handler',
'symfony/phpunit-bridge',
];
$ignoredPackages = ['symfony/error-handler'];
$changeVersion = static function (
array $packages
) use (
Expand All @@ -32,6 +29,12 @@
continue;
}

if (PHP_MAJOR_VERSION >= 8 && 'phpunit/phpunit' === $packageName) {
$packageVersion = '^9.4.0';

continue;
}

if (false === \mb_strpos($packageName, 'symfony/')) {
continue;
}
Expand Down Expand Up @@ -59,15 +62,14 @@

\file_put_contents(
$composerFilePath,
\json_encode($composerJson)
\json_encode($composerJson, JSON_PRETTY_PRINT)
);

$command = "composer install -o {$defaultComposerFlags}";
echo $command, PHP_EOL;
echo \shell_exec($command);

$preferLowest = '';
if ('high' !== $dependenciesEnv) {
$updateCommand = "composer update -o --prefer-lowest {$defaultComposerFlags}";
echo $updateCommand, PHP_EOL;
echo \shell_exec($updateCommand);
$preferLowest = '--prefer-lowest';
}

$command = \trim("composer update -o {$defaultComposerFlags} {$preferLowest}");
echo $command, PHP_EOL;
echo \shell_exec($command);
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"issues": "http://github.com/lavary/crunz/issues"
},
"require": {
"php": "^7.2",
"php": ">=7.2",
"dragonmantank/cron-expression": "^2.0",
"opis/closure": "^3.5",
"swiftmailer/swiftmailer": "^6.0",
Expand All @@ -43,7 +43,7 @@
"bamarni/composer-bin-plugin": "^1.2",
"phpunit/phpunit": "^8.5.1",
"symfony/error-handler": "^4.4 || ^5.0",
"symfony/phpunit-bridge": "^3.4.31 || ^4.3 || ^5.0"
"symfony/phpunit-bridge": "^3.4.40 || ^4.4.8 || ^5.0.8"
},
"autoload": {
"psr-4": {
Expand Down
17 changes: 17 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,20 @@ services:
volumes:
- .:/var/www/html
- ./docker/php72/php.ini:/usr/local/etc/php/php.ini:ro

php80:
build:
context: ./docker/php80
working_dir: /var/www/html
environment:
CRUNZ_CONTAINER_DEBUG: 1
command: >
sh -c "
chown -R www-data:www-data /var/www/.composer \
&& echo 'Logs from /var/log/php/error.log:' \
&& touch /var/log/php/error.log \
&& tail -f /var/log/php/error.log
"
volumes:
- .:/var/www/html
- ./docker/php80/php.ini:/usr/local/etc/php/php.ini:ro
22 changes: 22 additions & 0 deletions docker/php80/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM php:8.0.0rc1-cli-alpine

RUN apk add --no-cache \
shadow \
su-exec && \
usermod --non-unique --uid 1000 www-data && \
apk del \
shadow && \
docker-php-ext-install -j$(nproc) \
opcache \
sysvsem

RUN mkdir -p \
/var/log/php \
/var/www/.composer \
&& touch /var/log/php/error.log \
&& chown www-data:www-data \
/var/log/php/error.log \
/var/www/.composer

COPY --from=composer:2.0.0-RC1 /usr/bin/composer /usr/bin/composer
ENV COMPOSER_HOME /var/www/.composer
27 changes: 27 additions & 0 deletions docker/php80/php.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
realpath_cache_size = 8192k
realpath_cache_ttl = 6000

expose_php = On
error_log = /var/log/php/error.log
error_reporting = E_ALL
display_errors = On
display_startup_errors = On
log_errors = On
report_memleaks = On

memory_limit = 80M

date.timezone = "UTC"

zend.assertions = 1

opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=80
opcache.interned_strings_buffer=5
opcache.max_accelerated_files=3000
opcache.validate_timestamps=1
opcache.revalidate_freq=0
opcache.save_comments=1
opcache.fast_shutdown=1
opcache.huge_code_pages=1
5 changes: 4 additions & 1 deletion tests/EndToEnd/DebugTaskTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ public function test_task_debug(): void
for ($i = 1; $i <= 5; ++$i) {
$key = "_{$i}";
$this->assertArrayHasKey($key, $contentLines);
$this->assertRegExp('/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:00 UTC$/', $contentLines[$key]);
$this->assertMatchesRegularExpression(
'/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:00 UTC$/',
$contentLines[$key]
);
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/EndToEnd/LoggerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private function assertLogRecord(
): void {
$levelFormatted = \mb_strtoupper($level);

$this->assertRegExp(
$this->assertMatchesRegularExpression(
"/^\[[0-9]{4}(-[0-9]{2}){2} [0-9]{2}(:[0-9]{2}){2}\] crunz\.{$levelFormatted}:.+?({$message})/",
$logRecord
);
Expand Down
2 changes: 1 addition & 1 deletion tests/EndToEnd/WrongTaskTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function everyTaskMustReturnCrunzScheduleInstance(string $crunzCommand):
$normalizedOutput = $this->normalizeProcessErrorOutput($process);

$this->assertFalse($process->isSuccessful());
$this->assertRegExp(
$this->assertMatchesRegularExpression(
"@Task at path '.*WrongTasks\\.php' returned 'array', but 'C( ?)runz\\\\Schedule' instance is required\.@",
$normalizedOutput
);
Expand Down
35 changes: 19 additions & 16 deletions tests/TestCase/EndToEnd/Environment/Environment.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,30 +188,33 @@ private function dumpComposerJson(): void

$projectDir = $this->filesystem
->projectRootDirectory();
$content = \json_encode(
[
'repositories' => [
[
'type' => 'path',
'url' => $projectDir,
'options' => [
'symlink' => false,
],
$content = [
'repositories' => [
[
'type' => 'path',
'url' => $projectDir,
'options' => [
'symlink' => false,
],
],
'require' => [
'lavary/crunz' => '*@dev',
],
],
JSON_PRETTY_PRINT
);
'require' => [
'lavary/crunz' => '*@dev',
],
];

if (PHP_MAJOR_VERSION >= 8) {
$content['config']['platform']['php'] = '7.4.99';
}

if (false === $content) {
$contentJson = \json_encode($content, JSON_PRETTY_PRINT);
if (false === $contentJson) {
throw new \RuntimeException("Unable to encode 'composer.json' content.");
}

$this->filesystem
->dumpFile($composerJson->toString(), $content);
->dumpFile($composerJson->toString(), $contentJson)
;
}

private function composerInstall(): void
Expand Down
2 changes: 2 additions & 0 deletions tests/TestCase/EndToEndTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

abstract class EndToEndTestCase extends TestCase
{
use PolyfillAssertTrait;

/** @var FilesystemInterface */
private $filesystem;

Expand Down
25 changes: 25 additions & 0 deletions tests/TestCase/PolyfillAssertTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Crunz\Tests\TestCase;

use PHPUnit\Framework\Constraint\DirectoryExists;
use PHPUnit\Framework\Constraint\LogicalNot;
use PHPUnit\Framework\Constraint\RegularExpression;

trait PolyfillAssertTrait
{
public static function assertMatchesRegularExpression(
string $pattern,
string $string,
string $message = ''
): void {
static::assertThat($string, new RegularExpression($pattern), $message);
}

public static function assertDirectoryDoesNotExist(string $directory, string $message = ''): void
{
static::assertThat($directory, new LogicalNot(new DirectoryExists()), $message);
}
}
2 changes: 2 additions & 0 deletions tests/TestCase/UnitTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

abstract class UnitTestCase extends TestCase
{
use PolyfillAssertTrait;

/** @var ClosureSerializerInterface|null */
private $closureSerializer = null;

Expand Down
6 changes: 3 additions & 3 deletions tests/Unit/Filesystem/FilesystemTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
use Crunz\Filesystem\Filesystem;
use Crunz\Path\Path;
use Crunz\Tests\TestCase\TemporaryFile;
use PHPUnit\Framework\TestCase;
use Crunz\Tests\TestCase\UnitTestCase;

final class FilesystemTest extends TestCase
final class FilesystemTest extends UnitTestCase
{
/** @test */
public function cwdIsCorrect(): void
Expand Down Expand Up @@ -57,7 +57,7 @@ public function removeDirectoryRemovesDirectoriesRecursively(): void

$filesystem->removeDirectory($rootPath->toString());

$this->assertDirectoryNotExists($rootPath->toString());
$this->assertDirectoryDoesNotExist($rootPath->toString());
}

/** @test */
Expand Down
13 changes: 10 additions & 3 deletions tests/Unit/HttpClient/StreamHttpClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,17 @@ final class StreamHttpClientTest extends TestCase
/** @test */
public function pingFailWithInvalidAddress(): void
{
$expectedExceptionMessage = 'Ping failed with message: "fopen(http://www.wrong-address.tld): failed to open stream: php_network_getaddresses: getaddrinfo failed:';
if (PHP_MAJOR_VERSION >= 8) {
$expectedExceptionMessage = \str_replace(
'failed to open',
'Failed to open',
$expectedExceptionMessage
);
}

$this->expectException(HttpClientException::class);
$this->expectExceptionMessage(
'Ping failed with message: "fopen(http://www.wrong-address.tld): failed to open stream: php_network_getaddresses: getaddrinfo failed:'
);
$this->expectExceptionMessage($expectedExceptionMessage);

$client = new StreamHttpClient();
$client->ping('http://www.wrong-address.tld');
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/UserInterface/Cli/ClosureRunCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ final class ClosureRunCommandTest extends UnitTestCase
/** @dataProvider closureValueProvider */
public function testReturnValueOfClosureIsOmitted(int $returnValue): void
{
$closure = static function () use ($returnValue): int {
$closure = static function () use ($returnValue) {
return $returnValue;
};
$command = $this->createCommand();
Expand Down
Loading

0 comments on commit 9a3e29c

Please sign in to comment.