refactor: use mnapoli/silly

This commit is contained in:
Oliver Davies 2023-03-13 01:19:12 +00:00
parent 5c4ddd52a4
commit cf25359c7b
4 changed files with 291 additions and 204 deletions

View file

@ -1,25 +1,187 @@
#!/usr/bin/env php
<?php
use OliverDaviesLtd\BuildConfigs\Console\Command\BuildConfigurationCommand;
declare(strict_types=1);
require __DIR__.'/../vendor/autoload.php';
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use OliverDaviesLtd\BuildConfigs\Enum\Language;
use OliverDaviesLtd\BuildConfigs\Enum\WebServer;
use OliverDaviesLtd\BuildConfigs\Validator\ConfigurationValidator;
use Symfony\Component\Console\Application;
use Silly\Application;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Validator\ConstraintViolationInterface;
use Symfony\Component\Yaml\Yaml;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
require __DIR__ . '/../vendor/autoload.php';
$app = new Application();
$filesystem = new Filesystem();
$twig = new Environment(new FilesystemLoader([__DIR__.'/../templates']));
$configurationValidator = new ConfigurationValidator();
$app->command(
'run [-c|--config-file=] [-o|--output-dir=]',
function (
SymfonyStyle $io,
string $configFile = 'build.yaml',
string $outputDir = '.',
): void {
$configurationData = array_merge(
Yaml::parseFile(__DIR__ . '/../resources/build.defaults.yaml'),
Yaml::parseFile($configFile),
);
$application = new Application();
$command = new BuildConfigurationCommand($twig, $filesystem, $configurationValidator);
$violations = (new ConfigurationValidator())->validate($configurationData);
$application->addCommands([
new BuildConfigurationCommand($twig, $filesystem, $configurationValidator),
if (0 < $violations->count()) {
$io->error('Configuration is invalid.');
$io->listing(
collect($violations)
->map(fn (ConstraintViolationInterface $v) => "{$v->getInvalidValue()} - {$v->getMessage()}")
->toArray()
);
return;
}
if (isset($configurationData['docker-compose'])) {
$configurationData['dockerCompose'] = $configurationData['docker-compose'];
$configurationData['docker-compose'] = null;
}
$io->info("Building configuration for {$configurationData['name']}.");
$filesToGenerate = collect([
['env.example', '.env.example'],
]);
if (false !== Arr::get($configurationData, "justfile", true)) {
$filesToGenerate->push(['justfile', 'justfile']);
}
if (isset($configurationData['dockerCompose']) && $configurationData['dockerCompose'] !== null) {
$filesToGenerate->push(['docker-compose.yaml', 'docker-compose.yaml']);
}
if (isPhp(Arr::get($configurationData, 'language'))) {
$filesToGenerate->push(['php/Dockerfile', 'Dockerfile']);
$filesToGenerate->push(['php/phpcs.xml', 'phpcs.xml.dist']);
$filesToGenerate->push(['php/phpstan.neon', 'phpstan.neon.dist']);
$filesToGenerate->push(['php/phpunit.xml', 'phpunit.xml.dist']);
$filesToGenerate->push(['php/docker-entrypoint-php', 'tools/docker/images/php/root/usr/local/bin/docker-entrypoint-php']);
}
if (isNode(Arr::get($configurationData, 'language'))) {
$filesToGenerate->push(['node/.yarnrc', '.yarnrc']);
$filesToGenerate->push(['node/Dockerfile', 'Dockerfile']);
}
if (isCaddy(Arr::get($configurationData, 'web.type'))) {
$filesToGenerate->push(['web/caddy/Caddyfile', 'tools/docker/images/web/root/etc/caddy/Caddyfile']);
}
if (isNginx(Arr::get($configurationData, 'web.type'))) {
$filesToGenerate->push(['web/nginx/default.conf', 'tools/docker/images/web/root/etc/nginx/conf.d/default.conf']);
}
if ('drupal-project' === Arr::get($configurationData, 'type')) {
// Ensure a "docroot" value is set.
if (null === Arr::get($configurationData, 'drupal.docroot')) {
Arr::set($configurationData, 'drupal.docroot', 'web');
}
// Add a Drupal version of phpunit.xml.dist.
$filesToGenerate->push(['drupal-project/phpunit.xml.dist', 'phpunit.xml.dist']);
}
$configurationData['managedText'] = 'Do not edit this file. It is automatically generated by \'build-configs\'.';
generateFiles(
configurationData: $configurationData,
filesToGenerate: $filesToGenerate,
outputDir: $outputDir,
);
}
)->descriptions('Generate project-specific configuration files.', [
'--config-file' => 'The path to the project\'s build.yaml file',
'--output-dir' => 'The directory to create files in',
]);
$application->setDefaultCommand('build-configs', true);
$application->run();
$app->setDefaultCommand('run');
$app->run();
/**
* @param array<string, string> $configurationData
*/
function generateFiles(
Collection $filesToGenerate,
string $outputDir,
array $configurationData,
): void
{
$filesystem = new Filesystem();
$twig = new Environment(new FilesystemLoader([__DIR__ . '/../templates']));
if (isPhp(Arr::get($configurationData, 'language'))) {
$filesystem->mkdir("{$outputDir}/tools/docker/images/php/root/usr/local/bin");
}
if (isCaddy(Arr::get($configurationData, 'web.type'))) {
$filesystem->mkdir("{$outputDir}/tools/docker/images/web/root/etc/caddy");
} elseif (isNginx(Arr::get($configurationData, 'web.type'))) {
$filesystem->mkdir("{$outputDir}/tools/docker/images/web/root/etc/nginx/conf.d");
}
$filesToGenerate->map(function(array $filenames) use ($outputDir): array {
$filenames[0] = "{$filenames[0]}.twig";
$filenames[1] = "{$outputDir}/${filenames[1]}";
return $filenames;
})->each(function(array $filenames) use ($configurationData, $filesystem, $twig): void {
$filesystem->dumpFile($filenames[1], $twig->render($filenames[0], $configurationData));
});
// If the Docker entrypoint file is generated, ensure it is executable.
if ($filesystem->exists("{$outputDir}/tools/docker/images/php/root/usr/local/bin/docker-entrypoint-php")) {
$filesystem->chmod("{$outputDir}/tools/docker/images/php/root/usr/local/bin/docker-entrypoint-php", 0755);
}
}
function isCaddy(?string $webServer): bool
{
if (is_null($webServer)) {
return false;
}
return strtoupper($webServer) === WebServer::CADDY->name;
}
function isNginx(?string $webServer): bool
{
if (is_null($webServer)) {
return false;
}
return strtoupper($webServer) === WebServer::NGINX->name;
}
function isNode(?string $language): bool
{
if (is_null($language)) {
return false;
}
return strtoupper($language) === Language::NODE->name;
}
function isPhp(?string $language): bool
{
if (is_null($language)) {
return false;
}
return strtoupper($language) === Language::PHP->name;
}