Skip to content

Commit 9bf8c59

Browse files
authored
Refactor how we use run() docker command (#426)
1. use array insteand of string, it's more secure, and easier to manipulate data 2. move many code from the builder to to the run() command 3. add an exec() command 4. and remove run_in_docker_or_locally_for_mac, not used anymore
1 parent ffd0170 commit 9bf8c59

5 files changed

Lines changed: 90 additions & 65 deletions

File tree

.castor/docker.php

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -175,22 +175,14 @@ function stop(
175175
}
176176

177177
/**
178-
* @param array<string> $params
178+
* @param list<string> $params
179179
*/
180180
#[AsTask(description: 'Opens a shell (bash) or proxy any command to the builder container', aliases: ['builder'])]
181181
function builder(#[AsArgsAfterOptionEnd] array $params = []): int
182182
{
183-
$c = context()->withEnvironment($_ENV + $_SERVER);
183+
$context = context()->withEnvironment($_ENV + $_SERVER);
184184

185-
if (0 === \count($params)) {
186-
$params = ['bash'];
187-
$c = $c->toInteractive();
188-
} else {
189-
$c = $c->withTty(false)->withPty(false)->withInput(STDIN)->withAllowFailure();
190-
$params = array_map(escapeshellarg(...), $params);
191-
}
192-
193-
return (int) docker_compose_run(implode(' ', $params), c: $c)->getExitCode();
185+
return (int) docker_compose_run($params, $context)->getExitCode();
194186
}
195187

196188
/**
@@ -435,8 +427,11 @@ function docker_compose(array $subCommand, ?Context $c = null, array $profiles =
435427
return run($command, context: $c);
436428
}
437429

430+
/**
431+
* @param list<string> $params
432+
*/
438433
function docker_compose_run(
439-
string $runCommand,
434+
array $params,
440435
?Context $c = null,
441436
string $service = 'builder',
442437
bool $noDeps = true,
@@ -469,16 +464,57 @@ function docker_compose_run(
469464
$command[] = "{$key}={$value}";
470465
}
471466

467+
if (0 === \count($params)) {
468+
$params = ['bash'];
469+
$c = $c->toInteractive();
470+
} else {
471+
$c = $c->withTty(false)->withPty(false)->withInput(STDIN)->withAllowFailure();
472+
$params = array_map(escapeshellarg(...), $params);
473+
}
474+
472475
$command[] = $service;
473476
$command[] = '/bin/bash';
474477
$command[] = '-c';
475-
$command[] = "{$runCommand}";
478+
$command[] = implode(' ', $params);
476479

477480
return docker_compose($command, c: $c, profiles: ['*']);
478481
}
479482

483+
/**
484+
* @param list<string> $params
485+
*/
486+
function docker_compose_exec(
487+
array $params,
488+
?Context $context = null,
489+
string $service = 'builder',
490+
): Process {
491+
$context ??= context();
492+
493+
$command = [
494+
'exec',
495+
];
496+
497+
if (0 === \count($params)) {
498+
$params = ['bash'];
499+
$context = $context->toInteractive();
500+
} else {
501+
$context = $context->withTty(false)->withPty(false)->withInput(STDIN)->withAllowFailure();
502+
$params = array_map(escapeshellarg(...), $params);
503+
}
504+
505+
$command[] = $service;
506+
$command[] = '/bin/bash';
507+
$command[] = '-c';
508+
$command[] = implode(' ', $params);
509+
510+
return docker_compose($command, c: $context, profiles: ['*']);
511+
}
512+
513+
/**
514+
* @param list<string> $params
515+
*/
480516
function docker_exit_code(
481-
string $runCommand,
517+
array $params,
482518
?Context $c = null,
483519
string $service = 'builder',
484520
bool $noDeps = true,
@@ -487,7 +523,7 @@ function docker_exit_code(
487523
$c = ($c ?? context())->withAllowFailure();
488524

489525
$process = docker_compose_run(
490-
runCommand: $runCommand,
526+
params: $params,
491527
c: $c,
492528
service: $service,
493529
noDeps: $noDeps,
@@ -497,19 +533,6 @@ function docker_exit_code(
497533
return $process->getExitCode() ?? 0;
498534
}
499535

500-
// Mac users have a lot of problems running Yarn / Webpack on the Docker stack
501-
// so this func allow them to run these tools on their host
502-
function run_in_docker_or_locally_for_mac(string $command, ?Context $c = null): void
503-
{
504-
$c ??= context();
505-
506-
if ($c['macos']) {
507-
run($command, context: $c->withWorkingDirectory($c['root_dir']));
508-
} else {
509-
docker_compose_run($command, c: $c);
510-
}
511-
}
512-
513536
#[AsTask(description: 'Push images cache to the registry', namespace: 'docker', name: 'push', aliases: ['push'])]
514537
function push(bool $dryRun = false): void
515538
{

.castor/init.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,16 @@ function symfony(bool $webApp = false): void
4444
}
4545

4646
build();
47-
docker_compose_run('composer create-project symfony/skeleton sf');
47+
docker_compose_run(['composer', 'create-project', 'symfony/skeleton', 'sf']);
4848

4949
fs()->mirror($base . '/sf/', $base, options: ['override' => true]);
5050
fs()->remove([$base . '/sf', $base . '/var']);
5151

5252
if ($webApp) {
53-
docker_compose_run('composer require webapp');
53+
docker_compose_run(['composer', 'require', 'webapp']);
5454
}
5555

56-
docker_compose_run("sed -i 's#^DATABASE_URL.*#DATABASE_URL=postgresql://app:app@postgres:5432/app\\?serverVersion=16\\&charset=utf8#' .env");
56+
docker_compose_run(['sed', '-i', 's#^DATABASE_URL.*#DATABASE_URL=postgresql://app:app@postgres:5432/app\?serverVersion=16\&charset=utf8#', '.env']);
5757
file_put_contents($gitIgnore, $gitIgnoreContent, \FILE_APPEND);
5858
}
5959

@@ -69,12 +69,12 @@ function sylius(): void
6969
}
7070

7171
build();
72-
docker_compose_run('composer create-project sylius/sylius-standard sylius');
72+
docker_compose_run(['composer', 'create-project', 'sylius/sylius-standard', 'sylius']);
7373

7474
fs()->mirror($base . '/sylius/', $base, options: ['override' => true]);
7575
fs()->remove([$base . '/sylius', $base . '/var']);
7676

77-
docker_compose_run("sed -i 's#^DATABASE_URL.*#DATABASE_URL=postgresql://app:app@postgres:5432/app\\?serverVersion=16\\&charset=utf8#' .env");
77+
docker_compose_run(['sed', '-i', 's#^DATABASE_URL.*#DATABASE_URL=postgresql://app:app@postgres:5432/app\?serverVersion=16\&charset=utf8#', '.env']);
7878
file_put_contents($gitIgnore, $gitIgnoreContent, \FILE_APPEND);
7979

8080
chrome();

.castor/qa.php

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,23 @@ function install(): void
2727
{
2828
io()->title('Installing QA tooling');
2929

30-
docker_compose_run('composer install -o', workDir: '/var/www/tools/php-cs-fixer');
31-
docker_compose_run('composer install -o', workDir: '/var/www/tools/phpstan');
32-
docker_compose_run('composer install -o', workDir: '/var/www/tools/twig-cs-fixer');
30+
docker_compose_run(['composer', 'install', '-o'], workDir: '/var/www/tools/php-cs-fixer');
31+
docker_compose_run(['composer', 'install', '-o'], workDir: '/var/www/tools/phpstan');
32+
docker_compose_run(['composer', 'install', '-o'], workDir: '/var/www/tools/twig-cs-fixer');
3333
}
3434

3535
#[AsTask(description: 'Updates tooling')]
3636
function update(): void
3737
{
3838
io()->title('Updating QA tooling');
3939

40-
docker_compose_run('composer update -o', workDir: '/var/www/tools/php-cs-fixer');
41-
docker_compose_run('composer update -o', workDir: '/var/www/tools/phpstan');
42-
docker_compose_run('composer update -o', workDir: '/var/www/tools/twig-cs-fixer');
40+
docker_compose_run(['composer', 'update', '-o'], workDir: '/var/www/tools/php-cs-fixer');
41+
docker_compose_run(['composer', 'update', '-o'], workDir: '/var/www/tools/phpstan');
42+
docker_compose_run(['composer', 'update', '-o'], workDir: '/var/www/tools/twig-cs-fixer');
4343
}
4444

4545
/**
46-
* @param string[] $rawTokens
46+
* @param list<string> $rawTokens
4747
*/
4848
#[AsTask(description: 'Runs PHPUnit', aliases: ['phpunit'])]
4949
function phpunit(#[AsRawTokens] array $rawTokens = []): int
@@ -54,7 +54,7 @@ function phpunit(#[AsRawTokens] array $rawTokens = []): int
5454

5555
io()->section('Running PHPUnit...');
5656

57-
return docker_exit_code('vendor/bin/phpunit ' . implode(' ', $rawTokens));
57+
return docker_exit_code(['vendor/bin/phpunit', ...$rawTokens]);
5858
}
5959

6060
#[AsTask(description: 'Runs PHPStan', aliases: ['phpstan'])]
@@ -68,8 +68,10 @@ function phpstan(
6868

6969
io()->section('Running PHPStan...');
7070

71-
$options = $baseline ? '--generate-baseline --allow-empty-baseline' : '';
72-
$command = \sprintf('phpstan analyse --memory-limit=-1 %s -v', $options);
71+
$command = ['phpstan', 'analyse', '--memory-limit=-1', '-v'];
72+
if ($baseline) {
73+
$command = [...$command, '--generate-baseline', '--allow-empty-baseline'];
74+
}
7375

7476
return docker_exit_code($command, workDir: '/var/www');
7577
}
@@ -82,7 +84,7 @@ function securityAudit(): int
8284
if (is_file("{$basePath}/composer.lock")) {
8385
io()->text('Running Composer audit...');
8486

85-
$exitCode = docker_exit_code('composer audit');
87+
$exitCode = docker_exit_code(['composer', 'audit']);
8688

8789
if (0 !== $exitCode) {
8890
return $exitCode;
@@ -92,7 +94,7 @@ function securityAudit(): int
9294
if (is_file("{$basePath}/yarn.lock")) {
9395
io()->text('Running Yarn audit...');
9496

95-
$exitCode = docker_exit_code('yarn audit');
97+
$exitCode = docker_exit_code(['yarn', 'audit']);
9698

9799
if (0 !== $exitCode) {
98100
return $exitCode;
@@ -102,7 +104,7 @@ function securityAudit(): int
102104
if (is_file("{$basePath}/package-lock.json")) {
103105
io()->text('Running NPM audit...');
104106

105-
return docker_exit_code('npm audit');
107+
return docker_exit_code(['npm', 'audit']);
106108
}
107109

108110
return 0;
@@ -118,10 +120,10 @@ function cs(bool $dryRun = false): int
118120
io()->section('Running PHP CS Fixer...');
119121

120122
if ($dryRun) {
121-
return docker_exit_code('php-cs-fixer fix --dry-run --diff', workDir: '/var/www');
123+
return docker_exit_code(['php-cs-fixer', 'fix', '--dry-run', '--diff'], workDir: '/var/www');
122124
}
123125

124-
return docker_exit_code('php-cs-fixer fix -v', workDir: '/var/www');
126+
return docker_exit_code(['php-cs-fixer', 'fix', '-v'], workDir: '/var/www');
125127
}
126128

127129
#[AsTask(description: 'Fixes Twig Coding Style', aliases: ['twig-cs'])]
@@ -134,8 +136,8 @@ function twigCs(bool $dryRun = false): int
134136
io()->section('Running Twig CS Fixer...');
135137

136138
if ($dryRun) {
137-
return docker_exit_code('twig-cs-fixer', workDir: '/var/www');
139+
return docker_exit_code(['twig-cs-fixer'], workDir: '/var/www');
138140
}
139141

140-
return docker_exit_code('twig-cs-fixer --fix', workDir: '/var/www');
142+
return docker_exit_code(['twig-cs-fixer', '--fix'], workDir: '/var/www');
141143
}

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,13 @@ jobs:
101101
#[AsTask()]
102102
function test()
103103
{
104-
docker_compose_run('echo "Hello World"');
104+
docker_compose_run(['echo', 'Hello World']);
105105
}
106106
107107
#[AsTask()]
108108
function app_env()
109109
{
110-
docker_compose_run('php public/index.php');
110+
docker_compose_run(['php', 'public/index.php']);
111111
}
112112
EOPHP
113113

castor.php

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,23 +67,23 @@ function install(): void
6767

6868
if (is_file("{$basePath}/composer.json")) {
6969
io()->section('Installing PHP dependencies');
70-
docker_compose_run('composer install -n --prefer-dist --optimize-autoloader');
70+
docker_compose_run(['composer', 'install', '-n', '--prefer-dist', '--optimize-autoloader']);
7171
}
7272
if (is_file("{$basePath}/yarn.lock")) {
7373
io()->section('Installing Node.js dependencies');
74-
docker_compose_run('yarn install --immutable');
74+
docker_compose_run(['yarn', 'install', '--immutable']);
7575
} elseif (is_file("{$basePath}/package.json")) {
7676
io()->section('Installing Node.js dependencies');
7777

7878
if (is_file("{$basePath}/package-lock.json")) {
79-
docker_compose_run('npm ci');
79+
docker_compose_run(['npm', 'ci']);
8080
} else {
81-
docker_compose_run('npm install');
81+
docker_compose_run(['npm', 'install']);
8282
}
8383
}
8484
if (is_file("{$basePath}/importmap.php")) {
8585
io()->section('Installing importmap');
86-
docker_compose_run('bin/console importmap:install');
86+
docker_compose_run(['bin/console', 'importmap:install']);
8787
}
8888

8989
qa\install();
@@ -94,7 +94,7 @@ function update(bool $withTools = false): void
9494
{
9595
io()->title('Updating dependencies...');
9696

97-
// docker_compose_run('composer update -o');
97+
// docker_compose_run(['composer', 'update', '-o']);
9898

9999
if ($withTools) {
100100
qa\update();
@@ -106,7 +106,7 @@ function cache_clear(bool $warm = true): void
106106
{
107107
// io()->title('Clearing the application cache');
108108

109-
// docker_compose_run('rm -rf var/cache/');
109+
// docker_compose_run(['rm', '-rf', 'var/cache/']);
110110

111111
// if ($warm) {
112112
// cache_warmup();
@@ -118,16 +118,16 @@ function cache_warmup(): void
118118
{
119119
// io()->title('Warming the application cache');
120120

121-
// docker_compose_run('bin/console cache:warmup', c: context()->withAllowFailure());
121+
// docker_compose_run(['bin/console', 'cache:warmup'], c: context()->withAllowFailure());
122122
}
123123

124124
#[AsTask(description: 'Migrates database schema', namespace: 'app:db', aliases: ['migrate'])]
125125
function migrate(): void
126126
{
127127
// io()->title('Migrating the database schema');
128128

129-
// docker_compose_run('bin/console doctrine:database:create --if-not-exists');
130-
// docker_compose_run('bin/console doctrine:migration:migrate -n --allow-no-migration --all-or-nothing');
129+
// docker_compose_run(['bin/console', 'doctrine:database:create', '--if-not-exists']);
130+
// docker_compose_run(['bin/console', 'doctrine:migration:migrate', '-n', '--allow-no-migration', '--all-or-nothing']);
131131
}
132132

133133
#[AsTask(description: 'Loads fixtures', namespace: 'app:db', aliases: ['fixtures'])]
@@ -136,7 +136,7 @@ function fixtures(): void
136136
// io()->title('Loads fixtures');
137137

138138
// Uncomment one of them...
139-
// docker_compose_run('bin/console doctrine:fixture:load -n');
140-
// docker_compose_run('bin/console foundry:load-fixtures -n');
141-
// docker_compose_run('bin/console sylius:fixture:load -n');
139+
// docker_compose_run(['bin/console', 'doctrine:fixture:load', '-n']);
140+
// docker_compose_run(['bin/console', 'foundry:load-fixtures', '-n']);
141+
// docker_compose_run(['bin/console', 'sylius:fixture:load', '-n']);
142142
}

0 commit comments

Comments
 (0)