diff --git a/src/BuildProcess/BuildContainerImage.php b/src/BuildProcess/BuildContainerImage.php index a6da3da1..2cf79446 100644 --- a/src/BuildProcess/BuildContainerImage.php +++ b/src/BuildProcess/BuildContainerImage.php @@ -2,6 +2,7 @@ namespace Laravel\VaporCli\BuildProcess; +use Illuminate\Support\Collection; use Illuminate\Support\Str; use Laravel\VaporCli\Docker; use Laravel\VaporCli\Helpers; @@ -37,11 +38,18 @@ class BuildContainerImage ]; /** - * The Docker build arguments. + * The Docker CLI build arguments. * * @var array */ - protected $buildArgs; + protected $cliBuildArgs; + + /** + * The Docker manifest build arguments. + * + * @var array + */ + protected $manifestBuildArgs; /** * Create a new project builder. @@ -50,11 +58,12 @@ class BuildContainerImage * @param array $buildArgs * @return void */ - public function __construct($environment = null, $buildArgs = []) + public function __construct($environment = null, $cliBuildArgs = [], $manifestBuildArgs = []) { $this->baseConstructor($environment); - $this->buildArgs = $buildArgs; + $this->cliBuildArgs = $cliBuildArgs; + $this->manifestBuildArgs = $manifestBuildArgs; } /** @@ -68,7 +77,16 @@ public function __invoke() return; } - if (! $this->validateDockerFile($this->environment, $runtime = Manifest::runtime($this->environment))) { + $buildArgs = Collection::make($this->manifestBuildArgs) + ->merge(Collection::make($this->cliBuildArgs) + ->mapWithKeys(function ($value) { + [$key, $value] = explode('=', $value, 2); + + return [$key => $value]; + }) + )->toArray(); + + if (! $this->validateDockerFile($this->environment, $runtime = Manifest::runtime($this->environment), $buildArgs)) { Helpers::abort('The base image used in '.Path::dockerfile($this->environment).' is incompatible with the "'.$runtime.'" runtime, or you are running an outdated version of Vapor CLI.'); } @@ -97,17 +115,21 @@ protected function getTagName() * * @param string $environment * @param string $runtime + * @param array $buildArgs * @return bool */ - public function validateDockerFile($environment, $runtime) + public function validateDockerFile($environment, $runtime, $buildArgs) { $contents = file_get_contents(Path::dockerfile($environment)); - if (! Str::contains($contents, 'laravelphp/vapor:php')) { - // Custom image... + if (! Str::contains($contents, 'FROM laravelphp/vapor')) { return false; } + foreach ($buildArgs as $key => $value) { + $contents = str_replace('${'.$key.'}', $value, $contents); + } + if ($runtime === 'docker') { foreach (static::$x86Images as $image) { if (! Str::contains($contents, 'FROM '.$image.'-') @@ -127,7 +149,7 @@ public function validateDockerFile($environment, $runtime) } /** - * Format the Docker build arguments. + * Format the Docker CLI build arguments. * * @return array */ @@ -135,7 +157,7 @@ public function formatBuildArguments() { return array_merge( ['__VAPOR_RUNTIME='.Manifest::runtime($this->environment)], - array_filter($this->buildArgs, function ($value) { + array_filter($this->cliBuildArgs, function ($value) { return ! Str::startsWith($value, '__VAPOR_RUNTIME'); }) ); diff --git a/src/Commands/BuildCommand.php b/src/Commands/BuildCommand.php index e77cb810..1383faaa 100644 --- a/src/Commands/BuildCommand.php +++ b/src/Commands/BuildCommand.php @@ -88,7 +88,7 @@ public function handle() new ExtractVendorToSeparateDirectory($this->argument('environment')), new CompressApplication($this->argument('environment')), new CompressVendor($this->argument('environment')), - new BuildContainerImage($this->argument('environment'), $this->option('build-arg')), + new BuildContainerImage($this->argument('environment'), $this->option('build-arg'), Manifest::dockerBuildArgs($this->argument('environment'))), ])->each->__invoke(); $time = (new DateTime())->diff($startedAt)->format('%im%Ss'); diff --git a/tests/BuildContainerImageTest.php b/tests/BuildContainerImageTest.php index 319b1a5f..b677459c 100644 --- a/tests/BuildContainerImageTest.php +++ b/tests/BuildContainerImageTest.php @@ -33,13 +33,13 @@ protected function tearDown(): void /** * @dataProvider runtimeProvider */ - public function test_cannot_build_with_x86_runtime_and_arm_base_image($runtime, $dockerFileContents, $expectation) + public function test_cannot_build_with_x86_runtime_and_arm_base_image($runtime, $dockerFileContents, $buildArgs, $expectation) { file_put_contents($this->dockerFile, $dockerFileContents); $this->assertSame( $expectation, - (new BuildContainerImage('production'))->validateDockerFile('production', $runtime) + (new BuildContainerImage('production'))->validateDockerFile('production', $runtime, $buildArgs) ); } @@ -83,61 +83,73 @@ public function runtimeProvider() [ 'docker', 'FROM laravelphp/vapor:php82-arm', + [], false, ], [ 'docker', 'FROM laravelphp/vapor:php82', + [], true, ], [ 'docker-arm', 'FROM laravelphp/vapor:php82', + [], false, ], [ 'docker-arm', 'FROM laravelphp/vapor:php82-arm', + [], true, ], [ 'docker-arm', 'FROM custom/image', + [], false, ], [ 'docker', 'FROM custom/image', + [], false, ], [ 'docker', 'FROM custom/image'.PHP_EOL.'FROM laravelphp/vapor:php82', + [], true, ], [ 'docker', 'FROM custom/image'.PHP_EOL.'FROM laravelphp/vapor:php82-arm', + [], false, ], [ 'docker-arm', 'FROM custom/image'.PHP_EOL.'FROM laravelphp/vapor:php82-arm', + [], true, ], [ 'docker-arm', 'FROM custom/image'.PHP_EOL.'FROM laravelphp/vapor:php82', + [], false, ], [ 'docker', 'FROM custom/vapor:php82-arm', + [], false, ], [ 'docker-arm', 'FROM custom/vapor:php82', + [], false, ], @@ -145,21 +157,25 @@ public function runtimeProvider() [ 'docker', "\r\nFROM laravelphp/vapor:php82-arm\r\n", + [], false, ], [ 'docker', "\nFROM laravelphp/vapor:php82-arm\n", + [], false, ], [ 'docker', "\nFROM laravelphp/vapor:php82-arm\n", + [], false, ], [ 'docker-arm', "\nFROM laravelphp/vapor:php82\n", + [], false, ], @@ -167,31 +183,87 @@ public function runtimeProvider() [ 'docker', 'FROM laravelphp/vapor:php82', + [], true, ], [ 'docker', 'FROM laravelphp/vapor:php83', + [], false, ], [ 'docker-arm', 'FROM laravelphp/vapor:php82-arm', + [], true, ], [ 'docker-arm', 'FROM laravelphp/vapor:php82-arm', + [], true, ], [ 'docker-arm', 'FROM laravelphp/vapor:php83-arm', + [], false, ], [ 'docker-arm', 'FROM laravelphp/vapor:php84-arm', + [], + false, + ], + [ + 'docker-arm', + 'FROM laravelphp/vapor:php84-arm', + [], + false, + ], + + // Build arguments + [ + 'docker-arm', + "ARG VERSION=php81\nFROM laravelphp/vapor:\${VERSION}-arm", + [], + false, + ], + [ + 'docker', + "ARG VERSION=php81\nFROM laravelphp/vapor:\${VERSION}", + [], + false, + ], + [ + 'docker-arm', + "ARG VERSION=php81\nFROM laravelphp/vapor:\${VERSION}", + ['VERSION' => 'php82-arm'], + true, + ], + [ + 'docker', + "ARG VERSION=php81\nFROM laravelphp/vapor:\${VERSION}", + ['VERSION' => 'php82'], + true, + ], + [ + 'docker-arm', + "ARG VERSION=php81\nFROM laravelphp/vapor:\${VERSION}", + ['VERSION' => 'php82-arm'], + true, + ], + [ + 'docker-arm', + "ARG VERSION=php81\nFROM laravelphp/vapor:\${VERSION}", + ['VERSION' => 'php82'], + false, + ], + [ + 'docker', + "ARG VERSION=php81\nFROM laravelphp/vapor:\${VERSION}", + ['VERSION' => 'php82-arm'], false, ], ]; diff --git a/vapor b/vapor index 2483692a..2cad570b 100755 --- a/vapor +++ b/vapor @@ -68,7 +68,7 @@ Container::setInstance($container = new Container); /** * Start the console application. */ -$app = new Application('Laravel Vapor', '1.55.1'); +$app = new Application('Laravel Vapor', '1.55.2'); // Authentication... $app->add(new Commands\LoginCommand);