diff --git a/.env.default b/.env.default deleted file mode 100644 index 966d206de9d4b32635b68ce1109f70e15c34d39b..0000000000000000000000000000000000000000 --- a/.env.default +++ /dev/null @@ -1,5 +0,0 @@ -APP_NAME=Alien4Friends -APP_ENV=production -APP_KEY= -APP_DEBUG=false -APP_URL=http://localhost/ diff --git a/.env.example b/.env.example new file mode 100644 index 0000000000000000000000000000000000000000..17dd2e2d357d28ae26255dfde13c52cde4d63db8 --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +APP_NAME=Alien4Friends +APP_ENV=production +APP_KEY= +APP_DEBUG=true +APP_URL=http://laravel.test + +WWWGROUP=1000 +WWWUSER=1000 diff --git a/README.md b/README.md index 208f442bbd1fc5af7a61f1b6b33f7ad0a4d43f53..a8ca74263a3cff5b518da550ea70ef3cb03b5655 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ # Aliens4friends Dashboard An expandable dashboard to filter and visualize alien4friends license statistics -## Basics/Requirements +## Local development environment + +### Basics/Requirements This project was created based on Laravel 8 & Laravel UI (Vue.js). @@ -10,40 +12,69 @@ https://laravel.com/docs/8.x/ https://laravel.com/docs/7.x/frontend Vuetify is mainly used as frontend components: https://vuetifyjs.com/ +Sail is used for local development: https://laravel.com/docs/8.x/sail + +Sail requires a running installation of Docker. -## install & run app (dev & production) +### install app & backend dependencies - sudo docker build . -t af4d -f infrastructure/docker/Dockerfile - sudo docker run -d -p [PORT]:5000 --env APP_ENV=[production|local] + cd ~ + git clone [repo-url] solda-app + cd ~/solda-app + docker run --rm -v $(pwd):/app composer install + cp .env.example .env -if 'production' is passed as APP_ENV, the app will automatically force ssl/https for all requests. This prevents delivery of resources over http if the app is running behind a load balancer that resolves the certificates itself. use 'local' to develop or use the app without valid https. default is 'production'. +### adapt .env file to your needs -the app is internally accessible via port 5000. Port mapping is done according to individual requirements. +APP_NAME=String | used as application name by many external Laravel libraries. +APP_ENV=production | currently only possible setting with corresponding effect on code. See "Useful Information/Https". +APP_KEY=App-Key | secret key used for encryption. Will be generated automatically by php artisan key:generate. +APP_DEBUG=Boolean | always false in production to avoid debug output including sensitive data. +APP_URL=http://laravel.test | current base-url. Used e.g. for mail dispatch, external libraries or by console commands as base-url. -after docker run the app is reachable via hostname:[PORT]. +WWWGROUP=1000 | laravel sail group +WWWUSER=1000 | laravel sail user -### further configuration +### start dev-environment -Docker container is based on https://hub.docker.com/r/webdevops/php-nginx + ./vendor/bin/sail up -Container & configuration details can be found @ https://dockerfile.readthedocs.io/en/latest/content/DockerImages/dockerfiles/php-nginx.html +### install & compile frontend dependencies -the configuration of the internal nginx server can be customized @ infrastructure/nginx/a4f.conf. + ./vendor/bin/sail npm install + ./vendor/bin/sail artisan key:generate + ./vendor/bin/sail npm run dev -### run/dev without shipped Dockerfile +### (optional) add dev-url to your hosts-file -feel free to use https://laravel.com/docs/8.x/homestead or https://laravel.com/docs/8.x/sail as alternative dev-environments + 127.0.0.1 laravel.test -### .env variables +The app can now be accessed at http://laravel.test. If changes are made to CSS or JS, the frontend files must be recompiled: -the app runs in docker out of the box without any additional configuration / change of these variables. -currently no access data or other sensitive data is required to operate the app. + ./vendor/bin/sail npm run dev -APP_NAME=String | used as application name by many external Laravel libraries. -APP_ENV=production | currently only possible setting with corresponding effect on code. -APP_KEY=App-Key | secret key used for encryption. Will be generated automatically by php artisan key:generate. -APP_DEBUG=Boolean | always false in production to avoid debug output including sensitive data. -APP_URL=http://laravel.test | current base-url. Used e.g. for mail dispatch, external libraries or by console commands as base-url. atm there is no use for this. +## Testing/Production Deployment +Deployment to any test or production environments is done manually via Rsync. A build environment with available Composer & Node and corresponding test or production environments are therefore required. + +### Server-Requirements +https://laravel.com/docs/8.x/deployment + +/public must be specified as the document root. It is assumed that the necessary .env files have already been configured once on the target systems. + +### Backend build + git clone [repo-url] solda-app + cd ~/solda-app + composer install --optimize-autoloader --no-dev + +### Frontend build + npm install + npm run prod + +### Publish + rsync -vzrS --exclude=".*" --exclude="node_modules" --exclude="storage" /solda-app/* [user]@[ip]:[html_path] + ssh [user]@[ip] + cd [html_path] + php artisan cache:clear ## Useful information @@ -54,3 +85,10 @@ The entire project-base was created by code generators and therefore follows the Any dependencies are installed via Composer & Npm. Corresponding dependency source code can be found in the folders /node_modules (JS/Frontend) and /vendor (PHP/Backend). Individual customisations are mainly, but not exclusively, located in the /resources (JS+CSS) and /app (PHP) folders. + +### Https/Ssl + +https assets should now be forced as soon as APP_ENV is set to production. if not, the asset() function in the blade templates takes a second parameter [bool|forceSecure]. + +* https://laravel.com/docs/8.x/requests#configuring-trusted-proxies +* https://laravel.com/docs/8.x/requests#configuring-trusted-hosts diff --git a/config/database.php b/config/database.php index 95006f11ed7758d1553754e60ff4a90e0ad95b20..b42d9b30a5463e6f1c739724d5debdc487f94748 100644 --- a/config/database.php +++ b/config/database.php @@ -37,7 +37,7 @@ return [ 'sqlite' => [ 'driver' => 'sqlite', - 'url' => env('DB_URL'), + 'url' => env('DATABASE_URL'), 'database' => env('DB_DATABASE', database_path('database.sqlite')), 'prefix' => '', 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), @@ -45,7 +45,7 @@ return [ 'mysql' => [ 'driver' => 'mysql', - 'url' => env('DB_URL'), + 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), @@ -65,7 +65,7 @@ return [ 'pgsql' => [ 'driver' => 'pgsql', - 'url' => env('DB_URL'), + 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '5432'), 'database' => env('DB_DATABASE', 'forge'), @@ -80,7 +80,7 @@ return [ 'sqlsrv' => [ 'driver' => 'sqlsrv', - 'url' => env('DB_URL'), + 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', 'localhost'), 'port' => env('DB_PORT', '1433'), 'database' => env('DB_DATABASE', 'forge'), diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..17f8bd02d605b854706f39754f2c274b76fa74c6 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,48 @@ +# For more information: https://laravel.com/docs/sail +version: '3.4' +services: + laravel.test: + build: + context: . + dockerfile: infrastructure/docker/Dockerfile + target: base + args: + WWWGROUP: '${WWWGROUP}' + image: sail-7.4/app + ports: + - '${APP_PORT:-80}:80' + environment: + WWWUSER: '${WWWUSER}' + LARAVEL_SAIL: 1 + env_file: + - .env + volumes: + - .:/var/www/html + networks: + - sail + depends_on: + - mysql + mysql: + image: 'mysql:8.0' + ports: + - '${FORWARD_DB_PORT:-3306}:3306' + environment: + MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' + MYSQL_DATABASE: '${DB_DATABASE}' + MYSQL_USER: '${DB_USERNAME}' + MYSQL_PASSWORD: '${DB_PASSWORD}' + MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' + volumes: + - 'sailmysql:/var/lib/mysql' + networks: + - sail + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"] + retries: 3 + timeout: 5s +networks: + sail: + driver: bridge +volumes: + sailmysql: + driver: local diff --git a/infrastructure/docker/Dockerfile b/infrastructure/docker/Dockerfile index 317d8e5244a68214e05242891513c3d6cc839fce..bc1891f3fcccc299062249ce3b56b8c016089fdd 100644 --- a/infrastructure/docker/Dockerfile +++ b/infrastructure/docker/Dockerfile @@ -1,62 +1,67 @@ -FROM webdevops/php-nginx:7.4-alpine -ARG APP_ENV=production - -# restore intermediate mess -USER root - -RUN apk add oniguruma-dev postgresql-dev libxml2-dev -RUN docker-php-ext-install \ - bcmath \ - ctype \ - fileinfo \ - json \ - mbstring \ - pdo_mysql \ - pdo_pgsql \ - tokenizer \ - xml - -# install build systems -COPY --from=composer:latest /usr/bin/composer /usr/bin/composer -RUN apk add --update npm - -ENV WEB_DOCUMENT_ROOT /app/public -ENV APP_ENV $APP_ENV - -WORKDIR /app - -# copy with chown to prevent slow chown bug (also known as 'now i finally survive until deployment ends' fix) -COPY --chown=application:application . . -COPY ./infrastructure/nginx/a4f.conf /opt/docker/etc/nginx/conf.d - -# do not exec composer and npm as root -USER application - -# install backend & frontend dependencies & compile -RUN composer install --no-interaction --optimize-autoloader --no-dev -RUN npm install -RUN npm run prod - -RUN cp .env.default .env - -# reload new .env -RUN php artisan config:clear - -# sessions will be invalidated @ every deployment. for our purposes this is ok. -RUN php artisan key:generate --force - -# reload new .env -RUN php artisan config:clear - -# optimizations -RUN php artisan config:cache -RUN php artisan route:cache -RUN php artisan view:cache - -# restore bash user -USER root - -# reload new .env -RUN php artisan config:clear - -EXPOSE 5000 +FROM ubuntu:20.04 as base + +LABEL maintainer="Taylor Otwell" + +ARG WWWGROUP=1000 + +WORKDIR /var/www/html + +ENV DEBIAN_FRONTEND noninteractive +ENV TZ=UTC + +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN apt-get update \ + && apt-get install -y gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python2 \ + && mkdir -p ~/.gnupg \ + && chmod 600 ~/.gnupg \ + && echo "disable-ipv6" >> ~/.gnupg/dirmngr.conf \ + && apt-key adv --homedir ~/.gnupg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E5267A6C \ + && apt-key adv --homedir ~/.gnupg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C300EE8C \ + && echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu focal main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \ + && apt-get update \ + && apt-get install -y php7.4-cli php7.4-dev \ + php7.4-pgsql php7.4-sqlite3 php7.4-gd \ + php7.4-curl php7.4-memcached \ + php7.4-imap php7.4-mysql php7.4-mbstring \ + php7.4-xml php7.4-zip php7.4-bcmath php7.4-soap \ + php7.4-intl php7.4-readline php7.4-pcov \ + php7.4-msgpack php7.4-igbinary php7.4-ldap \ + php7.4-redis \ + && php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer \ + && curl -sL https://deb.nodesource.com/setup_14.x | bash - \ + && apt-get install -y nodejs \ + && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ + && echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \ + && apt-get update \ + && apt-get install -y yarn \ + && apt-get install -y mysql-client \ + && apt-get install -y postgresql-client \ + && apt-get -y autoremove \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +RUN setcap "cap_net_bind_service=+ep" /usr/bin/php7.4 + +RUN groupadd --force -g $WWWGROUP sail && \ + useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 sail + +COPY infrastructure/docker/start-container /usr/local/bin/start-container +COPY infrastructure/docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf +COPY infrastructure/docker/php.ini /etc/php/7.4/cli/conf.d/99-sail.ini +RUN chmod +x /usr/local/bin/start-container + +ENTRYPOINT ["start-container"] + +FROM base as jenkinsci +ARG JENKINS_GROUP_ID=2000 +ARG JENKINS_USER_ID=2000 +RUN groupadd -g $JENKINS_GROUP_ID jenkins && \ + useradd -ms /bin/bash --no-user-group -g $JENKINS_GROUP_ID -u $JENKINS_USER_ID jenkins + +FROM base as build +# Use the .dockerignore file to exclude files from this COPY command +COPY . /var/www/html/ +RUN npm install && \ + composer install --optimize-autoloader --no-dev && \ + chown -R sail:$WWWGROUP /var/www/html diff --git a/infrastructure/docker/docker-compose.build.yml b/infrastructure/docker/docker-compose.build.yml new file mode 100644 index 0000000000000000000000000000000000000000..c2f446d492b107b3a8cdf01e5de1eb894c95849e --- /dev/null +++ b/infrastructure/docker/docker-compose.build.yml @@ -0,0 +1,9 @@ +version: "3.4" + +services: + app: + image: ${DOCKER_IMAGE}:${DOCKER_TAG} + build: + context: ../../ + dockerfile: infrastructure/docker/Dockerfile + target: build diff --git a/infrastructure/docker/docker-compose.run.yml b/infrastructure/docker/docker-compose.run.yml new file mode 100644 index 0000000000000000000000000000000000000000..66ffbd8bc6f5debd3009b0d15cca14f6b6751390 --- /dev/null +++ b/infrastructure/docker/docker-compose.run.yml @@ -0,0 +1,37 @@ +version: "3.4" + +services: + app: + image: ${DOCKER_IMAGE}:${DOCKER_TAG} + restart: unless-stopped + env_file: + - .env + ports: + - ${SERVER_PORT}:80 + networks: + - sail + depends_on: + - mysql + + mysql: + image: 'mysql:8.0' + env_file: + - .env + environment: + MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' + MYSQL_DATABASE: '${DB_DATABASE}' + MYSQL_USER: '${DB_USERNAME}' + MYSQL_PASSWORD: '${DB_PASSWORD}' + MYSQL_ALLOW_EMPTY_PASSWORD: 'no' + volumes: + - ../shared/var/lib/mysql:/var/lib/mysql + networks: + - sail + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"] + retries: 3 + timeout: 5s + +networks: + sail: + driver: bridge diff --git a/infrastructure/docker/php.ini b/infrastructure/docker/php.ini new file mode 100644 index 0000000000000000000000000000000000000000..66d04d5befa3da9e6960ba9a595cd67e015c6013 --- /dev/null +++ b/infrastructure/docker/php.ini @@ -0,0 +1,4 @@ +[PHP] +post_max_size = 100M +upload_max_filesize = 100M +variables_order = EGPCS diff --git a/infrastructure/docker/prod/Dockerfile b/infrastructure/docker/prod/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..dcad882b1ce06f5ef18e19b29ab0e48321762824 --- /dev/null +++ b/infrastructure/docker/prod/Dockerfile @@ -0,0 +1,32 @@ +FROM webdevops/php-nginx:7.4-alpine + +# Install Laravel framework system requirements (https://laravel.com/docs/8.x/deployment#optimizing-configuration-loading) +RUN apk add oniguruma-dev postgresql-dev libxml2-dev +RUN docker-php-ext-install \ + bcmath \ + ctype \ + fileinfo \ + json \ + mbstring \ + pdo_mysql \ + pdo_pgsql \ + tokenizer \ + xml + +# Copy Composer binary from the Composer official Docker image +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer + +ENV WEB_DOCUMENT_ROOT /app/public +ENV APP_ENV production +WORKDIR /app +COPY . . + +RUN composer install --no-interaction --optimize-autoloader --no-dev +# Optimizing Configuration loading +RUN php artisan config:cache +# Optimizing Route loading +RUN php artisan route:cache +# Optimizing View loading +RUN php artisan view:cache + +RUN chown -R application:application . diff --git a/infrastructure/docker/prod/readme.md b/infrastructure/docker/prod/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..150e9623d91559c6e9a653a38c6a9f9fee3510cc --- /dev/null +++ b/infrastructure/docker/prod/readme.md @@ -0,0 +1,3 @@ +Taken from https://www.koyeb.com/tutorials/dockerize-and-deploy-a-laravel-application-to-production + +not tested, example production container diff --git a/infrastructure/docker/start-container b/infrastructure/docker/start-container new file mode 100644 index 0000000000000000000000000000000000000000..82e9433ef9a50599fc020626b50fc12ec50a27b5 --- /dev/null +++ b/infrastructure/docker/start-container @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +if [ -n "$WWWUSER" ]; then + usermod -u "$WWWUSER" sail +fi + +if [ ! -d /.composer ]; then + mkdir /.composer +fi + +chmod -R ugo+rw /.composer + +if [ $# -gt 0 ];then + exec gosu "$WWWUSER" "$@" +else + /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf +fi diff --git a/infrastructure/docker/supervisord.conf b/infrastructure/docker/supervisord.conf new file mode 100644 index 0000000000000000000000000000000000000000..9d28479582929223c04c2b2e8fb6f597e35bf41a --- /dev/null +++ b/infrastructure/docker/supervisord.conf @@ -0,0 +1,14 @@ +[supervisord] +nodaemon=true +user=root +logfile=/var/log/supervisor/supervisord.log +pidfile=/var/run/supervisord.pid + +[program:php] +command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80 +user=sail +environment=LARAVEL_SAIL="1" +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 diff --git a/infrastructure/jenkins/ci.groovy b/infrastructure/jenkins/ci.groovy index 8debadeb30cb50b56c1ae1fd0e59a7d3923f8c90..09bf0fe86b52fec2bc3542f067460d2a5deab355 100644 --- a/infrastructure/jenkins/ci.groovy +++ b/infrastructure/jenkins/ci.groovy @@ -20,7 +20,7 @@ pipeline { stage('Backend - Test') { steps { sh """ - cp .env.default .env + cp .env.example .env composer install php artisan key:generate php artisan test --without-tty diff --git a/infrastructure/nginx/a4f.conf b/infrastructure/nginx/a4f.conf deleted file mode 100644 index 3fa203ba319badba73e93a51e418d0ec11b8551c..0000000000000000000000000000000000000000 --- a/infrastructure/nginx/a4f.conf +++ /dev/null @@ -1,34 +0,0 @@ -server { - listen 5000 default_server; - listen [::]:5000 default_server; - - server_name _; - - root /app/public; - - add_header X-Frame-Options "SAMEORIGIN"; - add_header X-Content-Type-Options "nosniff"; - - index index.php; - - charset utf-8; - - location / { - try_files $uri $uri/ /index.php?$query_string; - } - - location = /favicon.ico { access_log off; log_not_found off; } - location = /robots.txt { access_log off; log_not_found off; } - - error_page 404 /index.php; - - location ~ \.php$ { - fastcgi_pass php; - fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; - include fastcgi_params; - } - - location ~ /\.(?!well-known).* { - deny all; - } -} diff --git a/package.json b/package.json index 681004962daff2b6287f48b5e9723e68d29259e3..d9d8941baaa7132ce26fd8a10c3409ef28b57651 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "prod": "npm run production", "production": "mix --production" }, - "version": "0.8.8", + "version": "0.8.6", "author": { "name": "Alex Complojer", "email": "alex@agon-e.com" diff --git a/resources/js/components/TableDetailComponent.vue b/resources/js/components/TableDetailComponent.vue index be9bda9d427f680ad03de117489b9626324074ab..7ebd07df679c40564d0b8d910ed7a9d9551f530f 100644 --- a/resources/js/components/TableDetailComponent.vue +++ b/resources/js/components/TableDetailComponent.vue @@ -551,7 +551,6 @@ export default { }, getSourceFileRelease(source_file) { var release = ""; - if(source_file.paths) for (var a = 0; a < source_file.paths.length; a++) { const tags = source_file.paths[a].split("/"); if (tags.length >= 2) {