Add boilerplate code, Docker environment, Makefile etc.

This commit is contained in:
Lexi / Zoe 2021-07-23 03:18:33 +02:00
parent 1e9d351173
commit 114a67dbe4
Signed by: binaryDiv
GPG Key ID: F8D4956E224DA232
21 changed files with 3766 additions and 0 deletions

14
.dockerignore Normal file
View File

@ -0,0 +1,14 @@
.git
# Editors
.vscode
.idea
# General
/tmp
/_tmp
# PHP
/.composer
/.phpunit.cache
/coverage

25
.drone.yml Normal file
View File

@ -0,0 +1,25 @@
---
kind: pipeline
type: docker
name: default
steps:
- name: install dependencies
image: composer
volumes:
- name: composer-cache
path: /tmp/cache
environment:
COMPOSER_CACHE_DIR: /tmp/cache
commands:
- composer install --no-progress --no-interaction
- name: run unit tests
image: php:7.3
commands:
- vendor/bin/phpunit -c phpunit.xml
volumes:
- name: composer-cache
host:
path: /tmp/drone/composer-cache

1
.env Normal file
View File

@ -0,0 +1 @@
COMPOSE_PROJECT_NAME=mail-account-admin

7
.env.develop Normal file
View File

@ -0,0 +1,7 @@
# .env.development: Environment variables for local development
# Set composer cache directory
COMPOSER_CACHE_DIR=./.composer
# Disable Twig cache
TWIG_CACHE_DIR=

13
.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
# Editors
.idea
.vscode
# General
/tmp
/_tmp
# PHP
/.composer
/.phpunit.cache
/coverage
/vendor

30
Dockerfile Normal file
View File

@ -0,0 +1,30 @@
FROM php:7.3-apache AS base
WORKDIR /var/www
RUN apt-get update && \
apt-get install -y libzip-dev unzip git && \
docker-php-ext-install pdo pdo_mysql zip
RUN a2enmod rewrite && \
sed -ri -e 's!/var/www/html!/var/www/public!g' /etc/apache2/sites-available/*.conf
COPY --from=composer /usr/bin/composer /usr/bin/composer
FROM base AS development
RUN cp $PHP_INI_DIR/php.ini-development $PHP_INI_DIR/php.ini && \
pecl install xdebug && \
docker-php-ext-enable xdebug
# TODO: production image untested
#FROM base AS production
#
#RUN cp $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini
#
#COPY vendor/ /var/www/vendor/
#COPY public/ /var/www/public/
#COPY src/ /var/www/src/
#COPY templates/ /var/www/templates/

View File

102
Makefile Normal file
View File

@ -0,0 +1,102 @@
# Current UID and GID that the containers will be started as
DOCKER_UID = "$(shell id -u):$(shell id -g)"
# Basic docker-compose command
DOCKER_COMPOSE = DOCKER_UID=$(DOCKER_UID) docker-compose
# Commands inside containers
DOCKER_RUN = $(DOCKER_COMPOSE) run --rm app
COMPOSER = $(DOCKER_RUN) composer
PHPUNIT = $(DOCKER_RUN) vendor/bin/phpunit
.PHONY: all clean \
docker-up docker-up-detached docker-down docker-restart docker-build docker-rebuild docker-purge docker-logs docker-run \
composer-install composer-install-no-dev composer-update composer-cmd \
test phpunit open-coverage
# Default target
all: docker-build composer-install docker-up
# Container management
# --------------------
# Start docker containers in foreground mode, building images if needed
docker-up:
$(DOCKER_COMPOSE) up --build
# Start docker containers in detached mode
docker-up-detached:
$(DOCKER_COMPOSE) up --build --detach
# Stop running docker containers
docker-down:
$(DOCKER_COMPOSE) down
# Restart docker containers (use `make docker-restart SERVICE=foo` to just restart a specific service)
docker-restart:
$(DOCKER_COMPOSE) restart $(SERVICE)
# Build container images without starting the containers
docker-build:
$(DOCKER_COMPOSE) build
# Rebuild docker containers from scratch (pulling base images and ignoring cache)
docker-rebuild:
$(DOCKER_COMPOSE) build --pull --no-cache
# Stop running docker containers and delete all volumes
docker-purge:
$(DOCKER_COMPOSE) down --volumes
# Show container logs (use `make docker-logs SERVICE=foo` to just select a specific service)
docker-logs:
$(DOCKER_COMPOSE) logs -f $(SERVICE) || true
# Run command in app container (e.g. `make docker-run CMD="bash"`)
docker-run:
$(DOCKER_RUN) "$(or $(CMD),bash)"
# Dependency management
# ---------------------
# Install PHP composer dependencies inside the app container
composer-install:
$(COMPOSER) install
# Install PHP composer dependencies without development dependencies like phpunit
composer-install-no-dev:
$(COMPOSER) install --no-dev
# Update PHP composer dependencies inside the app container
composer-update:
$(COMPOSER) update
# Run arbitrary composer commands inside the app container (e.g. `make composer-cmd CMD="help"`)
composer-cmd:
@test -n "$(CMD)" || (echo "Please use 'make composer-cmd CMD=\"some command\"'"; exit 1)
$(COMPOSER) $(CMD)
# Test suites
# -----------
# Run all test suites
test: phpunit
# Run phpunit tests
phpunit:
$(PHPUNIT) -c phpunit.xml --testdox
# Open HTML coverage report in $BROWSER (needs to be generated by phpunit first)
open-coverage:
$(or $(BROWSER),firefox) coverage/index.html
# Clean up
# --------
# Remove vendor directory, phpunit caches and other files that have been generated
clean: docker-down
rm -rf .composer vendor .phpunit.cache coverage

35
composer.json Normal file
View File

@ -0,0 +1,35 @@
{
"name": "0xbd/mail-account-admin",
"description": "Web UI to administrate mail server accounts. Designed for the database scheme used on 0xbd.space mail servers.",
"type": "project",
"authors": [
{
"name": "binaryDiv",
"email": "binarydiv@gmail.com"
}
],
"config": {
"optimize-autoloader": true
},
"require": {
"php": "^7.3",
"ext-pdo": "*",
"slim/slim": "^4.8",
"slim/psr7": "^1.3",
"php-di/php-di": "^6.3",
"slim/twig-view": "^3.2"
},
"require-dev": {
"phpunit/phpunit": "^9"
},
"autoload": {
"psr-4": {
"MailAccountAdmin\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\Unit\\": "tests/Unit/"
}
}
}

3321
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

14
docker-compose.yml Normal file
View File

@ -0,0 +1,14 @@
version: '3.4'
services:
app:
build:
context: .
target: development
ports:
- 8080:80
env_file:
- .env.develop
volumes:
- ./:/var/www/
user: ${DOCKER_UID}

30
phpunit.xml Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
cacheResultFile=".phpunit.cache/test-results"
executionOrder="depends,defects"
forceCoversAnnotation="true"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
failOnWarning="true"
colors="true"
verbose="true">
<testsuites>
<testsuite name="unit">
<directory suffix="Test.php">tests/Unit</directory>
</testsuite>
</testsuites>
<coverage cacheDirectory=".phpunit.cache/code-coverage" processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
<report>
<html outputDirectory="coverage/" lowUpperBound="50" highLowerBound="100"/>
<text outputFile="php://stdout" showOnlySummary="true"/>
</report>
</coverage>
</phpunit>

4
public/.htaccess Normal file
View File

@ -0,0 +1,4 @@
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]

19
public/index.php Normal file
View File

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use MailAccountAdmin\Dependencies;
use MailAccountAdmin\Middlewares;
use MailAccountAdmin\Routes;
use MailAccountAdmin\Settings;
use Slim\Factory\AppFactory;
$settings = new Settings();
$container = Dependencies::createContainer($settings);
$app = AppFactory::createFromContainer($container);
Middlewares::setMiddlewares($app);
Routes::setRoutes($app);
$app->run();

41
src/Dependencies.php Normal file
View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace MailAccountAdmin;
use DI\Container;
use MailAccountAdmin\Login\LoginController;
use Psr\Container\ContainerInterface;
use Slim\Views\Twig;
class Dependencies
{
private const SETTINGS = 'settings';
private const TWIG = 'view';
private const TWIG_TEMPLATE_DIR = __DIR__ . '/../templates';
public static function createContainer(Settings $settings): Container
{
$container = new Container();
// App settings
$container->set(self::SETTINGS, $settings);
// Twig template engine
$container->set(self::TWIG, function (ContainerInterface $c) {
/** @var Settings $settings */
$settings = $c->get(self::SETTINGS);
return Twig::create(self::TWIG_TEMPLATE_DIR, $settings->getTwigSettings());
});
// Login, registration, authentication
$container->set(LoginController::class, function (ContainerInterface $c) {
return new LoginController(
$c->get(self::TWIG)
);
});
return $container;
}
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace MailAccountAdmin\Login;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Views\Twig;
class LoginController
{
/** @var Twig */
private $view;
public function __construct(Twig $view)
{
$this->view = $view;
}
public function showLoginPage(Request $request, Response $response): Response
{
$renderData = [
];
return $this->view->render($response, 'login.html', $renderData);
}
}

15
src/Middlewares.php Normal file
View File

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace MailAccountAdmin;
use Slim\App;
use Slim\Views\TwigMiddleware;
class Middlewares
{
public static function setMiddlewares(App $app): void
{
$app->add(TwigMiddleware::createFromContainer($app));
}
}

15
src/Routes.php Normal file
View File

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace MailAccountAdmin;
use MailAccountAdmin\Login\LoginController;
use Slim\App;
class Routes
{
public static function setRoutes(App $app): void
{
$app->get('/', LoginController::class . ':showLoginPage');
}
}

16
src/Settings.php Normal file
View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace MailAccountAdmin;
class Settings
{
public function getTwigSettings(): array
{
$cacheDir = getenv('TWIG_CACHE_DIR');
return [
'cache' => !empty($cacheDir) ? $cacheDir : false,
];
}
}

19
templates/login.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>MailAccountAdmin</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <link rel="stylesheet" href=""> -->
</head>
<body>
<h1>MailAccountAdmin - Login</h1>
<b>Hello.</b>
<!-- <script src="" async defer></script> -->
</body>
</html>

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
/**
* @coversNothing
*/
final class HelloWorldTest extends TestCase
{
// TODO: Delete this file
public function testTrue(): void
{
$this->assertTrue(true);
}
}