diff --git a/src/Action/CreateListOfFilesToGenerate.php b/src/Action/CreateListOfFilesToGenerate.php index 8434385..4142e8d 100644 --- a/src/Action/CreateListOfFilesToGenerate.php +++ b/src/Action/CreateListOfFilesToGenerate.php @@ -22,6 +22,9 @@ final class CreateListOfFilesToGenerate */ [$configurationData, $configurationDataDto] = $configurationDataAndDto; + $isDocker = static::isDocker($configurationData); + $isFlake = static::isFlake($configurationData); + /** @var Collection */ $filesToGenerate = collect(); @@ -36,6 +39,25 @@ final class CreateListOfFilesToGenerate ]); break; + case (strtolower(ProjectType::Fractal->name)): + $filesToGenerate = collect([ + new TemplateFile(data: 'fractal/.gitignore', name: '.gitignore'), + new TemplateFile(data: 'fractal/justfile', name: 'justfile'), + ]); + + if (self::isDocker($configurationData)) { + $filesToGenerate->push(new TemplateFile(data: 'fractal/.env.example', name: '.env.example')); + $filesToGenerate->push(new TemplateFile(data: 'fractal/.dockerignore', name: '.dockerignore')); + $filesToGenerate->push(new TemplateFile(data: 'fractal/.hadolint.yaml', name: '.hadolint.yaml')); + $filesToGenerate->push(new TemplateFile(data: 'fractal/.yarnrc', name: '.yarnrc')); + $filesToGenerate->push(new TemplateFile(data: 'fractal/Dockerfile', name: 'Dockerfile')); + $filesToGenerate->push(new TemplateFile(data: 'fractal/docker-compose.yaml', name: 'docker-compose.yaml')); + } elseif (self::isFlake($configurationData)) { + $filesToGenerate->push(new TemplateFile(data: 'fractal/.envrc', name: '.envrc')); + $filesToGenerate->push(new TemplateFile(data: 'fractal/flake.nix', name: 'flake.nix')); + } + break; + case (strtolower(ProjectType::Drupal->name)): $filesToGenerate = collect([ new TemplateFile(data: 'drupal/.dockerignore', name: '.dockerignore'), @@ -76,9 +98,6 @@ final class CreateListOfFilesToGenerate return $next([$configurationData, $configurationDataDto, $filesToGenerate]); } - $isDocker = static::isDocker($configurationData); - $isFlake = static::isFlake($configurationData); - if ($isDocker) { $filesToGenerate->push(new TemplateFile(data: 'common/.dockerignore', name: '.dockerignore')); $filesToGenerate->push(new TemplateFile(data: 'common/.hadolint.yaml', name: '.hadolint.yaml')); @@ -121,13 +140,6 @@ final class CreateListOfFilesToGenerate } } - if (static::isTypeScript(Arr::get($configurationData, 'language'))) { - if ($isDocker) { - $filesToGenerate[] = new TemplateFile(data: 'typescript/.yarnrc', name: '.yarnrc'); - $filesToGenerate[] = new TemplateFile(data: 'typescript/Dockerfile', name: 'Dockerfile'); - } - } - if (static::isCaddy(Arr::get($configurationData, 'web.type'))) { $filesToGenerate[] = new TemplateFile( data: 'web/caddy/Caddyfile', diff --git a/src/DataTransferObject/Config.php b/src/DataTransferObject/Config.php index 17d5b12..95b1f5f 100644 --- a/src/DataTransferObject/Config.php +++ b/src/DataTransferObject/Config.php @@ -46,7 +46,7 @@ final class Config )] public array $experimental; - #[Assert\Choice(choices: ['php', 'typescript'])] + #[Assert\Choice(choices: ['javascript', 'php', 'typescript'])] #[Assert\NotBlank] public string $language; diff --git a/src/Enum/ProjectType.php b/src/Enum/ProjectType.php index f51c7e2..9365ce9 100644 --- a/src/Enum/ProjectType.php +++ b/src/Enum/ProjectType.php @@ -8,4 +8,5 @@ enum ProjectType { case Astro; case Drupal; + case Fractal; } diff --git a/templates/fractal/.dockerignore.twig b/templates/fractal/.dockerignore.twig new file mode 100644 index 0000000..7e47535 --- /dev/null +++ b/templates/fractal/.dockerignore.twig @@ -0,0 +1,3 @@ +{{ managedText|raw }} + +README.md diff --git a/templates/fractal/.env.example.twig b/templates/fractal/.env.example.twig new file mode 100644 index 0000000..93d3339 --- /dev/null +++ b/templates/fractal/.env.example.twig @@ -0,0 +1,8 @@ +# {{ managedText|raw }} + +export DOCKER_UID=1000 + +export COMPOSE_PROJECT_NAME={{ name }} +export COMPOSE_PROFILES=node + +export DOCKER_WEB_VOLUME=.:{{ project_root }} diff --git a/templates/fractal/.envrc.twig b/templates/fractal/.envrc.twig new file mode 100644 index 0000000..cff5673 --- /dev/null +++ b/templates/fractal/.envrc.twig @@ -0,0 +1,3 @@ +# {{ managedText|raw }} + +use flake diff --git a/templates/fractal/.gitignore.twig b/templates/fractal/.gitignore.twig new file mode 100644 index 0000000..c6cf6e0 --- /dev/null +++ b/templates/fractal/.gitignore.twig @@ -0,0 +1,8 @@ +# {{ managedText | raw }} + +node_modules + +{% if flake is not defined %} +.env +docker-compose.override.yaml +{% endif %} diff --git a/templates/fractal/.hadolint.yaml.twig b/templates/fractal/.hadolint.yaml.twig new file mode 100644 index 0000000..d87bf88 --- /dev/null +++ b/templates/fractal/.hadolint.yaml.twig @@ -0,0 +1,2 @@ +ignore: + - DL3059 diff --git a/templates/fractal/.yarnrc.twig b/templates/fractal/.yarnrc.twig new file mode 100644 index 0000000..ad1af28 --- /dev/null +++ b/templates/fractal/.yarnrc.twig @@ -0,0 +1,3 @@ +# {{ managedText|raw }} + +--modules-folder /node_modules diff --git a/templates/fractal/Dockerfile.twig b/templates/fractal/Dockerfile.twig new file mode 100644 index 0000000..fc5bf8f --- /dev/null +++ b/templates/fractal/Dockerfile.twig @@ -0,0 +1,20 @@ +FROM node:{{ node.version }} AS base + +WORKDIR {{ project_root }} + +RUN mkdir /node_modules \ + && chown node:node -R {{ project_root }} /node_modules + +COPY --chown=node:node package*.json *yarn* {{ project_root }} + +USER node + +################################################################################ + +FROM base AS build + +RUN yarn install --frozen-lockfile + +COPY --chown=node:node . . + +CMD ["bash"] diff --git a/templates/fractal/docker-compose.yaml.twig b/templates/fractal/docker-compose.yaml.twig new file mode 100644 index 0000000..228cd29 --- /dev/null +++ b/templates/fractal/docker-compose.yaml.twig @@ -0,0 +1,57 @@ +# {{ 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:-./:{{ project_root }}}" + 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 %} + + node: + <<: [*default-proxy, *default-app] + build: + context: . + target: build + volumes: + - .:{{ project_root }} + profiles: [node] + +networks: + web: + external: true + name: traefik_proxy diff --git a/templates/fractal/flake.nix.twig b/templates/fractal/flake.nix.twig new file mode 100644 index 0000000..ba5eff8 --- /dev/null +++ b/templates/fractal/flake.nix.twig @@ -0,0 +1,25 @@ +# {{ managedText|raw }} + +{ + inputs = { + devshell.url = "github:numtide/devshell"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = inputs@{ flake-parts, ... }: + flake-parts.lib.mkFlake { inherit inputs; } { + imports = [ inputs.devshell.flakeModule ]; + + systems = [ "x86_64-linux" ]; + + perSystem = { config, self', inputs', pkgs, system, ... }: { + devshells.default = { + packages = with pkgs; [ +{% for package in flake.devshell.packages %} + "{{ package }}" +{% endfor %} + ]; + }; + }; + }; +} diff --git a/templates/fractal/justfile.twig b/templates/fractal/justfile.twig new file mode 100644 index 0000000..b3b8caa --- /dev/null +++ b/templates/fractal/justfile.twig @@ -0,0 +1,82 @@ +# {{ managedText | raw }} + +{% set isFlake = flake is defined %} + +default: + @just --list + +# Start the project +start: +{% if not isFlake %} + cp -v --no-clobber .env.example .env + docker compose up -d +{% else %} + yarn dev +{% endif %} + +{% if not isFlake %} +# Stop the project +stop: + docker compose down +{% endif %} + +yarn *args: +{% if isFlake %} + {{ "just _exec yarn {{ args }}" | raw }} +{% else %} + {{ "just _exec node yarn {{ args }}" | raw }} +{% endif %} + +fractal *args: + {{ "just yarn fractal {{ args }}" | raw }} + +clean: + rm -fr build + +build *args: + {{ "just fractal build {{ args }}" | raw }} + +sync: clean build + #!/usr/bin/env bash + set -eux + aws s3 sync "build/." s3://"${BUCKET_NAME}" \ + --acl "public-read" \ + --cache-control max-age=3600 + +# Enable or disable Git hooks +git-hooks command: + #!/usr/bin/env bash + set -euo pipefail + + case "{{ '{{ command }}'|raw }}" in + "on") + echo "Enabling Git hooks..." + git config core.hooksPath .githooks + ;; + "off") + echo "Disabling Git hooks..." + git config --unset core.hooksPath + ;; + *) + echo "Error: Invalid argument. Must be either 'on' or 'off'" + ;; + esac + +_exec +args: +{% if isFlake %} + {{ "nix develop --command {{ args }}" | raw }} +{% else %} + {{ "docker compose exec -T {{ args }}" | raw }} +{% endif %} + +{% if not isFlake %} +_run service command *args: + docker compose run \ + --entrypoint {{ "{{ command }}"|raw }} \ + --no-deps \ + --rm \ + -T \ + {{ "{{ service }} {{ args }}"|raw }} +{% endif %} + +# vim: ft=just