diff --git a/_twig/docker-compose.yml/application.yml.twig b/_twig/docker-compose.yml/application.yml.twig new file mode 100644 index 00000000..bf8fad4f --- /dev/null +++ b/_twig/docker-compose.yml/application.yml.twig @@ -0,0 +1,62 @@ +{% set blocks = '_twig/docker-compose.yml/' %} +{% set dockersync = false %} +{% if @('host.os') == 'darwin' and @('docker-sync') == 'yes' %} +{% set dockersync = true %} +{% endif %} + + console: +{% if @('app.build') == 'dynamic' %} + build: + context: ../ + dockerfile: .my127ws/docker/image/console/Dockerfile + entrypoint: /entrypoint.dynamic.sh + volumes: + - {{ (dockersync) ? @('workspace.name') ~ '-sync:/app:nocopy' : '../:/app:delegated' }} + - ./application:/home/build/application + - ./docker/image/console/root/lib/task:/lib/task +{% else %} + image: {{ @('docker.repository') ~ ':' ~ @('app.version') ~ '-console' }} +{% endif %} + labels: + - traefik.enable=false + environment: &APP_ENV_VARS +{% include blocks ~ 'environment.yml.twig' %} + networks: + - private + + nginx: +{% if @('app.build') == 'dynamic' %} + build: docker/image/nginx + volumes: + - {{ (dockersync) ? @('workspace.name') ~ '-sync:/app:nocopy' : '../:/app:delegated' }} +{% else %} + image: {{ @('docker.repository') ~ ':' ~ @('app.version') ~ '-nginx' }} +{% endif %} + labels: + - traefik.backend=${APP_NAME} + - traefik.frontend.rule=Host:${APP_HOST} + - traefik.docker.network=my127ws + - traefik.port=80 + links: + - php-fpm:php-fpm + networks: + private: + aliases: + - {{ @('hostname') }} + shared: {} + + php-fpm: +{% if @('app.build') == 'dynamic' %} + build: docker/image/php-fpm + entrypoint: /entrypoint.dynamic.sh + volumes: + - {{ (dockersync) ? @('workspace.name') ~ '-sync:/app:nocopy' : '../:/app:delegated' }} +{% else %} + image: {{ @('docker.repository') ~ ':' ~ @('app.version') ~ '-php-fpm' }} +{% endif %} + labels: + - traefik.enable=false + networks: + - private + environment: + <<: *APP_ENV_VARS diff --git a/_twig/docker-compose.yml/service/chrome.yml.twig b/_twig/docker-compose.yml/service/chrome.yml.twig new file mode 100644 index 00000000..c8a1c813 --- /dev/null +++ b/_twig/docker-compose.yml/service/chrome.yml.twig @@ -0,0 +1,7 @@ + chrome: + image: yukinying/chrome-headless-browser:latest + command: ["--no-sandbox", "--disable-gpu", "--headless", "--disable-dev-shm-usage", "--remote-debugging-address=0.0.0.0", "--remote-debugging-port=9222", "--user-data-dir=/data"] + labels: + - traefik.enable=false + networks: + - private diff --git a/_twig/docker-compose.yml/service/memcached.yml.twig b/_twig/docker-compose.yml/service/memcached.yml.twig new file mode 100644 index 00000000..f4116b00 --- /dev/null +++ b/_twig/docker-compose.yml/service/memcached.yml.twig @@ -0,0 +1,6 @@ + memcached: + image: memcached:1-alpine + labels: + - traefik.enable=false + networks: + - private diff --git a/_twig/docker-compose.yml/service/mysql.yml.twig b/_twig/docker-compose.yml/service/mysql.yml.twig new file mode 100644 index 00000000..5294d5d8 --- /dev/null +++ b/_twig/docker-compose.yml/service/mysql.yml.twig @@ -0,0 +1,13 @@ + mysql: + image: mysql:5.7 + labels: + - traefik.enable=false + environment: + - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASS} + - MYSQL_DATABASE=${DB_NAME} + - MYSQL_USER=${DB_USER} + - MYSQL_PASSWORD=${DB_PASS} + networks: + - private + ports: + - 3306 diff --git a/_twig/docker-compose.yml/service/redis-session.yml.twig b/_twig/docker-compose.yml/service/redis-session.yml.twig new file mode 100644 index 00000000..bff97a5b --- /dev/null +++ b/_twig/docker-compose.yml/service/redis-session.yml.twig @@ -0,0 +1,8 @@ + redis-session: + image: redis:4-alpine + # 1GB; evict key that would expire soonest + command: redis-server --maxmemory 1073742000 --maxmemory-policy volatile-ttl + labels: + - traefik.enable=false + networks: + - private diff --git a/_twig/docker-compose.yml/service/redis.yml.twig b/_twig/docker-compose.yml/service/redis.yml.twig new file mode 100644 index 00000000..d8a0519c --- /dev/null +++ b/_twig/docker-compose.yml/service/redis.yml.twig @@ -0,0 +1,8 @@ + redis: + image: redis:4-alpine + # 1GB; evict any least recently used key even if they don't have a TTL + command: redis-server --maxmemory 1073742000 --maxmemory-policy allkeys-lru + labels: + - traefik.enable=false + networks: + - private diff --git a/application/overlay/.dockerignore.twig b/application/overlay/.dockerignore.twig new file mode 100644 index 00000000..96c90adc --- /dev/null +++ b/application/overlay/.dockerignore.twig @@ -0,0 +1,8 @@ +{% set build = @('app.build') %} +{% set blocks = 'application/overlay/_twig/.dockerignore/' %} + +{% if build == 'dynamic' %} +{% include blocks ~ 'dynamic.twig' %} +{% else %} +{% include blocks ~ 'static.twig' %} +{% endif %} diff --git a/application/overlay/Jenkinsfile.twig b/application/overlay/Jenkinsfile.twig new file mode 100644 index 00000000..8d4fe42a --- /dev/null +++ b/application/overlay/Jenkinsfile.twig @@ -0,0 +1,25 @@ +pipeline { + agent { label "my127ws" } + environment { + MY127WS_KEY = credentials('{{ @('workspace.name') }}-my127ws-key') + MY127WS_ENV = "pipeline" + } + stages { + stage('Build') { + steps { sh 'ws install' } + } + stage('Test') { + parallel { + stage('quality') { steps { sh 'ws exec composer test-quality' } } + stage('unit') { steps { sh 'ws exec composer test-unit' } } + stage('acceptance') { steps { sh 'ws exec composer test-acceptance' } } + } + } + } + post { + always { + sh 'ws destroy' + cleanWs() + } + } +} diff --git a/application/overlay/_twig/.dockerignore/dynamic.twig b/application/overlay/_twig/.dockerignore/dynamic.twig new file mode 100644 index 00000000..4ebb7d2c --- /dev/null +++ b/application/overlay/_twig/.dockerignore/dynamic.twig @@ -0,0 +1,2 @@ +* +!.my127ws diff --git a/application/overlay/_twig/.dockerignore/static.twig b/application/overlay/_twig/.dockerignore/static.twig new file mode 100644 index 00000000..c007eac9 --- /dev/null +++ b/application/overlay/_twig/.dockerignore/static.twig @@ -0,0 +1 @@ +# no need for exclusions for now diff --git a/application/overlay/auth.json.twig b/application/overlay/auth.json.twig new file mode 100644 index 00000000..0731d871 --- /dev/null +++ b/application/overlay/auth.json.twig @@ -0,0 +1,15 @@ +{ + "http-basic": { + {% for repo in @('composer.auth.basic') %} + "{{ repo.path }}": { + "username": "{{ repo.username }}", + "password": "{{ repo.password }}" + }{% if not loop.last %},{% endif %} + {% endfor %} + }, + "github-oauth": { + {% if @('composer.auth.github') %} + "github.com": "{{ @('composer.auth.github') }}" + {% endif %} + } +} diff --git a/docker-compose.yml.twig b/docker-compose.yml.twig new file mode 100644 index 00000000..ee7fe0db --- /dev/null +++ b/docker-compose.yml.twig @@ -0,0 +1,22 @@ +{% set blocks = '_twig/docker-compose.yml/' %} +{% set dockersync = false %} +{% if @('host.os') == 'darwin' and @('docker-sync') == 'yes' %} +{% set dockersync = true %} +{% endif %} +version: '3' +services: +{% include blocks ~ 'application.yml.twig' %} +{% for service in @('app.services') %} +{% include blocks ~ 'service/' ~ service ~ '.yml.twig' %} +{% endfor %} +networks: + private: + external: false + shared: + external: + name: my127ws +{% if dockersync %} +volumes: + {{ @('workspace.name') }}-sync: + external: true +{% endif %} diff --git a/docker-sync.yml.twig b/docker-sync.yml.twig new file mode 100644 index 00000000..c3a5f1a0 --- /dev/null +++ b/docker-sync.yml.twig @@ -0,0 +1,16 @@ +version: '2' +options: + compose-file-path: + - .my127ws/docker-compose.yml +syncs: + {{ @('workspace.name') }}-sync: + src: ../ + sync_userid: '1000' + sync_excludes_type: BelowPath + sync_excludes: &IGNORE + - .docker-sync + - .idea + - .my127ws + - .git + - var + watch_excludes: *IGNORE diff --git a/docker/image/console/.dockerignore b/docker/image/console/.dockerignore new file mode 100644 index 00000000..cf49d54d --- /dev/null +++ b/docker/image/console/.dockerignore @@ -0,0 +1 @@ +**/*.twig diff --git a/docker/image/console/Dockerfile.twig b/docker/image/console/Dockerfile.twig new file mode 100644 index 00000000..a8386061 --- /dev/null +++ b/docker/image/console/Dockerfile.twig @@ -0,0 +1,31 @@ +FROM {{ @('docker.image.console') }} + +COPY .my127ws/docker/image/console/root / +RUN chown -R build:build /home/build + +ENV APP_MODE={{ @('app.mode') }} \ + ASSETS_DIR={{ @('assets.local') }} + +{% if @('node.version') is not null %} +USER build +RUN . /home/build/.nvm/nvm.sh \ + && nvm install {{ @('node.version') }} \ + && nvm use {{ @('node.version') }} \ + && nvm alias default {{ @('node.version') }} \ + && npm install -g yarn +USER root +{% endif %} + +{% if @('app.build') == 'static' %} +RUN chown build:build /app +COPY --chown=build:build .my127ws/application /home/build/application +COPY --chown=build:build ./ /app +USER build +RUN app build +USER root +{% else %} +VOLUME /app +VOLUME /home/build/application +{% endif %} + +ENTRYPOINT /entrypoint.sh diff --git a/docker/image/console/root/app/.gitkeep b/docker/image/console/root/app/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docker/image/console/root/bin/app b/docker/image/console/root/bin/app new file mode 100755 index 00000000..e80527d4 --- /dev/null +++ b/docker/image/console/root/bin/app @@ -0,0 +1,18 @@ +#!/bin/bash +set -e + +main() +{ + task "$@" +} + +bootstrap() +{ + export NVM_DIR="$HOME/.nvm" + # shellcheck source=/home/build/nvm.sh + [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" + . /lib/sidekick.sh +} + +bootstrap +main "$@" diff --git a/docker/image/console/root/entrypoint.dynamic.sh b/docker/image/console/root/entrypoint.dynamic.sh new file mode 100755 index 00000000..bce09d26 --- /dev/null +++ b/docker/image/console/root/entrypoint.dynamic.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +main() +{ + source /entrypoint.sh +} + +setup_app_volume_permissions() +{ + case "$STRATEGY" in + "host-linux-normal") + usermod -u "$(stat -c '%u' /app)" build + groupmod -g "$(stat -c '%g' /app)" build + ;; + "host-osx-normal") + usermod -u 1000 build + groupmod -g 1000 build + ;; + "host-osx-dockersync") + usermod -u 1000 build + groupmod -g 1000 build + ;; + *) + exit 1 + esac + + chown build:build /app +} + +resolve_volume_mount_strategy() +{ + if [ "${HOST_OS_FAMILY}" = "linux" ]; then + STRATEGY="host-linux-normal" + elif [ "${HOST_OS_FAMILY}" = "darwin" ]; then + if (mount | grep "/app type fuse.osxfs") &2>1 > /dev/null; then + STRATEGY="host-osx-normal" + elif (mount | grep "/app type ext4") &2>1 > /dev/null; then + STRATEGY="host-osx-dockersync" + else + exit 1 + fi + else + exit 1 + fi +} + +bootstrap() +{ + resolve_volume_mount_strategy + setup_app_volume_permissions +} + +bootstrap +main diff --git a/docker/image/console/root/entrypoint.sh b/docker/image/console/root/entrypoint.sh new file mode 100755 index 00000000..1bbbb9c7 --- /dev/null +++ b/docker/image/console/root/entrypoint.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +main() +{ + su - build + sh -c 'while sleep 3600; do :; done' +} + +setup_app_networking() +{ + # make linux consistent with docker-for-mac + if [ "${HOST_OS_FAMILY}" = "linux" ]; then + DOCKER_INTERNAL_HOST="host.docker.internal" + if ! grep $DOCKER_INTERNAL_HOST /etc/hosts > /dev/null ; then + DOCKER_INTERNAL_IP=$(/sbin/ip route|awk '/default/ { print $3 }') + echo -e "$DOCKER_INTERNAL_IP $DOCKER_INTERNAL_HOST" | tee -a /etc/hosts > /dev/null + fi + fi +} + +bootstrap() +{ + setup_app_networking +} + +bootstrap +main diff --git a/docker/image/console/root/home/build/.my.cnf b/docker/image/console/root/home/build/.my.cnf new file mode 100644 index 00000000..76ebd185 --- /dev/null +++ b/docker/image/console/root/home/build/.my.cnf @@ -0,0 +1,3 @@ +[client] +host=mysql +user=root diff --git a/docker/image/console/root/lib/sidekick.sh b/docker/image/console/root/lib/sidekick.sh new file mode 100644 index 00000000..a9667193 --- /dev/null +++ b/docker/image/console/root/lib/sidekick.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +VERBOSE="no" + +RUN_CWD="" + +INDICATOR_RUNNING="34m" +INDICATOR_SUCCESS="32m" +INDICATOR_ERROR="31m" +INDICATOR_PASSTHRU="37m" + +TASKS="/lib/task" + +task() +{ + local task_file="${TASKS}/${1//:/\/}.sh" + local task_name="task_${1//:/_}" + + declare -F "$task_name" &>/dev/null || source "$task_file" + + shift + + $task_name "$@" +} + +prompt() +{ + if [ "${RUN_CWD}" != "$(pwd)" ]; then + RUN_CWD="$(pwd)" + echo -e "\\033[1m[\\033[0mdocker(console):$(pwd)\\033[1m]:\\033[0m" + fi +} + +run() +{ + local COMMAND="$*" + if [ "$VERBOSE" = "no" ]; then + prompt + + echo " > ${COMMAND[*]}" + setCommandIndicator $INDICATOR_RUNNING + + if ! bash -c "${COMMAND[@]}" > /tmp/my127ws-stdout.txt 2> /tmp/my127ws-stderr.txt; then + setCommandIndicator $INDICATOR_ERROR + + cat /tmp/my127ws-stderr.txt + + echo "----------------------------------" + echo "Full Logs :-" + echo " stdout: /tmp/my127ws-stdout.txt" + echo " stdout: /tmp/my127ws-stderr.txt" + + exit 1 + else + setCommandIndicator $INDICATOR_SUCCESS + fi + else + passthru "${COMMAND[@]}" + fi +} + +passthru() +{ + prompt + + echo -e "\\033[${INDICATOR_PASSTHRU}■\\033[0m > $*" + bash -c "$@" + + if [ "$?" != "0" ]; then + exit 1 + fi +} + +setCommandIndicator() +{ + echo -ne "\\033[1A"; + echo -ne "\\033[$1" + echo -n "■" + echo -ne "\\033[0m" + echo -ne "\\033[1E"; +} diff --git a/docker/image/console/root/lib/task/assets/apply.sh b/docker/image/console/root/lib/task/assets/apply.sh new file mode 100644 index 00000000..d1aa30f9 --- /dev/null +++ b/docker/image/console/root/lib/task/assets/apply.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +function task_assets_apply() +{ + local ASSETS_DIR="${ASSETS_DIR:-tools/assets/development}" + + SQL="SELECT IF (COUNT(*) = 0, 'no', 'yes') FROM information_schema.tables WHERE table_schema = '$DB_NAME';" + IS_DATABASE_APPLIED="$(mysql -ss -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" -e "$SQL")" + + if [ "$IS_DATABASE_APPLIED" = "no" ]; then + local DATABASE_FILE="/app/${ASSETS_DIR}/${DB_NAME}.sql.gz" + if [ ! -f "$DATABASE_FILE" ]; then + DATABASE_FILE="$(find "/app/${ASSETS_DIR}/" -maxdepth 1 -name "${DB_NAME}*.sql.gz" -print | head -n1)" + fi + + if [ -f "$DATABASE_FILE" ]; then + run "zcat $DATABASE_FILE | mysql -h $DB_HOST -u root -p$DB_ROOT_PASS $DB_NAME" + else + task "install" + fi + fi + + for file in "/app/${ASSETS_DIR}/"*.files.{tgz,tar.gz}; do + [ -f "$file" ] || continue + run "tar -xvf ${file} -C /app" + done +} diff --git a/docker/image/console/root/lib/task/assets/dump.sh b/docker/image/console/root/lib/task/assets/dump.sh new file mode 100644 index 00000000..de377bcd --- /dev/null +++ b/docker/image/console/root/lib/task/assets/dump.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +function task_assets_dump() +{ + local ASSETS_DIR="${ASSETS_DIR:-tools/assets/development}" + + if [ ! -d "/app/${ASSETS_DIR}" ]; then + run "mkdir -p /app/${ASSETS_DIR}" + fi + + run "mysqldump -h ${DB_HOST} -u ${DB_USER} -p${DB_PASS} ${DB_NAME} | gzip > /app/${ASSETS_DIR}/${DB_NAME}.sql.gz" +} diff --git a/docker/image/console/root/lib/task/build.sh b/docker/image/console/root/lib/task/build.sh new file mode 100644 index 00000000..73b09622 --- /dev/null +++ b/docker/image/console/root/lib/task/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +function task_build() +{ + if [ ! -f /app/composer.json ]; then + task "skeleton:apply" + fi + + task "overlay:apply" + + task "build:backend" + task "build:frontend" +} diff --git a/docker/image/console/root/lib/task/build/backend.sh.twig b/docker/image/console/root/lib/task/build/backend.sh.twig new file mode 100644 index 00000000..418fa623 --- /dev/null +++ b/docker/image/console/root/lib/task/build/backend.sh.twig @@ -0,0 +1,15 @@ +#!/bin/bash + +function task_build_backend() +{( + cd {{ @('backend.path') }} + + if [ ! {{ @('backend.build.when')|raw }} ]; then + return 0; + fi + + {% for step in @('backend.build.steps') -%} + {{ step|raw }} + {% endfor %} + +)} diff --git a/docker/image/console/root/lib/task/build/frontend.sh.twig b/docker/image/console/root/lib/task/build/frontend.sh.twig new file mode 100644 index 00000000..deff49a4 --- /dev/null +++ b/docker/image/console/root/lib/task/build/frontend.sh.twig @@ -0,0 +1,15 @@ +#!/bin/bash + +function task_build_frontend() +{( + cd {{ @('frontend.path') }} + + if [ ! {{ @('frontend.build.when')|raw }} ]; then + return 0; + fi + + {% for step in @('frontend.build.steps') -%} + {{ step|raw }} + {% endfor %} + +)} diff --git a/docker/image/console/root/lib/task/composer/install.sh b/docker/image/console/root/lib/task/composer/install.sh new file mode 100644 index 00000000..483ee213 --- /dev/null +++ b/docker/image/console/root/lib/task/composer/install.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +function task_composer_install() +{ + if [ "$APP_MODE" = "production" ]; then + passthru "composer install --no-interaction --optimize-autoloader" + else + passthru "composer install --no-interaction" + fi +} diff --git a/docker/image/console/root/lib/task/init.sh.twig b/docker/image/console/root/lib/task/init.sh.twig new file mode 100644 index 00000000..ed61e7c0 --- /dev/null +++ b/docker/image/console/root/lib/task/init.sh.twig @@ -0,0 +1,13 @@ +#!/bin/bash + +function task_init() +{ + task "mysql:available" + task "assets:apply" + + {% for step in @('backend.init.steps') -%} + {{ step|raw }} + {% endfor %} + + task "welcome" +} diff --git a/docker/image/console/root/lib/task/install.sh.twig b/docker/image/console/root/lib/task/install.sh.twig new file mode 100644 index 00000000..72f0e138 --- /dev/null +++ b/docker/image/console/root/lib/task/install.sh.twig @@ -0,0 +1,11 @@ +#!/bin/bash + +function task_install() +{ + task "mysql:available" + + {% for step in @('backend.install.steps') -%} + {{ step|raw }} + {% endfor %} + +} diff --git a/docker/image/console/root/lib/task/mysql/available.sh b/docker/image/console/root/lib/task/mysql/available.sh new file mode 100644 index 00000000..69d39ff9 --- /dev/null +++ b/docker/image/console/root/lib/task/mysql/available.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +function task_mysql_available() +{ + local counter=0 + + while [ ! "$(mysqladmin -h "$DB_HOST" -u root -p"$DB_ROOT_PASS" ping 2> /dev/null)" ]; do + + if (( counter > 30 )); then + (>&2 echo "timeout while waiting on mysql to become available") + exit 1 + fi + + sleep 1 + ((++counter)) + done +} diff --git a/docker/image/console/root/lib/task/overlay/apply.sh b/docker/image/console/root/lib/task/overlay/apply.sh new file mode 100644 index 00000000..8dc36389 --- /dev/null +++ b/docker/image/console/root/lib/task/overlay/apply.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +function task_overlay_apply() +{ + run "rsync --exclude='*.twig' --exclude='_twig' -a /home/build/application/overlay/ /app/" +} diff --git a/docker/image/console/root/lib/task/skeleton/apply.sh b/docker/image/console/root/lib/task/skeleton/apply.sh new file mode 100644 index 00000000..c256f9ee --- /dev/null +++ b/docker/image/console/root/lib/task/skeleton/apply.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +function task_skeleton_apply() +{ + run "rsync --exclude='*.twig' --exclude='_twig' -a /home/build/application/skeleton/ /app/" +} diff --git a/docker/image/console/root/lib/task/welcome.sh b/docker/image/console/root/lib/task/welcome.sh new file mode 100644 index 00000000..17e3188d --- /dev/null +++ b/docker/image/console/root/lib/task/welcome.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +function task_welcome() +{ + echo "" + echo "Welcome!" + echo "--------" + echo "URL: https://${APP_HOST}" + echo "Admin: /admin" + echo " Username: admin" + echo " Password: admin123" + echo "" +} diff --git a/docker/image/console/root/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini.twig b/docker/image/console/root/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini.twig new file mode 100644 index 00000000..858a33ad --- /dev/null +++ b/docker/image/console/root/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini.twig @@ -0,0 +1,8 @@ +{% set xdebug = @('php.ext-xdebug') %} + +{% if xdebug.cli.enable == 'yes' %} + zend_extension=xdebug.so + {% for key, value in xdebug.config -%} + xdebug.{{ key }}={{ value }} + {% endfor %} +{% endif %} diff --git a/docker/image/console/root/usr/local/etc/php/php.ini.twig b/docker/image/console/root/usr/local/etc/php/php.ini.twig new file mode 100644 index 00000000..b76369c9 --- /dev/null +++ b/docker/image/console/root/usr/local/etc/php/php.ini.twig @@ -0,0 +1,10 @@ +{% for name, value in @('php.ini') %} +{{ name }} = {{ value }} +{% endfor %} +{% for name, value in @('php.cli.ini') %} +{{ name }} = {{ value }} +{% endfor %} + +; UTC for consistent logging that doesn't vary for Daylight Savings +; If you need to change it, configure your application to display dates offset from UTC. +date.timezone = UTC diff --git a/docker/image/nginx/Dockerfile.twig b/docker/image/nginx/Dockerfile.twig new file mode 100644 index 00000000..35eb35c3 --- /dev/null +++ b/docker/image/nginx/Dockerfile.twig @@ -0,0 +1,13 @@ +{% if @('app.build') == 'static' %} +FROM {{ @('docker.repository') ~ ':' ~ @('app.version') }}-console as console +{% endif %} + +FROM nginx:1.15-alpine +COPY root / + +{% if @('app.build') == 'static' %} +COPY --from=console /app /app +{% else %} +VOLUME /app +{% endif %} + diff --git a/docker/image/nginx/root/etc/nginx/snippets/certificate.conf b/docker/image/nginx/root/etc/nginx/snippets/certificate.conf new file mode 100644 index 00000000..80e7be3f --- /dev/null +++ b/docker/image/nginx/root/etc/nginx/snippets/certificate.conf @@ -0,0 +1,2 @@ +ssl_certificate /etc/ssl/certs/app.crt; +ssl_certificate_key /etc/ssl/private/app.key; diff --git a/docker/image/nginx/root/etc/nginx/snippets/ssl-params.conf b/docker/image/nginx/root/etc/nginx/snippets/ssl-params.conf new file mode 100644 index 00000000..54588782 --- /dev/null +++ b/docker/image/nginx/root/etc/nginx/snippets/ssl-params.conf @@ -0,0 +1,18 @@ +# from https://cipherli.st/ +# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html + +ssl_protocols TLSv1 TLSv1.1 TLSv1.2; +ssl_prefer_server_ciphers on; +ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; +ssl_ecdh_curve secp384r1; +ssl_session_cache shared:SSL:10m; +ssl_session_tickets off; +ssl_stapling on; +ssl_stapling_verify on; + +resolver 1.1.1.1 8.8.8.8 valid=300s; +resolver_timeout 5s; + +add_header Strict-Transport-Security "max-age=63072000; includeSubdomains"; +add_header X-Frame-Options DENY; +add_header X-Content-Type-Options nosniff; diff --git a/docker/image/nginx/root/etc/ssl/certs/app.crt.twig b/docker/image/nginx/root/etc/ssl/certs/app.crt.twig new file mode 100644 index 00000000..0d945815 --- /dev/null +++ b/docker/image/nginx/root/etc/ssl/certs/app.crt.twig @@ -0,0 +1 @@ +{{ @('tls.crt') }} \ No newline at end of file diff --git a/docker/image/nginx/root/etc/ssl/private/app.key.twig b/docker/image/nginx/root/etc/ssl/private/app.key.twig new file mode 100644 index 00000000..6bb8bcbf --- /dev/null +++ b/docker/image/nginx/root/etc/ssl/private/app.key.twig @@ -0,0 +1 @@ +{{ @('tls.key') }} \ No newline at end of file diff --git a/docker/image/php-fpm/.dockerignore b/docker/image/php-fpm/.dockerignore new file mode 100644 index 00000000..cf49d54d --- /dev/null +++ b/docker/image/php-fpm/.dockerignore @@ -0,0 +1 @@ +**/*.twig diff --git a/docker/image/php-fpm/Dockerfile.twig b/docker/image/php-fpm/Dockerfile.twig new file mode 100644 index 00000000..5f3e7375 --- /dev/null +++ b/docker/image/php-fpm/Dockerfile.twig @@ -0,0 +1,15 @@ +{% if @('app.build') == 'static' %} +FROM {{ @('docker.repository') ~ ':' ~ @('app.version') }}-console as console +{% endif %} + +FROM {{ @('docker.image.php-fpm') }} +WORKDIR /app +COPY root / + +{% if @('app.build') == 'static' %} +RUN chown www-data:www-data /app +COPY --from=console --chown=www-data:www-data /app /app +{% else %} +VOLUME /app +{% endif %} +ENV APP_MODE {{ @('app.mode') }} diff --git a/docker/image/php-fpm/root/app/.gitkeep b/docker/image/php-fpm/root/app/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docker/image/php-fpm/root/entrypoint.dynamic.sh b/docker/image/php-fpm/root/entrypoint.dynamic.sh new file mode 100755 index 00000000..71bcfc60 --- /dev/null +++ b/docker/image/php-fpm/root/entrypoint.dynamic.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +main() +{ + source /entrypoint.sh +} + +setup_app_networking() +{ + # make linux consistent with docker-for-mac + if [ "${HOST_OS_FAMILY}" = "linux" ]; then + DOCKER_INTERNAL_HOST="host.docker.internal" + if ! grep $DOCKER_INTERNAL_HOST /etc/hosts > /dev/null ; then + DOCKER_INTERNAL_IP=$(/sbin/ip route|awk '/default/ { print $3 }') + echo -e "$DOCKER_INTERNAL_IP $DOCKER_INTERNAL_HOST" | tee -a /etc/hosts > /dev/null + fi + fi +} + +setup_app_volume_permissions() +{ + case "$STRATEGY" in + "host-linux-normal") + usermod -u "$(stat -c '%u' /app)" www-data + groupmod -g "$(stat -c '%g' /app)" www-data + ;; + "host-osx-normal") + usermod -u 1000 www-data + groupmod -g 1000 www-data + ;; + "host-osx-dockersync") + usermod -u 1000 www-data + groupmod -g 1000 www-data + ;; + *) + exit 1 + esac +} + +resolve_volume_mount_strategy() +{ + if [ "${HOST_OS_FAMILY}" = "linux" ]; then + STRATEGY="host-linux-normal" + elif [ "${HOST_OS_FAMILY}" = "darwin" ]; then + if (mount | grep "/app type fuse.osxfs") &2>1 > /dev/null; then + STRATEGY="host-osx-normal" + elif (mount | grep "/app type ext4") &2>1 > /dev/null; then + STRATEGY="host-osx-dockersync" + else + exit 1 + fi + else + exit 1 + fi +} + +bootstrap() +{ + resolve_volume_mount_strategy + setup_app_volume_permissions + setup_app_networking +} + +bootstrap +main diff --git a/docker/image/php-fpm/root/entrypoint.sh b/docker/image/php-fpm/root/entrypoint.sh new file mode 100755 index 00000000..7a3cc9c9 --- /dev/null +++ b/docker/image/php-fpm/root/entrypoint.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +# run +exec supervisord -c /etc/supervisor/supervisord.conf -n diff --git a/docker/image/php-fpm/root/etc/supervisor/conf.d/php-fpm.conf b/docker/image/php-fpm/root/etc/supervisor/conf.d/php-fpm.conf new file mode 100644 index 00000000..4819202a --- /dev/null +++ b/docker/image/php-fpm/root/etc/supervisor/conf.d/php-fpm.conf @@ -0,0 +1,9 @@ +[program:php-fpm] +command=docker-php-entrypoint php-fpm +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +user = root +autostart = true +autorestart = true diff --git a/docker/image/php-fpm/root/etc/supervisor/supervisord.conf b/docker/image/php-fpm/root/etc/supervisor/supervisord.conf new file mode 100644 index 00000000..6cfe17a9 --- /dev/null +++ b/docker/image/php-fpm/root/etc/supervisor/supervisord.conf @@ -0,0 +1,18 @@ +[supervisord] +nodaemon = true +logfile=/dev/stdout +logfile_maxbytes=0 +pidfile = /var/run/supervisord.pid + +[include] +files = /etc/supervisor/conf.d/*.conf + +[supervisorctl] +serverurl = unix:///var/run/supervisor.sock + +[unix_http_server] +file = /var/run/supervisor.sock +chmod = 0700 + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface diff --git a/docker/image/php-fpm/root/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini.twig b/docker/image/php-fpm/root/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini.twig new file mode 100644 index 00000000..1c319dad --- /dev/null +++ b/docker/image/php-fpm/root/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini.twig @@ -0,0 +1,8 @@ +{% set xdebug = @('php.ext-xdebug') %} + +{% if xdebug.enable == 'yes' %} + zend_extension=xdebug.so + {% for key, value in xdebug.config -%} + xdebug.{{ key }}={{ value }} + {% endfor %} +{% endif %} diff --git a/docker/image/php-fpm/root/usr/local/etc/php/php.ini.twig b/docker/image/php-fpm/root/usr/local/etc/php/php.ini.twig new file mode 100644 index 00000000..90f4ad60 --- /dev/null +++ b/docker/image/php-fpm/root/usr/local/etc/php/php.ini.twig @@ -0,0 +1,10 @@ +{% for name, value in @('php.ini') %} +{{ name }} = {{ value }} +{% endfor %} +{% for name, value in @('php.fpm.ini') %} +{{ name }} = {{ value }} +{% endfor %} + +; UTC for consistent logging that doesn't vary for Daylight Savings +; If you need to change it, configure your application to display dates offset from UTC. +date.timezone = UTC diff --git a/docs/.gitkeep b/docs/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/harness/attributes/common.yml b/harness/attributes/common.yml new file mode 100644 index 00000000..853e0cac --- /dev/null +++ b/harness/attributes/common.yml @@ -0,0 +1,137 @@ + + +attributes.default: + + app: + # build - static|dynamic + # dynamic - volumes are mounted and the build step is run once the containers have started + # static - app is copied into console, built, then the resulting build is copied into the web image + build: dynamic + + # mode - development|production + # development - additional tooling is made available and application is run in development mode + # production - leaner images with less tooling and application is run in production mode + mode: development + + services: [mysql] + + docker-sync: yes + + docker: + repository: = @("workspace.name") + image: + console: = 'my127/php:' ~ @('php.version') ~ '-fpm-stretch-console' + php-fpm: = 'my127/php:' ~ @('php.version') ~ '-fpm-stretch' + + composer: + auth: + basic: ~ + github: ~ + + backend: + path: /app + build: + when: -f "composer.json" + steps: + - task "composer:install" + install: + steps: [] + init: + steps: [] + + frontend: + path: /app + watch: npm watch + build: + when: -f "package.json" + steps: + - run "npm install" + + node: + # only set this attribute if you wish to override the supplied node version, by default + # the supplied version will be the current LTS. + version: null + + php: + version: 7.3 + cli: + ini: + memory_limit: -1 + fpm: + ini: + memory_limit: 1024M + ini: ~ + ext-xdebug: + enable: no + cli: + enable: no + config: + remote_enable: 1 + remote_autostart: 1 + remote_port: 9000 + remote_host: host.docker.internal + + assets: + remote: ="s3://"~@("aws.bucket")~"/development" + local: tools/assets/development + + database: + host: mysql + user: app + pass: app + name: app + root_pass: DV6RdNY3QcFsBk7V + + domain: my127.site + hostname: = @('namespace') ~ '.' ~ @('domain') + + tls: + key: | + -----BEGIN PRIVATE KEY----- + MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC9q3EMGDtDNKAt + CHyM1MfWUaIGsv5Zka7pfjIOKL/KvrSIVpZyyJ3lSALeRyyDDRZeYwkbkNdDJgir + FmD0vJkYifYWfGdIJmbjdm62LGyzDf79Ve8aQF0lLcedMhoCfu7+qciIYnjHdvkx + Y6Fo9CTZP7m+oSNmUjHdJD3scX4l3vodBK67Hpk+W2eEhwAxG5aFsspDnPi4L9ha + KlMps+eSn1hLLGYrmthtP2assckvdyL10hS7+OOZFmj5vxGNbQn2F4whiu06JmXL + oO8T9yd8XNN383FjREYKjrQcyJo3izvawEgrRi9mNKM9DhWuBdbYNe/cSgGfwBK6 + Kc9e8zCLAgMBAAECggEAVL6fOgoxoGuJDdX24G3KBCZhQKEFKDwBbO4nq0/lsc7X + lvspKYwdkG5Gac5fQwa78dxKG3jx1VzPDrJnC7KgrOgnfhCDjScrXYJzIQ5kWvRr + 9AFLXe1YMN5ti/zwxiC05DA0G0v0LxsnaDvdyKkdNbxVX6lbycH76ZTh3h0vgfeD + Wc8MMlRTa+ORWKoIZsm+qnNLhWQhhbmoA8LNkZqtJIOBZuyAu8vyXzrEFIhKqVzU + Jdz0S+xtgYUkoXCTgdYiqoFjlKhaIIV2Fc0vbc68ziIiu3ZtaVch7wNyftoXyjBr + hjI1GT1dr7NsQpPZ6xtqjGhIvUuVSeCSBZeeXkymAQKBgQDsxFb916gIxl3QQYPV + NiKPi3rZD5iuMTjy0937dhHWGGYlWW2GEE0XjWrmLUnGyLuxwA5kFgS0eMubbhTg + aeewHamHeN/pcJIF6HndJbqXLB148E8ux6grpQrHKpTb2RLOPkd6bAgn1SjPllCL + a/vVanevaJs8U27sKEfGND0aCwKBgQDNE7IzvD1JAUrzqzG9Lxg+NhaHQTQfW45W + cuHvESiyhc93kdufvcCTrrRRXSZOqDN26+64Ni62O/ulduq4qZmhG/lxqSz5mnpr + 2oV2Kg1C1EUC4V2B9WQoMOhvOa0esTVSm9hC4oX0kYIzl6HbVAUGe8JMXOoKTJkV + 3sAz0FbTgQKBgQC1CX+2wvIiG4NaHO4v1h/hAHajiDBnaQ2xZtzCTMpgmPFpt5Ju + QwKfcqt9ar2RuKUDyeV3E/ru/7o3k5l06qWUXWnmQz96oG+XAuZDeXjN5JZ4hc8V + 5uYo0R6HoYCHBdlCSA6hhf9Kbcuxxq65nIzH54uyXNrt6qHTAw22ePULdwKBgQCK + vp+a1ukToldGQfV1zA330Pou6dNMv9Gt9S2cY5yII3W4rKrNCUDn6ZO/VGkdYDjp + ZTft02KJEk3vpWOqKbxxvo5l8pImEPhwTbhruImeRCSojTaJPS9U7bnjvj68/CFa + UWvf3IfKbkOLijQMQmzf9Q0AQwBolWgg3sJki7iigQKBgQCf82eve3W/s/pZzKGi + WWACcZLmDTHeH2AU3ZDfFaEAKObe/cdHMgk8MGewf1IF6QDQXtaxHlM5/FKQ1ohu + uoe7Xo1R+KlrVRxKAlNQ5lfzhAAgDNaOhpgkH4cehfPrIIh9rwNMSkHDRS0DELvY + DPyRumPy7zTg5YPzzl7tM1/OPA== + -----END PRIVATE KEY----- + + crt: | + -----BEGIN CERTIFICATE----- + MIIC6zCCAdOgAwIBAgIJAI4syJyPEWAMMA0GCSqGSIb3DQEBBQUAMAwxCjAIBgNV + BAMMASowHhcNMTgwNzI0MTE1MjQ0WhcNMTkwNzI0MTE1MjQ0WjAMMQowCAYDVQQD + DAEqMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvatxDBg7QzSgLQh8 + jNTH1lGiBrL+WZGu6X4yDii/yr60iFaWcsid5UgC3kcsgw0WXmMJG5DXQyYIqxZg + 9LyZGIn2FnxnSCZm43Zutixssw3+/VXvGkBdJS3HnTIaAn7u/qnIiGJ4x3b5MWOh + aPQk2T+5vqEjZlIx3SQ97HF+Jd76HQSuux6ZPltnhIcAMRuWhbLKQ5z4uC/YWipT + KbPnkp9YSyxmK5rYbT9mrLHJL3ci9dIUu/jjmRZo+b8RjW0J9heMIYrtOiZly6Dv + E/cnfFzTd/NxY0RGCo60HMiaN4s72sBIK0YvZjSjPQ4VrgXW2DXv3EoBn8ASuinP + XvMwiwIDAQABo1AwTjAdBgNVHQ4EFgQUK4SXDSeyVYbCWr31rz2K6GLRFoYwHwYD + VR0jBBgwFoAUK4SXDSeyVYbCWr31rz2K6GLRFoYwDAYDVR0TBAUwAwEB/zANBgkq + hkiG9w0BAQUFAAOCAQEAjz2PUbdi2S+h4UB3P2UBLdgDClkiSPF+gAqfw4D82faf + M8hpMuCcd3148dejU4tFPUdLx1MASK8ucCk7rcwVtafWPYU4nMDlmZ9Zj9F2Y8KY + dVfHfTIOblTSYc90g+nTFsTchkEFOH0nRZAKhCT3HphXNTZFNIQWoqe63SJZ8LTs + 8RBO/zcoh5E31+Rm0WxKlYH4QElLp9dXAtKueWGTafh2E8Re96IS+Uig+yC3RIYJ + MWLcATwR3lSnqN2ifByic5VGWbRKkGNsh3wAWlejL2FGv8mLU1q8nLK36UcU/HzZ + ziLtpidJOJHDpyDSAxDSxcP9fJ6gssMQln92DJ/SUQ== + -----END CERTIFICATE----- diff --git a/harness/attributes/environment/local.yml b/harness/attributes/environment/local.yml new file mode 100644 index 00000000..41505a54 --- /dev/null +++ b/harness/attributes/environment/local.yml @@ -0,0 +1,6 @@ + +attributes: + app: + build: dynamic + mode: development + version: develop \ No newline at end of file diff --git a/harness/attributes/environment/pipeline.yml b/harness/attributes/environment/pipeline.yml new file mode 100644 index 00000000..c3796c91 --- /dev/null +++ b/harness/attributes/environment/pipeline.yml @@ -0,0 +1,8 @@ + +attributes: + namespace: =exec("git log -n 1 --pretty=format:'%H'") + hostname: =@('workspace.name') ~ '.' ~ @('domain') + app: + build: static + mode: production + version: =exec("git log -n 1 --pretty=format:'%H'") diff --git a/harness/config/build.yml b/harness/config/build.yml new file mode 100644 index 00000000..a39788a2 --- /dev/null +++ b/harness/config/build.yml @@ -0,0 +1,18 @@ +command('app build'): + exec: | + #!bash(workspace:/)|@ + ws app build console + ws app build php-fpm + ws app build nginx +command('app build console'): + exec: | + #!bash(workspace:/)|@ + passthru docker build -t @('docker.repository'):@('app.version')-console -f .my127ws/docker/image/console/Dockerfile . +command('app build php-fpm'): + exec: | + #!bash(harness:/docker/image/php-fpm)|@ + passthru docker build -t @('docker.repository'):@('app.version')-php-fpm . +command('app build nginx'): + exec: | + #!bash(harness:/docker/image/nginx)|@ + passthru docker build -t @('docker.repository'):@('app.version')-nginx . diff --git a/harness/config/commands.yml b/harness/config/commands.yml new file mode 100644 index 00000000..83455765 --- /dev/null +++ b/harness/config/commands.yml @@ -0,0 +1,78 @@ + +command('enable'): + env: + USE_DOCKER_SYNC: = @('host.os') == 'darwin' and @('docker-sync') == 'yes' ? 'yes':'no' + APP_BUILD: = @('app.build') + APP_MODE: = @('app.mode') + NAMESPACE: = @('namespace') + HAS_ASSETS: = @('aws.bucket') !== null ? 'yes':'no' + exec: | + #!bash(harness:/) + source harness/scripts/enable.sh + +command('disable'): + env: + USE_DOCKER_SYNC: = (@('host.os') == 'darwin' and @('docker-sync') == 'yes') ? 'yes':'no' + NAMESPACE: = @('namespace') + exec: | + #!bash(harness:/) + source harness/scripts/disable.sh + +command('destroy'): + env: + NAMESPACE: = @('namespace') + APP_BUILD: = @('app.build') + APP_VERSION: = @('app.version') + DOCKER_REPOSITORY: = @('docker.repository') + USE_DOCKER_SYNC: = (@('host.os') == 'darwin' and @('docker-sync') == 'yes') ? 'yes':'no' + exec: | + #!bash(harness:/)|@ + source harness/scripts/destroy.sh + +command('exec %'): | + #!bash(harness:/)|= + docker-compose -p ={ @('namespace') } exec -T -u build console ={ input.argument('%') } + +command('console'): | + #!bash(harness:/)|@ + passthru docker-compose -p @('namespace') exec -u build console bash + +command('db-console'): | + #!bash(harness:/)|@ + docker-compose -p @('namespace') exec console bash -c 'mysql -h"$DB_HOST" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME"' + +command('assets download'): + env: + AWS_ID: =@('aws.id') + AWS_KEY: =@('aws.key') + exec: | + #!bash(workspace:/)|@ + passthru ws.aws s3 sync @('assets.remote') @('assets.local') + +command('assets upload'): + env: + AWS_ID: =@('aws.id') + AWS_KEY: =@('aws.key') + exec: | + #!bash(workspace:/)|@ + passthru ws.aws s3 sync @('assets.local') @('assets.remote') + +command('frontend build'): + exec: | + #!bash(harness:/)|@ + docker-compose -p @('namespace') exec -u build console bash -i -c 'app build:frontend' + +command('frontend watch'): + exec: | + #!bash(harness:/)|@ + docker-compose -p @('namespace') exec -u build console bash -i -c 'cd @('frontend.path'); @('frontend.watch')' + +command('frontend console'): + exec: | + #!bash(harness:/)|@ + docker-compose -p @('namespace') exec -u build console bash -i -c 'cd @('frontend.path'); bash' + +command('port '): + exec: | + #!bash(harness:/)|= + docker port $(docker-compose -p ={@('namespace')} ps -q ={input.argument('service')}) diff --git a/harness/config/events.yml b/harness/config/events.yml new file mode 100644 index 00000000..6139a17b --- /dev/null +++ b/harness/config/events.yml @@ -0,0 +1,10 @@ + +after('harness.install'): | + #!bash + ws enable + +after('harness.refresh'): | + #!bash(harness:/)|@ + run docker-compose -p @('namespace') stop + run docker-compose -p @('namespace') pull + run docker-compose -p @('namespace') up -d --build diff --git a/harness/config/functions.yml b/harness/config/functions.yml new file mode 100644 index 00000000..0420b03d --- /dev/null +++ b/harness/config/functions.yml @@ -0,0 +1,3 @@ +function('to_yaml', [text]): | + #!php + = preg_replace('/^/m', ' ', \Symfony\Component\Yaml\Yaml::dump($text, 100, 2)); diff --git a/harness/scripts/destroy.sh b/harness/scripts/destroy.sh new file mode 100755 index 00000000..c9d90a7c --- /dev/null +++ b/harness/scripts/destroy.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +run docker-compose -p "$NAMESPACE" down --rmi local --volumes --remove-orphans + +if [[ "$USE_DOCKER_SYNC" = "yes" ]]; then + run docker-sync stop + run docker rm "${NAMESPACE}-sync" + run docker volume rm "${NAMESPACE}-sync" +fi + +if [[ "$APP_BUILD" = "static" ]]; then + run docker image rm $(docker images --filter=reference="${DOCKER_REPOSITORY}:${APP_VERSION}-*" -q) +fi + +run rm -f .flag-built diff --git a/harness/scripts/disable.sh b/harness/scripts/disable.sh new file mode 100755 index 00000000..207ecbb7 --- /dev/null +++ b/harness/scripts/disable.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +if [[ "$USE_DOCKER_SYNC" = "yes" ]]; then + run docker-sync stop +fi + +run docker-compose -p "$NAMESPACE" stop diff --git a/harness/scripts/enable.sh b/harness/scripts/enable.sh new file mode 100755 index 00000000..dace2da0 --- /dev/null +++ b/harness/scripts/enable.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +main() +{ + if [ ! -f .flag-built ]; then + + passthru docker-compose -p "$NAMESPACE" down + + if [[ "$HAS_ASSETS" = "yes" ]]; then + ws assets download + fi + + $APP_BUILD + touch .flag-built + + else + passthru docker-compose -p "$NAMESPACE" up -d + passthru docker-compose -p "$NAMESPACE" exec -T -u build console app welcome + fi + + if [[ "$APP_BUILD" = "dynamic" && "$USE_DOCKER_SYNC" = "yes" ]]; then + passthru docker-sync start + fi +} + +dynamic() +{ + # we synchronise then stop docker-sync as leaving it running during the build + # will often cause it to crash. + + if [[ "$USE_DOCKER_SYNC" = "yes" ]]; then + passthru docker-sync start + passthru docker-sync stop + fi + + passthru docker-compose -p "$NAMESPACE" pull + passthru docker-compose -p "$NAMESPACE" build --pull + passthru docker-compose -p "$NAMESPACE" up -d + + passthru docker-compose -p "$NAMESPACE" exec -T -u build console app build + passthru docker-compose -p "$NAMESPACE" exec -T -u build console app init +} + +static() +{ + ws app build + + passthru docker-compose -p "$NAMESPACE" up -d + passthru docker-compose -p "$NAMESPACE" exec -T -u build console app init +} + +main