Skip to content

GH Actions: split PHAR build test from other tests #3442

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

Merged
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
66 changes: 60 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,60 @@ on:
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
php: ['5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2']

name: "Build Phar on PHP: ${{ matrix.php }}"

continue-on-error: ${{ matrix.php == '8.2' }}

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
ini-values: phar.readonly=Off, error_reporting=-1, display_errors=On

- name: Build the phar
run: php scripts/build-phar.php

- name: Upload the PHPCS phar
uses: actions/upload-artifact@v2
if: ${{ success() && matrix.php == '8.0' }}
with:
name: phpcs-phar
path: ./phpcs.phar
if-no-files-found: error
retention-days: 28

- name: Upload the PHPCBF phar
uses: actions/upload-artifact@v2
if: ${{ success() && matrix.php == '8.0' }}
with:
name: phpcbf-phar
path: ./phpcbf.phar
if-no-files-found: error
retention-days: 28

# Both the below only check a few files which are rarely changed and therefore unlikely to have issues.
# This test is about testing that the phars are functional, *not* about whether the code style complies.
- name: 'PHPCS: check code style using the Phar file to test the Phar is functional'
run: php phpcs.phar ./scripts

- name: 'PHPCBF: fix code style using the Phar file to test the Phar is functional'
run: php phpcbf.phar ./scripts

test:
runs-on: ubuntu-latest
needs: build

strategy:
# Keys:
Expand Down Expand Up @@ -45,11 +97,11 @@ jobs:
# Set the "short_open_tag" ini to make sure specific conditions are tested.
# Also turn on error_reporting to ensure all notices are shown.
if [[ ${{ matrix.custom_ini }} == true && "${{ matrix.php }}" == '5.5' ]]; then
echo '::set-output name=PHP_INI::phar.readonly=Off, error_reporting=-1, display_errors=On, date.timezone=Australia/Sydney, short_open_tag=On, asp_tags=On'
echo '::set-output name=PHP_INI::error_reporting=-1, display_errors=On, date.timezone=Australia/Sydney, short_open_tag=On, asp_tags=On'
elif [[ ${{ matrix.custom_ini }} == true && "${{ matrix.php }}" == '7.0' ]]; then
echo '::set-output name=PHP_INI::phar.readonly=Off, error_reporting=-1, display_errors=On, date.timezone=Australia/Sydney, short_open_tag=On'
echo '::set-output name=PHP_INI::error_reporting=-1, display_errors=On, date.timezone=Australia/Sydney, short_open_tag=On'
else
echo '::set-output name=PHP_INI::phar.readonly=Off, error_reporting=-1, display_errors=On'
echo '::set-output name=PHP_INI::error_reporting=-1, display_errors=On'
fi

- name: Install PHP
Expand Down Expand Up @@ -106,10 +158,12 @@ jobs:
if: ${{ matrix.custom_ini == false }}
run: composer validate --no-check-all --strict

- name: Build the phar
if: ${{ matrix.custom_ini == false }}
run: php scripts/build-phar.php
- name: Download the PHPCS phar
uses: actions/download-artifact@v2
with:
name: phpcs-phar

# This test specifically tests that the Phar which will be released works correctly on all PHP versions.
- name: 'PHPCS: check code style using the Phar file'
if: ${{ matrix.custom_ini == false }}
run: php phpcs.phar
93 changes: 89 additions & 4 deletions scripts/build-phar.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,73 @@
* @link http://pear.php.net/package/PHP_CodeSniffer
*/

use PHP_CodeSniffer\Config;
use PHP_CodeSniffer\Exceptions\RuntimeException;
use PHP_CodeSniffer\Exceptions\TokenizerException;
use PHP_CodeSniffer\Tokenizers\PHP;
use PHP_CodeSniffer\Util\Tokens;

error_reporting(E_ALL | E_STRICT);

if (ini_get('phar.readonly') === '1') {
echo 'Unable to build, phar.readonly in php.ini is set to read only.'.PHP_EOL;
exit(1);
}

require_once dirname(__DIR__).'/autoload.php';
require_once dirname(__DIR__).'/src/Util/Tokens.php';

if (defined('PHP_CODESNIFFER_VERBOSITY') === false) {
define('PHP_CODESNIFFER_VERBOSITY', 0);
}


/**
* Replacement for the PHP native php_strip_whitespace() function,
* which doesn't handle attributes correctly for cross-version PHP.
*
* @param string $fullpath Path to file.
* @param \PHP_CodeSniffer\Config $config Perfunctory Config.
*
* @return string
*
* @throws \PHP_CodeSniffer\Exceptions\RuntimeException When tokenizer errors are encountered.
*/
function stripWhitespaceAndComments($fullpath, $config)
{
$contents = file_get_contents($fullpath);

try {
$tokenizer = new PHP($contents, $config, "\n");
$tokens = $tokenizer->getTokens();
} catch (TokenizerException $e) {
throw new RuntimeException('Failed to tokenize file '.$fullpath);
}

$stripped = '';
foreach ($tokens as $token) {
if ($token['code'] === T_ATTRIBUTE_END || $token['code'] === T_OPEN_TAG) {
$stripped .= $token['content']."\n";
continue;
}

if (isset(Tokens::$emptyTokens[$token['code']]) === false) {
$stripped .= $token['content'];
continue;
}

if ($token['code'] === T_WHITESPACE) {
$stripped .= ' ';
}
}

return $stripped;

}//end stripWhitespaceAndComments()


$startTime = microtime(true);

$scripts = [
'phpcs',
'phpcbf',
Expand Down Expand Up @@ -51,6 +111,9 @@
$rdi = new \RecursiveDirectoryIterator($srcDir, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
$di = new \RecursiveIteratorIterator($rdi, 0, \RecursiveIteratorIterator::CATCH_GET_CHILD);

$config = new Config();
$fileCount = 0;

foreach ($di as $file) {
$filename = $file->getFilename();

Expand All @@ -60,21 +123,30 @@
}

$fullpath = $file->getPathname();
if (strpos($fullpath, '/Tests/') !== false) {
if (strpos($fullpath, DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR) !== false) {
continue;
}

$path = 'src'.substr($fullpath, $srcDirLen);
$phar->addFile($fullpath, $path);
}

if (substr($filename, -4) === '.xml') {
$phar->addFile($fullpath, $path);
} else {
// PHP file.
$phar->addFromString($path, stripWhitespaceAndComments($fullpath, $config));
}

++$fileCount;
}//end foreach

// Add autoloader.
$phar->addFile(realpath(__DIR__.'/../autoload.php'), 'autoload.php');
$phar->addFromString('autoload.php', stripWhitespaceAndComments(realpath(__DIR__.'/../autoload.php'), $config));

// Add licence file.
$phar->addFile(realpath(__DIR__.'/../licence.txt'), 'licence.txt');

echo 'done'.PHP_EOL;
echo "\t Added ".$fileCount.' files'.PHP_EOL;

/*
Add the stub.
Expand All @@ -93,3 +165,16 @@

echo 'done'.PHP_EOL;
}//end foreach

$timeTaken = ((microtime(true) - $startTime) * 1000);
if ($timeTaken < 1000) {
$timeTaken = round($timeTaken);
echo "DONE in {$timeTaken}ms".PHP_EOL;
} else {
$timeTaken = round(($timeTaken / 1000), 2);
echo "DONE in $timeTaken secs".PHP_EOL;
}

echo PHP_EOL;
echo 'Filesize generated phpcs.phar file: '.filesize(dirname(__DIR__).'/phpcs.phar').' bytes'.PHP_EOL;
echo 'Filesize generated phpcs.phar file: '.filesize(dirname(__DIR__).'/phpcbf.phar').' bytes'.PHP_EOL;