Skip to content

Commit

Permalink
Ship a constraint checker to the built PHARs (#116)
Browse files Browse the repository at this point in the history
This feature is about adding a check in the PHAR stub in order to gracefully fail with a human friendly error when the user is using the PHAR in a non-supported environment, e.g. invalid PHP version or missing extension. The goal is to gather those requirements without requiring any configuration from the user.
  • Loading branch information
theofidry authored Apr 22, 2018
1 parent 8d22c82 commit 58e173f
Show file tree
Hide file tree
Showing 63 changed files with 5,200 additions and 51 deletions.
16 changes: 16 additions & 0 deletions .docker/build
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env bash

set -euf -o pipefail

readonly DOCKER=$(which docker)

# Globals
# PWD

if [[ "$(docker images -q box_php53 2> /dev/null)" == "" ]]; then
$DOCKER build -t box_php53 -f "$PWD/.docker/php53" .
fi

if [[ "$(docker images -q box_php72 2> /dev/null)" == "" ]]; then
$DOCKER build -t box_php72 -f "$PWD/.docker/php72" .
fi
4 changes: 4 additions & 0 deletions .docker/php53
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM helder/php-5.3

RUN pecl install phar
RUN pecl install json
1 change: 1 addition & 0 deletions .docker/php72
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FROM php:7.2-cli
1 change: 0 additions & 1 deletion .gitattributes

This file was deleted.

13 changes: 12 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,23 @@
/*.phar.sig
/box.json
/bin/
!/bin/generate_default_stub
!/bin/box
!/bin/box.bat
!/bin/generate_default_stub
!/bin/dump-requirements-checker.php
/dist/
/fixtures/default_stub.php
/fixtures/build/dir010/*.phar
/fixtures/check-requirements/*/actual-output
/fixtures/check-requirements/*/*.phar
/.requirement-checker/
/requirement-checker/bin/*
!/requirement-checker/bin/check-requirments.php
/requirement-checker/actual_terminal_diff
/requirement-checker/.box/
/requirement-checker/tests/DisplayNormalizer.php
/requirement-checker/vendor/
/src/.requirement-checker/
/vendor/
/vendor-bin/*/composer.lock
/vendor-bin/*/vendor/
Expand Down
3 changes: 2 additions & 1 deletion .php_cs.dist
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ $config = PhpCsFixer\Config::create()
->in('tests')
->append(['bin/box'])
->notName('default_stub.php')
->exclude('check-requirements')
)
;

Expand All @@ -84,4 +85,4 @@ PhpCsFixer\FixerFactory::create()
->useRuleSet(new PhpCsFixer\RuleSet($config->getRules()))
;

return $config;
return $config;
81 changes: 81 additions & 0 deletions .php_cs_53.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php declare(strict_types=1);

$header = <<<'EOF'
This file is part of the box project.

(c) Kevin Herrera <kevin@herrera.io>
Théo Fidry <theo.fidry@gmail.com>

This source file is subject to the MIT license that is bundled
with this source code in the file LICENSE.
EOF;

$config = PhpCsFixer\Config::create()
->setRiskyAllowed(true)
->setRules([
'@Symfony' => true,
'@Symfony:risky' => true,
'align_multiline_comment' => true,
'array_syntax' => ['syntax' => 'long'],
'blank_line_before_statement' => [
'statements' => [
'continue',
'declare',
'return',
'throw',
'try',
],
],
'combine_consecutive_issets' => true,
'combine_consecutive_unsets' => true,
'compact_nullable_typehint' => true,
'header_comment' => ['header' => $header],
'heredoc_to_nowdoc' => true,
'list_syntax' => ['syntax' => 'long'],
'method_argument_space' => ['ensure_fully_multiline' => true],
'no_extra_consecutive_blank_lines' => [
'tokens' => [
'break',
'continue',
'extra',
'return',
'throw',
'use',
'parenthesis_brace_block',
'square_brace_block',
'curly_brace_block'
]
],
'no_null_property_initialization' => true,
'no_short_echo_tag' => true,
'no_superfluous_elseif' => true,
'no_unneeded_curly_braces' => true,
'no_unneeded_final_method' => true,
'no_unreachable_default_argument_value' => true,
'no_useless_else' => true,
'no_useless_return' => true,
'no_unused_imports' => true,
'ordered_imports' => true,
'php_unit_test_class_requires_covers' => true,
'phpdoc_add_missing_param_annotation' => true,
'phpdoc_order' => true,
'phpdoc_types_order' => true,
'semicolon_after_instruction' => true,
'single_line_comment_style' => true,
'strict_param' => true,
'yoda_style' => true,
])
->setFinder(
PhpCsFixer\Finder::create()
->in('requirement-checker/src')
->append(['requirement-checker/bin/check-requirements.php'])
)
;

PhpCsFixer\FixerFactory::create()
->registerBuiltInFixers()
->registerCustomFixers($config->getCustomFixers())
->useRuleSet(new PhpCsFixer\RuleSet($config->getRules()))
;

return $config;
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ language: php

sudo: false

services:
- docker

branches:
only:
- master
Expand Down
109 changes: 89 additions & 20 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,58 +21,105 @@ PHPCSFIXER=vendor-bin/php-cs-fixer/vendor/bin/php-cs-fixer
cs: ## Fix CS
cs: vendor-bin/php-cs-fixer/vendor/bin/php-cs-fixer
$(PHPNOGC) $(PHPCSFIXER) fix
$(PHPNOGC) $(PHPCSFIXER) fix --config .php_cs_53.dist

.PHONY: compile
compile: ## Compile the application into the PHAR
compile:
# Cleanup existing artefacts
rm -f bin/box.phar

# Build the PHAR
php bin/box compile $(args)
compile: box.phar
cp -f box.phar bin/box.phar


##
## Tests
##---------------------------------------------------------------------------

.PHONY: test
test: ## Run all the tests
test: ## Run all the tests
test: tu e2e

.PHONY: tu
tu: ## Run the unit tests
tu: bin/phpunit fixtures/default_stub.php
tu: ## Run the unit tests
tu: tu_requirement_checker tu_box

.PHONY: tu_box
tu_box: ## Run the unit tests
tu_box: bin/phpunit fixtures/default_stub.php .requirement-checker
$(PHPNOGC) bin/phpunit

.PHONY: tu_requirement_checker
tu_requirement_checker: ## Run the unit tests
tu_requirement_checker: requirement-checker/bin/phpunit requirement-checker/tests/DisplayNormalizer.php requirement-checker/actual_terminal_diff
cd requirement-checker && $(PHPNOGC) bin/phpunit

diff requirement-checker/expected_terminal_diff requirement-checker/actual_terminal_diff

.PHONY: tc
tc: ## Run the unit tests with code coverage
tc: ## Run the unit tests with code coverage
tc: bin/phpunit
phpdbg -qrr -d zend.enable_gc=0 bin/phpunit --coverage-html=dist/coverage --coverage-text

.PHONY: tm
tm: ## Run Infection
tm: bin/phpunit fixtures/default_stub.php
tm: ## Run Infection
tm: bin/phpunit fixtures/default_stub.php .requirement-checker requirement-checker/actual_terminal_diff
$(PHPNOGC) bin/infection

.PHONY: e2e
e2e: ## Run the end-to-end tests
e2e: e2e_scoper_alias
e2e: ## Runs all the end-to-end tests
e2e: e2e_scoper_alias e2e_check_requirements

.PHONY: e2e_scoper_alias
e2e_scoper_alias: ## Runs the end-to-end tests to check that the PHP-Scoper config API is working
e2e_scoper_alias: ## Runs the end-to-end tests to check that the PHP-Scoper config API is working
e2e_scoper_alias: box.phar
php box.phar compile --working-dir fixtures/build/dir010


.PHONY: e2e_check_requirements
DOCKER=docker run -i --rm -w /opt/box
PHP7PHAR=box_php72 php index.phar -vvv --no-ansi
PHP5PHAR=box_php53 php index.phar -vvv --no-ansi
e2e_check_requirements: ## Runs the end-to-end tests for the check requirements feature
e2e_check_requirements: box.phar
.docker/build

bin/box compile --working-dir fixtures/check-requirements/pass-no-config/

rm fixtures/check-requirements/pass-no-config/actual-output || true
$(DOCKER) -v "$$PWD/fixtures/check-requirements/pass-no-config":/opt/box $(PHP5PHAR) > fixtures/check-requirements/pass-no-config/actual-output
diff fixtures/check-requirements/pass-no-config/expected-output-53 fixtures/check-requirements/pass-no-config/actual-output

rm fixtures/check-requirements/pass-no-config/actual-output || true
$(DOCKER) -v "$$PWD/fixtures/check-requirements/pass-no-config":/opt/box $(PHP7PHAR) > fixtures/check-requirements/pass-no-config/actual-output
diff fixtures/check-requirements/pass-no-config/expected-output-72 fixtures/check-requirements/pass-no-config/actual-output

bin/box compile --working-dir fixtures/check-requirements/pass-complete/

rm fixtures/check-requirements/pass-complete/actual-output || true
$(DOCKER) -v "$$PWD/fixtures/check-requirements/pass-complete":/opt/box $(PHP5PHAR) > fixtures/check-requirements/pass-complete/actual-output
diff fixtures/check-requirements/pass-complete/expected-output-53 fixtures/check-requirements/pass-complete/actual-output

rm fixtures/check-requirements/pass-complete/actual-output || true
$(DOCKER) -v "$$PWD/fixtures/check-requirements/pass-complete":/opt/box $(PHP7PHAR) > fixtures/check-requirements/pass-complete/actual-output
diff fixtures/check-requirements/pass-complete/expected-output-72 fixtures/check-requirements/pass-complete/actual-output

bin/box compile --working-dir fixtures/check-requirements/fail-complete/

rm fixtures/check-requirements/fail-complete/actual-output || true
$(DOCKER) -v "$$PWD/fixtures/check-requirements/fail-complete":/opt/box $(PHP5PHAR) > fixtures/check-requirements/fail-complete/actual-output || true
diff fixtures/check-requirements/fail-complete/expected-output-53 fixtures/check-requirements/fail-complete/actual-output

rm fixtures/check-requirements/fail-complete/actual-output || true
$(DOCKER) -v "$$PWD/fixtures/check-requirements/fail-complete":/opt/box $(PHP7PHAR) > fixtures/check-requirements/fail-complete/actual-output || true
diff fixtures/check-requirements/fail-complete/expected-output-72 fixtures/check-requirements/fail-complete/actual-output


.PHONY: blackfire
blackfire: ## Profiles the compile step
blackfire: ## Profiles the compile step
blackfire: box.phar
# Profile compiling the PHAR from the source code
blackfire --reference=1 --samples=5 run $(PHPNOGC) bin/box compile --quiet
blackfire --reference=1 --samples=5 run $(PHPNOGC) -d bin/box compile --quiet

# Profile compiling the PHAR from the PHAR
mv -fv bin/box.phar .
blackfire --reference=2 --samples=5 run $(PHPNOGC) box.phar compile --quiet
blackfire --reference=2 --samples=5 run $(PHPNOGC) -d box.phar compile --quiet


#
Expand All @@ -82,6 +129,9 @@ blackfire: box.phar
composer.lock: composer.json
composer install

requirement-checker/composer.lock: requirement-checker/composer.json
composer install --working-dir requirement-checker

vendor: composer.lock
composer install

Expand All @@ -91,6 +141,12 @@ vendor/bamarni: composer.lock
bin/phpunit: composer.lock
composer install

requirement-checker/bin/phpunit: requirement-checker/composer.lock
composer install --working-dir requirement-checker

requirement-checker/vendor:
composer install --working-dir requirement-checker

vendor-bin/php-cs-fixer/vendor/bin/php-cs-fixer: vendor/bamarni
composer bin php-cs-fixer install

Expand All @@ -101,7 +157,20 @@ bin/box.phar: bin/box src vendor
fixtures/default_stub.php:
bin/generate_default_stub

box.phar: bin src res vendor box.json.dist scoper.inc.php
requirement-checker/tests/DisplayNormalizer.php: tests/Console/DisplayNormalizer.php
cat tests/Console/DisplayNormalizer.php | sed -E 's/namespace KevinGH\\Box\\Console;/namespace KevinGH\\RequirementChecker;/g' > requirement-checker/tests/DisplayNormalizer.php

.requirement-checker: requirement-checker requirement-checker/vendor
bin/box compile --working-dir requirement-checker

php bin/dump-requirements-checker.php

requirement-checker/actual_terminal_diff: requirement-checker/src/Terminal.php vendor/symfony/console/Terminal.php
diff vendor/symfony/console/Terminal.php requirement-checker/src/Terminal.php > requirement-checker/actual_terminal_diff || true

vendor/symfony/console/Terminal.php: vendor

box.phar: bin src res vendor box.json.dist scoper.inc.php .requirement-checker
# Compile Box
bin/box compile

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ great things:
1. [Main](doc/configuration.md#main-main)
1. [Output](doc/configuration.md#output-output)
1. [Permissions](doc/configuration.md#permissions-chmod)
1. [Check requirements](doc/configuration.md#check-requirements-check-requirements)
1. [Including files](doc/configuration.md#including-files)
1. [Files (`files` and `files-bin`)](doc/configuration.md#files-files-and-files-bin)
1. [Directories (`directories` and `directories-bin`)](doc/configuration.md#directories-directories-and-directories-bin)
Expand Down
19 changes: 19 additions & 0 deletions bin/dump-requirements-checker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

/*
* This file is part of the box project.
*
* (c) Kevin Herrera <kevin@herrera.io>
* Théo Fidry <theo.fidry@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

(new Phar(__DIR__.'/../requirement-checker/bin/check-requirements.phar'))->extractTo(
__DIR__.'/../.requirement-checker',
null,
true
);
3 changes: 3 additions & 0 deletions box.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"with this source code in the file LICENSE."
],

"directories-bin": [
".requirement-checker"
],
"files": [
"composer.json",
"vendor/composer/composer/LICENSE"
Expand Down
Loading

0 comments on commit 58e173f

Please sign in to comment.