diff --git a/src/Action/CreateListOfFilesToGenerate.php b/src/Action/CreateListOfFilesToGenerate.php index bf1376f..6c49947 100644 --- a/src/Action/CreateListOfFilesToGenerate.php +++ b/src/Action/CreateListOfFilesToGenerate.php @@ -40,6 +40,40 @@ final class CreateListOfFilesToGenerate ); }); break; + + case (strtolower(ProjectType::Drupal->name)): + $filesToGenerate = collect([ + new TemplateFile(data: 'drupal/.dockerignore', name: '.dockerignore'), + new TemplateFile(data: 'drupal/.env.example', name: '.env.example'), + new TemplateFile(data: 'drupal/.gitignore', name: '.gitignore'), + new TemplateFile(data: 'drupal/.hadolint.yaml', name: '.hadolint.yaml'), + new TemplateFile(data: 'drupal/Dockerfile', name: 'Dockerfile'), + new TemplateFile(data: 'drupal/docker-compose.yaml', name: 'docker-compose.yaml'), + ]); + + $extraDatabases = Arr::get($configurationData, 'database.extra_databases', []); + if (count($extraDatabases) > 0) { + $filesToGenerate->push(new TemplateFile( + data: 'drupal/extra-databases.sql', + name: 'extra-databases.sql', + path: 'tools/docker/images/database/root/docker-entrypoint-initdb.d', + )); + } + + $filesToGenerate->push(new TemplateFile(data: 'drupal/phpcs.xml.dist', name: 'phpcs.xml.dist')); + $filesToGenerate->push(new TemplateFile(data: 'drupal/phpunit.xml.dist', name: 'phpunit.xml.dist')); + $filesToGenerate->push(new TemplateFile( + data: 'drupal/docker-entrypoint-php', + name: 'docker-entrypoint-php', + path: 'tools/docker/images/php/root/usr/local/bin', + )); + + $filesToGenerate->push(new TemplateFile( + data: 'drupal/php.ini', + name: 'php.ini', + path: 'tools/docker/images/php/root/usr/local/etc/php', + )); + break; } if ($filesToGenerate->isNotEmpty()) { @@ -60,15 +94,6 @@ final class CreateListOfFilesToGenerate $filesToGenerate->push(new TemplateFile(data: 'common/flake.nix', name: 'flake.nix')); } - $extraDatabases = Arr::get($configurationData, 'database.extra_databases', []); - if (count($extraDatabases) > 0) { - $filesToGenerate[] = new TemplateFile( - data: 'extra-databases.sql', - name: 'extra-databases.sql', - path: 'tools/docker/images/database/root/docker-entrypoint-initdb.d', - ); - } - if (false !== Arr::get($configurationData, "justfile", true)) { $filesToGenerate[] = new TemplateFile(data: 'justfile', name: 'justfile'); } diff --git a/src/Enum/ProjectType.php b/src/Enum/ProjectType.php index 45f0246..f51c7e2 100644 --- a/src/Enum/ProjectType.php +++ b/src/Enum/ProjectType.php @@ -7,4 +7,5 @@ namespace App\Enum; enum ProjectType { case Astro; + case Drupal; } diff --git a/templates/drupal/.dockerignore.twig b/templates/drupal/.dockerignore.twig new file mode 100644 index 0000000..1df7806 --- /dev/null +++ b/templates/drupal/.dockerignore.twig @@ -0,0 +1,4 @@ +/README.md +{% if experimental.createGitHubActionsConfiguration %} +/.github/ +{%-endif-%} diff --git a/templates/drupal/.env.example.twig b/templates/drupal/.env.example.twig new file mode 100644 index 0000000..1d15149 --- /dev/null +++ b/templates/drupal/.env.example.twig @@ -0,0 +1,20 @@ +# {{ managedText|raw }} + +export DOCKER_UID=1000 + +{% if dockerCompose %} +export COMPOSE_PROJECT_NAME={{ name }} +export COMPOSE_PROFILES=web,php,database + +export DOCKER_WEB_VOLUME=.:{{ project_root }} +{% endif %} + +{% if experimental.useNewDatabaseCredentials %} +export MYSQL_DATABASE=app +export MYSQL_PASSWORD=app +export MYSQL_USER=app +{% else %} +export MYSQL_DATABASE=drupal +export MYSQL_PASSWORD=drupal +export MYSQL_USER=drupal +{% endif %} diff --git a/templates/drupal/.gitignore.twig b/templates/drupal/.gitignore.twig new file mode 100644 index 0000000..c5dd842 --- /dev/null +++ b/templates/drupal/.gitignore.twig @@ -0,0 +1,36 @@ +# {{ managedText|raw }} + +.editorconfig +.env +.gitattributes +vendor/ +{{ drupal.docroot }}/.csslintrc +{{ drupal.docroot }}/.eslintignore +{{ drupal.docroot }}/.eslintrc.json +{{ drupal.docroot }}/.ht.router.php +{{ drupal.docroot }}/.htaccess +{{ drupal.docroot }}/INSTALL.txt +{{ drupal.docroot }}/README.md +{{ drupal.docroot }}/autoload.php +{{ drupal.docroot }}/core/ +{{ drupal.docroot }}/example.gitignore +{{ drupal.docroot }}/index.php +{{ drupal.docroot }}/modules/README.txt +{{ drupal.docroot }}/modules/contrib/ +{{ drupal.docroot }}/profiles/README.txt +{{ drupal.docroot }}/robots.txt +{{ drupal.docroot }}/sites/*/files/ +{{ drupal.docroot }}/sites/*/private/ +{{ drupal.docroot }}/sites/*/services*.yml +{{ drupal.docroot }}/sites/*/settings*.php +{{ drupal.docroot }}/sites/README.txt +{{ drupal.docroot }}/sites/default/default.services.yml +{{ drupal.docroot }}/sites/default/default.settings.php +{{ drupal.docroot }}/sites/development.services.yml +{{ drupal.docroot }}/sites/example.settings.local.php +{{ drupal.docroot }}/sites/example.sites.php +{{ drupal.docroot }}/sites/simpletest/ +{{ drupal.docroot }}/themes/README.txt +{{ drupal.docroot }}/themes/contrib/ +{{ drupal.docroot }}/update.php +{{ drupal.docroot }}/web.config diff --git a/templates/drupal/.hadolint.yaml.twig b/templates/drupal/.hadolint.yaml.twig new file mode 100644 index 0000000..d87bf88 --- /dev/null +++ b/templates/drupal/.hadolint.yaml.twig @@ -0,0 +1,2 @@ +ignore: + - DL3059 diff --git a/templates/drupal/Dockerfile.twig b/templates/drupal/Dockerfile.twig new file mode 100644 index 0000000..7ad942d --- /dev/null +++ b/templates/drupal/Dockerfile.twig @@ -0,0 +1,104 @@ +# {{ managedText|raw }} + +FROM php:{{ php.version }} AS base + +COPY --from=composer:2 /usr/bin/composer /usr/bin/composer +RUN which composer && composer -V + +ARG DOCKER_UID=1000 +ENV DOCKER_UID="${DOCKER_UID}" + +WORKDIR {{ project_root }} + +RUN adduser --disabled-password --uid "${DOCKER_UID}" app \ + && chown app:app -R {{ project_root }} + +USER app + +ENV PATH="${PATH}:{{ project_root }}/bin:{{ project_root }}/vendor/bin" + +COPY --chown=app:app composer.* ./ + +################################################################################ + +FROM base AS build + +USER root + +{% if 'apache' in php.version %} +RUN a2enmod rewrite +{% endif %} + +{% if dockerfile.stages.build.packages %} +RUN apt-get update -yqq \ + && apt-get install -yqq --no-install-recommends \ + {{ dockerfile.stages.build.packages | join(' ') }} +{% endif %} + +RUN docker-php-ext-configure gd --with-jpeg + +{% if dockerfile.stages.build.extensions.install %} +RUN docker-php-ext-install {{ dockerfile.stages.build.extensions.install | join(' ') }} +{% endif %} + +COPY --chown=app:app phpunit.xml* ./ + +{% if dockerfile.stages.build.extra_files %} +COPY --chown=app:app {{ dockerfile.stages.build.extra_files | join(" ") }} ./ +{% endif %} +{% for directory in dockerfile.stages.build.extra_directories %} +COPY --chown=app:app {{ directory }} {{ directory }} +{% endfor %} + +{% for command in dockerfile.stages.build.root_commands | default([]) %} +RUN {{ command | raw }} +{% endfor %} + +USER app + +{% for command in dockerfile.stages.build.commands %} +RUN {{ command }} +{% endfor %} + +COPY --chown=app:app tools/docker/images/php/root / + +ENTRYPOINT ["/usr/local/bin/docker-entrypoint-php"] +CMD ["php-fpm"] + +{% if dockerfile.stages.test %} +################################################################################ + +FROM {{ dockerfile.stages.test.extends }} AS test + +COPY --chown=app:app . . + +RUN {% for command in dockerfile.stages.test.commands -%} +{% if not loop.first %} && {% endif %} +{{ command }} +{%- if not loop.last %} \{% endif %} + +{% endfor %} +{% endif %} + + +{% if web.type == "caddy" %} +################################################################################ + +FROM caddy:2 as web + +WORKDIR {{ project_root }} + +COPY tools/docker/images/web/root / +{% endif %} + +{% if web.type == "nginx" %} +################################################################################ + +FROM nginx:1 as web + +EXPOSE 8080 + +WORKDIR {{ project_root }} + +COPY tools/docker/images/web/root / +{% endif %} diff --git a/templates/drupal/docker-compose.yaml.twig b/templates/drupal/docker-compose.yaml.twig new file mode 100644 index 0000000..824cf5b --- /dev/null +++ b/templates/drupal/docker-compose.yaml.twig @@ -0,0 +1,88 @@ +# {{ managedText|raw }} + +x-proxy: &default-proxy + networks: + - default + - web + labels: + - "traefik.docker.network=traefik_proxy" + - "traefik.http.routers.${COMPOSE_PROJECT_NAME}.rule=Host( + `${COMPOSE_PROJECT_NAME}.localhost`, + {% for host in web.extra_hosts | default([]) -%} + {{ '`' ~ host ~ '`,' }} + {%- endfor %} + )" + +x-app: &default-app + volumes: + - "${DOCKER_WEB_VOLUME:-./{{ drupal.docroot }}:{{ project_root }}/{{ drupal.docroot }}}" + env_file: + - .env + restart: "${DOCKER_RESTART_POLICY:-unless-stopped}" + networks: + - default + deploy: + resources: + limits: + cpus: "${DOCKER_MYSQL_CPUS:-0}" + memory: "${DOCKER_MYSQL_MEMORY:-0}" + labels: + - "traefik.enabled=false" + tty: true + +services: +{% if "web" in dockerCompose.services %} + web: + <<: [*default-proxy, *default-app] + build: + context: . + target: web + depends_on: + - php + profiles: [web] +{% endif %} + + {% set anchors = [ + "apache" in php.version ? "*default-proxy" : null, + "*default-app", + ] -%} + php: + <<: [{{ anchors | filter(item => item is not null) | join(", ") }}] + build: + context: . + target: build + args: + - "DOCKER_UID=${DOCKER_UID:-1000}" + volumes: + - .:{{ project_root }} + {% if "database" in dockerCompose.services -%} + depends_on: + - database + {% endif -%} + profiles: [php] + + database: + image: {{ database.type }}:{{ database.version }} + deploy: + resources: + limits: + cpus: "${DOCKER_MYSQL_CPUS:-0}" + memory: "${DOCKER_MYSQL_MEMORY:-0}" + volumes: + - db-data:/var/lib/mysql + {{ database.extra_databases is not empty ? '- ./tools/docker/images/database/root/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d' : '' }} + env_file: + - .env + labels: + - "traefik.enabled=false" + environment: + MYSQL_RANDOM_ROOT_PASSWORD: true + profiles: [database] + +volumes: + db-data: {} + +networks: + web: + external: true + name: traefik_proxy diff --git a/templates/drupal/docker-entrypoint-php.twig b/templates/drupal/docker-entrypoint-php.twig new file mode 100644 index 0000000..a851428 --- /dev/null +++ b/templates/drupal/docker-entrypoint-php.twig @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +# {{ managedText|raw }} + +[[ -f composer.json && ! -d vendor ]] && composer install + +eval "$@" diff --git a/templates/extra-databases.sql.twig b/templates/drupal/extra-databases.sql.twig similarity index 66% rename from templates/extra-databases.sql.twig rename to templates/drupal/extra-databases.sql.twig index bfae912..2492117 100644 --- a/templates/extra-databases.sql.twig +++ b/templates/drupal/extra-databases.sql.twig @@ -1,4 +1,4 @@ -{% for database in database.extra_databases %} +{% new TemplateFilefor database in database.extra_databases %} CREATE DATABASE {{ database }}; GRANT ALL PRIVILEGES ON {{ database }}.* TO drupal@'%' IDENTIFIED BY 'drupal'; diff --git a/templates/drupal/php.ini.twig b/templates/drupal/php.ini.twig new file mode 100644 index 0000000..fa28093 --- /dev/null +++ b/templates/drupal/php.ini.twig @@ -0,0 +1,4 @@ +# {{ managedText }} + +max_vars_input = 1000 +memory_limit = {{ php.ini.memory_limit | default('128M') }} diff --git a/templates/drupal/phpcs.xml.dist.twig b/templates/drupal/phpcs.xml.dist.twig new file mode 100644 index 0000000..98af4fb --- /dev/null +++ b/templates/drupal/phpcs.xml.dist.twig @@ -0,0 +1,38 @@ + + + + + PHPCS configuration file for {{ name }}. + + {% for path in php.phpcs.paths|default('[]') %} + {{ path }} + {% endfor %} + + + + {% for standard in php.phpcs.standards|default(['Drupal', 'DrupalPractice']) %} + {% if not standard is same as "Drupal" %} + + {% endif %} + {% endfor %} + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/env.example.twig b/templates/env.example.twig index f79d004..365e728 100644 --- a/templates/env.example.twig +++ b/templates/env.example.twig @@ -4,16 +4,11 @@ export DOCKER_UID=1000 {% if dockerCompose %} export COMPOSE_PROJECT_NAME={{ name }} -{% if "php" == language %} export COMPOSE_PROFILES=web,php,database -{% elseif "node" == language %} -export COMPOSE_PROFILES=node -{% endif %} export DOCKER_WEB_VOLUME=.:{{ project_root }} {% endif %} -{% if "drupal" == type %} {% if experimental.useNewDatabaseCredentials %} export MYSQL_DATABASE=app export MYSQL_PASSWORD=app @@ -23,4 +18,3 @@ export MYSQL_DATABASE=drupal export MYSQL_PASSWORD=drupal export MYSQL_USER=drupal {% endif %} -{% endif %}