Skip to content

Commit

Permalink
[deployphp#2197] Created E2E testing environment
Browse files Browse the repository at this point in the history
Created docker-based end-to-end testing environment, which allows
for testing more complex scenarios.

Additionally added FunctionE2ETest class that contains test scenario
for `run` function with placeholders.

Closes deployphp#2197
  • Loading branch information
Bartlomiej Sacharski committed Oct 18, 2020
1 parent 5b615b4 commit a8c14cf
Show file tree
Hide file tree
Showing 14 changed files with 354 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.phar
phpunit.xml
.phpunit.result.cache
docker-compose.override.yml
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- Added labels and selectors support.
- Added support for placeholders in `run()` func.
- Added support for secret passing in `run()` func without outputting to logs.
- Added docker-based E2E testing environment. [#2197]

### Changed
- Refactored executor engine, up to 2x faster than before.
Expand Down Expand Up @@ -596,6 +597,7 @@
- Fixed remove of shared dir on first deploy.


[#2197]: https://github.com/deployphp/deployer/issues/2197
[#1994]: https://github.com/deployphp/deployer/issues/1994
[#1990]: https://github.com/deployphp/deployer/issues/1990
[#1989]: https://github.com/deployphp/deployer/issues/1989
Expand Down
82 changes: 82 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
FROM php:7.3-cli-alpine AS composer
RUN apk add wget
COPY ./scripts/install-composer.sh /tmp/install-composer.sh
RUN sh /tmp/install-composer.sh





FROM php:7.3-cli-alpine AS deployer
RUN apk add \
git \
openssh-client \
rsync

RUN ssh-keygen \
-q \
-b 2048 \
-t rsa \
-f ~/.ssh/id_rsa

ARG XDEBUG_VERSION=2.9.8
RUN set -eux; \
apk add --no-cache --virtual .build-deps $PHPIZE_DEPS; \
pecl install xdebug-$XDEBUG_VERSION; \
docker-php-ext-enable xdebug; \
apk del .build-deps

COPY --from=composer /tmp/composer /bin/composer
ENV E2E_ENV=1
VOLUME [ "/project" ]
WORKDIR /project





FROM php:7.3-apache AS server
RUN apt-get update && apt-get install -y \
git \
openssh-server \
sudo \
&& rm -rf /var/lib/apt/lists/*

# SSH login fix. Otherwise user is kicked off after login
RUN mkdir /run/sshd \
&& sed -i 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' /etc/pam.d/sshd

# Configure Apache to expose healthcheck & configure site to use /var/www/html/current ad document root
COPY ./conf/healthcheck.conf /etc/apache2/sites-available/healthcheck.conf
COPY ./initial-site/index.html /var/www/html/initial-site/index.html

ENV APACHE_DOCUMENT_ROOT /var/www/html/current
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/000-default.conf \
&& sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf \
&& ln -s /var/www/html/initial-site /var/www/html/current \
&& chown -R www-data:www-data /var/www/html \
&& echo "Listen 81" >> /etc/apache2/ports.conf \
&& a2enmod rewrite \
&& a2ensite healthcheck

RUN useradd \
--create-home \
deployer \
&& echo 'deployer:deployer' | chpasswd \
&& echo 'deployer ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \
&& mkdir ~deployer/.ssh \
&& touch ~deployer/.ssh/authorized_keys \
&& chown -R deployer:deployer ~deployer/.ssh \
&& chmod 700 ~deployer/.ssh \
&& chmod 600 ~deployer/.ssh/authorized_keys

COPY ./scripts/start-servers.sh /usr/local/bin/start-servers
COPY --from=composer /tmp/composer /usr/local/bin/composer
COPY --from=deployer /root/.ssh/id_rsa.pub /tmp/root_rsa.pub

RUN chmod a+x /usr/local/bin/start-servers \
&& cat /tmp/root_rsa.pub >> ~deployer/.ssh/authorized_keys \
&& rm -rf /tmp/root_rsa.pub

EXPOSE 22 80 81
CMD [ "start-servers" ]
88 changes: 88 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Deployer E2E testing environment

This directory contains an end-to-end testing environment for Deployer.

All commands mentioned in this readme, should be executed in the `docker` directory.

## Requirements

* Docker
* docker-compose

## Running tests

The E2E are started when running the `docker-compose up` command.
This will start the `server` container that has the Apache, OpenSSH & PHP 7.3 enabled.

Once the `server` is up and running, the `deployer` container will be started and alongside it
the tests will be ran.

## Adding new E2E tests

The E2E test should be a part of the `e2e` test suite.
Each `e2e` test class should inherit from `AbstractE2ETest` class.

Note: E2E tests will only run in an environment where env variable `E2E_ENV` has been set and has a truthy value.

## Manually accessing the `deployer` container.

The container can be accessed by running:

```bash
docker-compose run deployer sh
```

This command will spawn a `sh` shell inside the `deployer` container.

## About containers

### `deployer` container

The `deployer` container contains:

* git
* PHP 7.3 with XDebug enabled
* rsync
* SSH client

It is possible to access the `server` container via ssh by running:

```bash
ssh deployer@server
```

`root`'s public key has been added to authorized keys for `deployer` user.

#### Enabling XDebug

To enable XDebug create a `docker-compose.override.yml` file with following content:

```dockerfile
services:
deployer:
environment:
# See https://docs.docker.com/docker-for-mac/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host
# See https://github.com/docker/for-linux/issues/264
# The `remote_host` below may optionally be replaced with `remote_connect_back=1`
XDEBUG_CONFIG: >-
remote_enable=1
remote_host=${XDEBUG_HOST:-host.docker.internal}
remote_autostart=1
remote_port=9000
idekey=PHPSTORM
# This should correspond to the server declared in PHPStorm `Preferences | Languages & Frameworks | PHP | Servers`
# Then PHPStorm will use the corresponding path mappings
PHP_IDE_CONFIG: serverName=deployer-e2e
```

Note: you may want to set the `XDEBUG_HOST` env variable to point to your IP address when running tests in Linux.

### `server` container

The `server` container contains:

* Apache (with the `DocumentRoot` set to `/var/www/html/current`)
* git
* PHP 7.3
* SSH server with
* sudo (user `deployer` can use `sudo` without having to enter passwords)
32 changes: 32 additions & 0 deletions docker/conf/healthcheck.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<VirtualHost *:81>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com

ServerAdmin webmaster@localhost
DocumentRoot /var/www/html

# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

RewriteEngine on
RedirectMatch 204 /health_check

# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>
46 changes: 46 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
version: '2.4'

services:
deployer:
build:
context: .
target: deployer
depends_on:
server:
condition: service_healthy
volumes:
- ./../:/project
command: "php vendor/bin/pest"
networks:
- e2e
# environment:
# # See https://docs.docker.com/docker-for-mac/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host
# # See https://github.com/docker/for-linux/issues/264
# # The `remote_host` below may optionally be replaced with `remote_connect_back=1`
# XDEBUG_CONFIG: >-
# remote_enable=1
# remote_host=${XDEBUG_RHOST:-host.docker.internal}
# remote_autostart=1
# remote_port=9000
# idekey=PHPSTORM
# # This should correspond to the server declared in PHPStorm `Preferences | Languages & Frameworks | PHP | Servers`
# # Then PHPStorm will use the corresponding path mappings
# PHP_IDE_CONFIG: serverName=deployer-e2e

server:
build:
context: .
target: server
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:81/health_check"]
interval: 5s
timeout: 2s
retries: 3
start_period: 2s
networks:
e2e:
aliases:
- server.test

networks:
e2e:
5 changes: 5 additions & 0 deletions docker/initial-site/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
Hello World!
</body>
</html>
18 changes: 18 additions & 0 deletions docker/scripts/install-composer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh

EXPECTED_CHECKSUM="$(wget -q -O - https://composer.github.io/installer.sig)"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"

if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
then
>&2 echo 'ERROR: Invalid installer checksum'
rm composer-setup.php
exit 1
fi

php composer-setup.php --quiet --install-dir=/tmp --filename=composer
RESULT=$?
rm composer-setup.php
chmod a+x /tmp/composer
exit $RESULT
8 changes: 8 additions & 0 deletions docker/scripts/start-servers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh
set -e

echo "Starting SSH server"
/usr/sbin/sshd -D &

echo "Starting Apache"
exec /usr/local/bin/apache2-foreground
3 changes: 3 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
<testsuite name="Joy">
<directory>test/joy/</directory>
</testsuite>
<testsuite name="e2e">
<directory>test/e2e/</directory>
</testsuite>
</testsuites>
</phpunit>
17 changes: 17 additions & 0 deletions test/e2e/AbstractE2ETest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
namespace e2e;

use Deployer\AbstractTest;

abstract class AbstractE2ETest extends AbstractTest
{
protected function setUp(): void
{
parent::setUp();
$isE2EEnvironment = filter_var(getenv('E2E_ENV'), FILTER_VALIDATE_BOOLEAN);

if ($isE2EEnvironment !== true) {
$this->markTestSkipped('Cannot execute in non-E2E environment');
}
}
}
27 changes: 27 additions & 0 deletions test/e2e/FunctionsE2ETest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php declare(strict_types=1);
namespace e2e;

class FunctionsE2ETest extends AbstractE2ETest
{
private const RECIPE = __DIR__ . '/recipe/functions.php';

/**
* @group e2e
*/
public function testRunWithPlaceholders(): void
{
$this->init(self::RECIPE);

$this->tester->run([
'test:functions:run-with-placeholders',
'-f' => self::RECIPE,
'selector' => 'all',
]);

$display = $this->tester->getDisplay();
$display = trim($display); // Output may contain newlines, so we should trim them in advance

self::assertEquals(0, $this->tester->getStatusCode(), $display);
self::assertEquals('placeholder {{bar}} xyz%', $display);
}
}
13 changes: 13 additions & 0 deletions test/e2e/recipe/deploy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace Deployer;

set('application', 'deployer-e2e');
host('server.test')
->setTag('e2e')
->setRemoteUser('deployer')
->setSshOptions(
[
'UserKnownHostsFile' => '/dev/null',
'StrictHostKeyChecking' => 'no',
]
);
12 changes: 12 additions & 0 deletions test/e2e/recipe/functions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php declare(strict_types=1);
namespace Deployer;

require_once __DIR__ . '/deploy.php';

task('test:functions:run-with-placeholders', function (): void {
$cmd = "echo 'placeholder %foo% %baz%'";
$vars = [ 'foo' => '{{bar}}', 'baz' => 'xyz%' ];

$output = run($cmd, [ 'vars' => $vars ]);
output()->writeln($output); // we use this to skip \Deployer\parse() being called in normal \Deployer\writeln()
})->shallow();

0 comments on commit a8c14cf

Please sign in to comment.