Add slides for PHP Munich
This commit is contained in:
parent
6d8f1db01f
commit
70d330aa1b
BIN
src/building-build-configs-php-munich/diagram.png
Normal file
BIN
src/building-build-configs-php-munich/diagram.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
src/building-build-configs-php-munich/example.mp4
Normal file
BIN
src/building-build-configs-php-munich/example.mp4
Normal file
Binary file not shown.
|
@ -0,0 +1,27 @@
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
PageBreak standardPage
|
||||||
|
|
||||||
|
Result
|
||||||
|
======
|
||||||
|
|
||||||
|
- Easier and faster to create and onboard projects.
|
||||||
|
- One canonical source of truth.
|
||||||
|
- Easy to add new features and fixes for all projects.
|
||||||
|
- Automation is easier due to consistency (e.g. Docker Compose service names).
|
||||||
|
|
||||||
|
Thanks!
|
||||||
|
=======
|
||||||
|
|
||||||
|
References:
|
||||||
|
|
||||||
|
- https://opdavi.es/build-configs
|
||||||
|
- https://github.com/opdavies/docker-example-drupal
|
||||||
|
- https://github.com/opdavies/docker-example-drupal-commerce-kickstart
|
||||||
|
- https://github.com/opdavies/docker-example-drupal-localgov
|
||||||
|
|
||||||
|
|
|
||||||
|
|
||||||
|
Me:
|
||||||
|
|
||||||
|
- https://www.oliverdavies.uk
|
|
@ -0,0 +1,52 @@
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
PageBreak standardPage
|
||||||
|
|
||||||
|
Overriding Values
|
||||||
|
=================
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
php:
|
||||||
|
version: 8.1-fpm-bullseye
|
||||||
|
# Disable PHPCS, PHPStan and PHPUnit.
|
||||||
|
phpcs: false
|
||||||
|
phpstan: false
|
||||||
|
phpunit: false
|
||||||
|
|
||||||
|
# Ignore more directories from Git.
|
||||||
|
git:
|
||||||
|
ignore:
|
||||||
|
- /bin/
|
||||||
|
- /libraries/
|
||||||
|
- /web/profiles/contrib/
|
||||||
|
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
TextAnnotation "Drupal Commerce Kickstart demo. No custom modules to test, and additional paths to ignore from Git."
|
||||||
|
|
||||||
|
PageBreak
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
dockerfile:
|
||||||
|
stages:
|
||||||
|
build:
|
||||||
|
# What additional directories do we need?
|
||||||
|
extra_directories:
|
||||||
|
- config
|
||||||
|
- patches
|
||||||
|
- scripts
|
||||||
|
|
||||||
|
commands:
|
||||||
|
- composer validate --strict
|
||||||
|
- composer install
|
||||||
|
|
||||||
|
# What additional PHP extensions do we need?
|
||||||
|
extensions:
|
||||||
|
install: [bcmath]
|
||||||
|
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
TextAnnotation "Extra directories and PHP extensions that need to be added".
|
||||||
|
|
92
src/building-build-configs-php-munich/sections/example.rst
Normal file
92
src/building-build-configs-php-munich/sections/example.rst
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
Example
|
||||||
|
=======
|
||||||
|
|
||||||
|
build.yaml:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
name: my-example-project
|
||||||
|
type: drupal
|
||||||
|
language: php
|
||||||
|
|
||||||
|
php:
|
||||||
|
version: 8.1-fpm-bullseye
|
||||||
|
|
||||||
|
|
|
||||||
|
|
||||||
|
Dockerfile:
|
||||||
|
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
TextAnnotation "Abstract the project-specific values and configuration into this file."
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
FROM php:8.1-fpm-bullseye AS base
|
||||||
|
|
||||||
|
Configuring a Project
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
php:
|
||||||
|
version: 8.1-fpm-bullseye
|
||||||
|
|
||||||
|
# Which PHPCS standards should be used and on which paths?
|
||||||
|
phpcs:
|
||||||
|
paths: [web/modules/custom]
|
||||||
|
standards: [Drupal, DrupalPractice]
|
||||||
|
|
||||||
|
# What level should PHPStan run and on what paths?
|
||||||
|
phpstan:
|
||||||
|
level: max
|
||||||
|
paths: [web/modules/custom]
|
||||||
|
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
PageBreak
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
docker-compose:
|
||||||
|
# Which Docker Compose services do we need?
|
||||||
|
services:
|
||||||
|
- database
|
||||||
|
- php
|
||||||
|
- web
|
||||||
|
|
||||||
|
dockerfile:
|
||||||
|
stages:
|
||||||
|
build:
|
||||||
|
# What commands do we need to run?
|
||||||
|
commands:
|
||||||
|
- composer validate --strict
|
||||||
|
- composer install
|
||||||
|
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
PageBreak
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
web:
|
||||||
|
type: nginx # nginx, apache, caddy
|
||||||
|
|
||||||
|
database:
|
||||||
|
type: mariadb # mariadb, mysql
|
||||||
|
version: 10
|
||||||
|
|
||||||
|
# Where is Drupal located?
|
||||||
|
drupal:
|
||||||
|
docroot: web # web, docroot, null
|
||||||
|
|
||||||
|
experimental:
|
||||||
|
createGitHubActionsConfiguration: true
|
||||||
|
runGitHooksBeforePush: true
|
||||||
|
useNewDatabaseCredentials: true
|
||||||
|
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
TextAnnotation "Experimental opt-in features that I want to trial on certain projects or to disable non-applicable features - e.g. GitHub Actions on Bitbucket."
|
||||||
|
|
||||||
|
PageBreak
|
300
src/building-build-configs-php-munich/sections/internals.rst
Normal file
300
src/building-build-configs-php-munich/sections/internals.rst
Normal file
|
@ -0,0 +1,300 @@
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
PageBreak titlePage
|
||||||
|
|
||||||
|
.. class:: centredtitle
|
||||||
|
|
||||||
|
Build Configs internals
|
||||||
|
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
PageBreak standardPage
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
src/
|
||||||
|
Action/
|
||||||
|
CreateFinalConfigurationData.php
|
||||||
|
CreateListOfFilesToGenerate.php
|
||||||
|
GenerateConfigurationFiles.php
|
||||||
|
ValidateConfigurationData.php
|
||||||
|
Command/
|
||||||
|
GenerateCommand.php
|
||||||
|
InitCommand.php
|
||||||
|
DataTransferObject/
|
||||||
|
ConfigDto.php
|
||||||
|
TemplateFile.php
|
||||||
|
Enum/
|
||||||
|
Language.php
|
||||||
|
ProjectType.php
|
||||||
|
WebServer.php
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
:linenos:
|
||||||
|
:startinline: true
|
||||||
|
|
||||||
|
protected function configure(): void
|
||||||
|
$this
|
||||||
|
->addOption(
|
||||||
|
name: 'config-file',
|
||||||
|
shortcut: ['c'],
|
||||||
|
mode: InputOption::VALUE_REQUIRED,
|
||||||
|
description: 'The path to the project\'s build.yaml file',
|
||||||
|
default: 'build.yaml',
|
||||||
|
)
|
||||||
|
->addOption(
|
||||||
|
name: 'output-dir',
|
||||||
|
shortcut: ['o'],
|
||||||
|
mode: InputOption::VALUE_REQUIRED,
|
||||||
|
description: 'The directory to create files in',
|
||||||
|
default: '.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
:linenos:
|
||||||
|
:startinline: true
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
$configFile = $input->getOption(name: 'config-file');
|
||||||
|
$outputDir = $input->getOption(name: 'output-dir');
|
||||||
|
}
|
||||||
|
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
PageBreak
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
:linenos:
|
||||||
|
:startinline: true
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
|
||||||
|
$pipelines = [
|
||||||
|
new CreateFinalConfigurationData(),
|
||||||
|
|
||||||
|
new ValidateConfigurationData(),
|
||||||
|
|
||||||
|
new CreateListOfFilesToGenerate(),
|
||||||
|
|
||||||
|
new GenerateConfigurationFiles(
|
||||||
|
$this->filesystem,
|
||||||
|
$this->twig,
|
||||||
|
$outputDir,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
:linenos:
|
||||||
|
:startinline: true
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Collection<int,TemplateFile> $generatedFiles
|
||||||
|
* @var ConfigDto $configurationData
|
||||||
|
*/
|
||||||
|
[$configurationData, $generatedFiles] = (new Pipeline())
|
||||||
|
->send($configFile)
|
||||||
|
->through($pipelines)
|
||||||
|
->thenReturn();
|
||||||
|
|
||||||
|
$io->info("Building configuration for {$configurationData->name}.");
|
||||||
|
|
||||||
|
$io->write('Generated files:');
|
||||||
|
$io->listing(static::getListOfFiles(filesToGenerate: $generatedFiles)->toArray());
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
:linenos:
|
||||||
|
:startinline: true
|
||||||
|
|
||||||
|
// CreateFinalConfigurationData.php
|
||||||
|
|
||||||
|
public function handle(string $configFile, \Closure $next) {
|
||||||
|
{
|
||||||
|
$configurationData = Yaml::parseFile(filename: $configFile);
|
||||||
|
|
||||||
|
$configurationData = array_replace_recursive(
|
||||||
|
Yaml::parseFile(filename: __DIR__ . '/../../resources/build.defaults.yaml'),
|
||||||
|
$configurationData,
|
||||||
|
);
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
return $next($configurationData);
|
||||||
|
}
|
||||||
|
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
PageBreak
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
:linenos:
|
||||||
|
:startinline: true
|
||||||
|
|
||||||
|
// ValidateConfigurationData.php
|
||||||
|
|
||||||
|
public function handle(array $configurationData, \Closure $next)
|
||||||
|
{
|
||||||
|
// Convert the input to a configuration data object.
|
||||||
|
$normalizer = new ObjectNormalizer(null, new CamelCaseToSnakeCaseNameConverter());
|
||||||
|
$serializer = new Serializer([$normalizer], [new JsonEncoder()]);
|
||||||
|
|
||||||
|
$configurationDataDto = $serializer->deserialize(
|
||||||
|
json_encode($configurationData),
|
||||||
|
ConfigDto::class,
|
||||||
|
'json',
|
||||||
|
);
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
PageBreak
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
:linenos:
|
||||||
|
:startinline: true
|
||||||
|
|
||||||
|
// ValidateConfigurationData.php
|
||||||
|
|
||||||
|
public function handle(array $configurationData, \Closure $next)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
|
||||||
|
$validator = Validation::createValidatorBuilder()
|
||||||
|
->enableAnnotationMapping()
|
||||||
|
->getValidator();
|
||||||
|
$violations = $validator->validate($configurationDataDto);
|
||||||
|
|
||||||
|
if (0 < $violations->count()) {
|
||||||
|
throw new \RuntimeException('Configuration is invalid.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next([$configurationData, $configurationDataDto]);
|
||||||
|
}
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
:linenos:
|
||||||
|
:startinline: true
|
||||||
|
|
||||||
|
// ConfigDto.php
|
||||||
|
|
||||||
|
#[Assert\Collection(
|
||||||
|
allowExtraFields: false,
|
||||||
|
fields: ['docroot' => new Assert\Choice([null, 'web', 'docroot'])],
|
||||||
|
)]
|
||||||
|
public array $drupal;
|
||||||
|
|
||||||
|
#[Assert\Collection([
|
||||||
|
'ignore' => new Assert\Optional([
|
||||||
|
new Assert\All([
|
||||||
|
new Assert\Type('string'),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
])]
|
||||||
|
public array $git;
|
||||||
|
|
||||||
|
#[Assert\Choice(choices: ['javascript', 'php', 'typescript'])]
|
||||||
|
public string $language;
|
||||||
|
|
||||||
|
#[Assert\NotBlank]
|
||||||
|
#[Assert\Type('string')]
|
||||||
|
public string $name;
|
||||||
|
|
||||||
|
#[Assert\Type('string')]
|
||||||
|
public string $projectRoot;
|
||||||
|
|
||||||
|
#[Assert\Choice(choices: [
|
||||||
|
'drupal',
|
||||||
|
'fractal',
|
||||||
|
'php-library',
|
||||||
|
'symfony',
|
||||||
|
])]
|
||||||
|
public string $type;
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
:startinline: true
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
// CreateListOfFilesToGenerate.php
|
||||||
|
|
||||||
|
public function handle(array $configurationDataAndDto, \Closure $next)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ConfigDto $configDto,
|
||||||
|
* @var array<string,mixed> $configurationData
|
||||||
|
*/
|
||||||
|
[$configurationData, $configDto] = $configurationDataAndDto;
|
||||||
|
|
||||||
|
/** @var Collection<int, TemplateFile> */
|
||||||
|
$filesToGenerate = collect();
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
:startinline: true
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
// CreateListOfFilesToGenerate.php
|
||||||
|
|
||||||
|
public function handle(array $configurationDataAndDto, \Closure $next)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
|
||||||
|
if (!isset($configDto->php['phpunit']) || $configDto->php['phpunit'] !== false) {
|
||||||
|
|
||||||
|
$filesToGenerate->push(
|
||||||
|
new TemplateFile(
|
||||||
|
data: 'drupal/phpunit.xml.dist',
|
||||||
|
name: 'phpunit.xml.dist',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
return $next([$configurationData, $configDto, $filesToGenerate]);
|
||||||
|
}
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
:linenos:
|
||||||
|
:startinline: true
|
||||||
|
|
||||||
|
// GenerateConfigurationFiles.php
|
||||||
|
|
||||||
|
public function handle(array $filesToGenerateAndConfigurationData, \Closure $next)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
|
||||||
|
$filesToGenerate->each(function(TemplateFile $templateFile) use ($configurationData): void {
|
||||||
|
if ($templateFile->path !== null) {
|
||||||
|
if (!$this->filesystem->exists($templateFile->path)) {
|
||||||
|
$this->filesystem->mkdir("{$this->outputDir}/{$templateFile->path}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sourceFile = "{$templateFile->data}.twig";
|
||||||
|
|
||||||
|
$outputFile = collect([$this->outputDir, $templateFile->path, $templateFile->name])
|
||||||
|
->filter()->implode('/');
|
||||||
|
|
||||||
|
$this->filesystem->dumpFile($outputFile, $this->twig->render($sourceFile, $configurationData));
|
||||||
|
});
|
||||||
|
|
||||||
|
return $next([$configurationDataDto, $filesToGenerate]);
|
||||||
|
}
|
||||||
|
|
51
src/building-build-configs-php-munich/sections/intro.rst
Normal file
51
src/building-build-configs-php-munich/sections/intro.rst
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
PageBreak standardPage
|
||||||
|
|
||||||
|
What is "Build Configs"?
|
||||||
|
========================
|
||||||
|
|
||||||
|
- Command-line tool.
|
||||||
|
- Inspired by Workspace, name from the TheAltF4Stream.
|
||||||
|
- Built with Symfony.
|
||||||
|
- Creates and manages build configuration files.
|
||||||
|
- Customisable per-project.
|
||||||
|
- Drupal, PHP library, Fractal (TypeScript).
|
||||||
|
- "Sprint zero in a box".
|
||||||
|
|
||||||
|
What Problem Does it Solve?
|
||||||
|
===========================
|
||||||
|
|
||||||
|
- I work on multiple similar projects.
|
||||||
|
- Different configuration values - e.g. ``web`` vs. ``docroot``.
|
||||||
|
- Different versions of PHP, node, etc.
|
||||||
|
- Different Docker Compose (``fpm`` vs. ``apache`` images).
|
||||||
|
- Each project was separate.
|
||||||
|
- Difficult to add new features and fix bugs across all projects.
|
||||||
|
- Inconsistencies across projects.
|
||||||
|
- Out of the box solutions didn't seem like the best fit.
|
||||||
|
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
TextAnnotation "Multiple projects with similar but different configurations."
|
||||||
|
TextAnnotation ""
|
||||||
|
TextAnnotation "Out of the box solutions tend to focus on one technology, could be hard to customise, and usually had more than I nedeed."
|
||||||
|
TextAnnotation ""
|
||||||
|
TextAnnotation "Start small and build up instead of removing additional things."
|
||||||
|
TextAnnotation ""
|
||||||
|
TextAnnotation "More opportunities to learn the underlying technologies."
|
||||||
|
|
||||||
|
How Does it Work?
|
||||||
|
=================
|
||||||
|
|
||||||
|
.. image:: diagram.png
|
||||||
|
:width: 18cm
|
||||||
|
|
||||||
|
What Files Does it Generate?
|
||||||
|
============================
|
||||||
|
|
||||||
|
- Dockerfile, Docker Compose, Nix Flake, php.ini, NGINX default.conf.
|
||||||
|
- ``run`` file.
|
||||||
|
- PHPUnit, PHPCS, PHPStan.
|
||||||
|
- GitHub Actions workflow.
|
||||||
|
- Git hooks.
|
117
src/building-build-configs-php-munich/sections/templates.rst
Normal file
117
src/building-build-configs-php-munich/sections/templates.rst
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
PageBreak standardPage
|
||||||
|
|
||||||
|
Dockerfile.twig
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. code-block:: twig
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
FROM php:{{ php.version }} AS base
|
||||||
|
|
||||||
|
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||||
|
RUN which composer && composer -V
|
||||||
|
|
||||||
|
ARG DOCKER_UID=1000
|
||||||
|
ENV DOCKER_UID="${DOCKER_UID}"
|
||||||
|
|
||||||
|
WORKDIR {{ project_root }}
|
||||||
|
|
||||||
|
RUN adduser --disabled-password --uid "${DOCKER_UID}" app \
|
||||||
|
&& chown app:app -R {{ project_root }}
|
||||||
|
|
||||||
|
Dockerfile.twig
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. code-block:: twig
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
{% if dockerfile.stages.build.extensions.install %}
|
||||||
|
RUN docker-php-ext-install
|
||||||
|
{{ dockerfile.stages.build.extensions.install|join(' ') }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
COPY --chown=app:app phpunit.xml* ./
|
||||||
|
|
||||||
|
{% if dockerfile.stages.build.extra_files %}
|
||||||
|
COPY --chown=app:app {{ dockerfile.stages.build.extra_files|join(" ") }} ./
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for directory in dockerfile.stages.build.extra_directories %}
|
||||||
|
COPY --chown=app:app {{ directory }} {{ directory }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
docker-compose.yaml.twig
|
||||||
|
========================
|
||||||
|
|
||||||
|
.. code-block:: twig
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
services:
|
||||||
|
{% if "web" in dockerCompose.services %}
|
||||||
|
web:
|
||||||
|
<<: [*default-proxy, *default-app]
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
target: web
|
||||||
|
depends_on:
|
||||||
|
- php
|
||||||
|
profiles: [web]
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
phpstan.neon.dist.twig
|
||||||
|
======================
|
||||||
|
|
||||||
|
.. code-block:: twig
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
level: {{ php.phpstan.level }}
|
||||||
|
excludePaths:
|
||||||
|
- *Test.php
|
||||||
|
- *TestBase.php
|
||||||
|
paths:
|
||||||
|
{% for path in php.phpstan.paths -%}
|
||||||
|
- {{ path }}
|
||||||
|
{%- endfor %}
|
||||||
|
|
||||||
|
{% if php.phpstan.baseline %}
|
||||||
|
includes:
|
||||||
|
- phpstan-baseline.neon
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
phpunit.xml.dist.twig
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. code-block:: twig
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
<phpunit
|
||||||
|
beStrictAboutChangesToGlobalState="true"
|
||||||
|
beStrictAboutOutputDuringTests="false"
|
||||||
|
beStrictAboutTestsThatDoNotTestAnything="true"
|
||||||
|
bootstrap="{{ drupal.docroot }}/core/tests/bootstrap.php"
|
||||||
|
cacheResult="false"
|
||||||
|
colors="true"
|
||||||
|
failOnWarning="true"
|
||||||
|
printerClass="\Drupal\Tests\Listeners\HtmlOutputPrinter"
|
||||||
|
>
|
||||||
|
|
||||||
|
phpunit.xml.dist.twig
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. code-block:: twig
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="functional">
|
||||||
|
<directory>./{{ drupal.docroot }}/modules/custom/**/tests/**/Functional</directory>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="kernel">
|
||||||
|
<directory>./{{ drupal.docroot }}/modules/custom/**/tests/**/Kernel</directory>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="unit">
|
||||||
|
<directory>./{{ drupal.docroot }}/modules/custom/**/tests/**/Unit</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
30
src/building-build-configs-php-munich/slides.rst
Normal file
30
src/building-build-configs-php-munich/slides.rst
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
.. footer:: @opdavies
|
||||||
|
|
||||||
|
Building "Build Configs"
|
||||||
|
########################
|
||||||
|
|
||||||
|
.. class:: titleslideinfo
|
||||||
|
|
||||||
|
Oliver Davies (@opdavies)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
||||||
|
.. class:: titleslideinfo
|
||||||
|
|
||||||
|
https://opdavi.es/bcm
|
||||||
|
|
||||||
|
.. include:: ./sections/intro.rst
|
||||||
|
.. include:: ./sections/example.rst
|
||||||
|
.. include:: ./sections/customisation.rst
|
||||||
|
.. include:: ./sections/templates.rst
|
||||||
|
.. include:: ./sections/internals.rst
|
||||||
|
|
||||||
|
.. raw:: pdf
|
||||||
|
|
||||||
|
PageBreak titlePage
|
||||||
|
|
||||||
|
.. class:: centredtitle
|
||||||
|
|
||||||
|
Demo
|
||||||
|
|
||||||
|
.. include:: ./sections/conclusion.rst
|
Loading…
Reference in a new issue