Configuration¶
This project provides a generic way to create a various set of project types. For each project type, an appropriate build configuration exists. The configuration describes how to build a project, e.g. which steps are necessary and what properties are required when rendering project templates.
External template packages¶
Project templates are distributed through external Composer packages.
Important
Each Composer package must be of the type project-builder-template
.
1{
2 "name": "cpsit/project-builder-template-my-fancy-project",
3 "type": "project-builder-template",
4 // ...
5}
Additionally, the packages must be installable via Composer. There are three ways to make a template package available to the project builder:
Either register it on Packagist,
Use any other Composer registry (e.g. self-hosted Satis instance), or
Host the project template on a VCS repository (such as GitHub) to make your package available to the project builder.
Once you use the project builder to create a new project, you can select the appropriate provider that hosts your template package.
Tip
You can add the cpsit/project-builder
package as a dependency to
your template package. Composer will correctly resolve the constraint.
This way, you can define the versions of the project builder actually
supported by your package:
1{
2 "name": "cpsit/project-builder-template-my-fancy-project",
3 "type": "project-builder-template",
4 "require": {
5 "cpsit/project-builder": "^1.0"
6 }
7 // ...
8}
Exclude packages from listing¶
If a template package is published on a supported platform such as Packagist, it is always included in the list of available template packages when generating new projects.
However, a single template package can also be explicitly excluded from that list. This may be useful if a package is not meant to be publicly used or if it’s just published for demonstration or testing purposes.
In such cases, template packages may provide the following configuration in
their composer.json
file:
1{
2 "extra": {
3 "cpsit/project-builder": {
4 "exclude-from-listing": true
5 }
6 }
7}
File structure¶
Within the external Composer template package, the following file structure must exist:
my-fancy-project
├── composer.json
├── config.yml
├── config
│ └── services.yaml
├── src
│ ├── ...
│ └── Twig
│ └── Function
│ └── MyCustomTwigFunction.php
└── templates
├── shared
│ ├── ...
│ └── my-fancy-shared-resource
│ ├── composer.json
│ └── templates
│ └── src
│ ├── ...
│ └── .gitlab-ci.yml.twig
└── src
├── ...
└── composer.json.twig
In this example, the project type my-fancy-project
is configured and
distributed through the package cpsit/project-builder-template-my-fancy-project
.
It contains the following files and directories:
composer.json
(optional) defines additional template dependencies. Those are installed by the build stepinstallComposerDependencies
. Read more atProcessing build steps#Install Composer dependencies
.config.yml
is the main configuration file. It contains all instructions on how to build new projects of this project type. Read more atConfig file
.config
(optional) contains additional service configuration files, e.g.services.yaml
orservices.php
. Read more atDependency injection#Extending service configuration
.src
(optional) may contain additional PHP classes. Normally, these require an additional service configuration as described before.templates
(optional) contains various project source files. The following sub-folders are supported:shared
(optional) should contain shared source files. Those are normally created when installing Composer dependencies defined bycomposer.json
. Read more atShared source files
.src
(optional) contains all project source files. Those can be either generic files to be copied to the generated project or Twig template files. Twig files are processed before copying them to the generated project. Read more atSource files
.
Config file¶
Each project type requires a configuration file. It describes how to build a new project of this type and is located in the template directory of the associated project type.
The following filename variants are supported:
config.yml
config.yaml
config.json
See also
See ConfigReader::FILE_VARIANTS
for an overview of supported filenames.
Structure¶
Each config file should at least contain the following properties:
name
is kind of a label for the configured project type. It is mainly used for communication with the user, keeping the actual project type internal.steps
defines a list of necessary build steps. Those steps are processed once a new project of the associated project type is generated. Read more atProcessing build steps
.
Usually, it is also necessary to collect some more information from the user, e.g.
to be able to prepare template files such as README.md.twig
or composer.json.twig
.
For this, a set of properties
can be defined. Those properties are then used to
collect information in form of build instructions from the user. Read more at
Processing build steps#Collect build instructions
.
Example:
1name: My fancy project
2
3steps:
4 - type: installComposerDependencies
5 - type: collectBuildInstructions
6 - type: processSourceFiles
7 options:
8 fileConditions:
9 # You can define a Twig template to render...
10 - path: composer.json.twig
11 if: 'features["composer"]'
12 # ... or use static files
13 - path: example-v3.conf
14 if: 'features["example"] && example["version"] == "3"'
15 target: example.conf
16 - type: processSharedSourceFiles
17 options:
18 fileConditions:
19 # Use Symfony Expression Language to define file conditions
20 - path: phpunit.xml
21 if: 'features["phpunit"]'
22 # Mirror an entire directory
23 - path: 'source-dir/*'
24 target: 'target-dir/*'
25 # Apply Twig expression for custom target directory names
26 - path: 'source-dir/*'
27 target: '{{ project.name | slugify }}-target-dir/*'
28 - type: mirrorProcessedFiles
29 - type: runCommand
30 options:
31 command: 'git init --initial-branch=main'
32 skipConfirmation: true
33 allowFailure: true
34 - type: runCommand
35 options:
36 command: 'composer update'
37 allowFailure: true
38 required: false
39 - type: showNextSteps
40 options:
41 templateFile: templates/next-steps.html.twig
42
43properties:
44 # Project
45 - identifier: project
46 name: Project
47 properties:
48 - identifier: customer_name
49 name: Customer name
50 type: staticValue
51 validators:
52 - type: notEmpty
53 - identifier: project_name
54 name: Project name
55 type: staticValue
56 defaultValue: basic
57 validators:
58 - type: notEmpty
59 - type: regex
60 options:
61 pattern: '/^[a-zA-Z]+$/'
62 errorMessage: 'The project name should consist of letters only.'
63
64 # Features
65 - identifier: features
66 name: Features
67 properties:
68 - identifier: composer
69 name: Enable <comment>Composer</comment> support?
70 type: question
71 defaultValue: true
72 - identifier: phpstan
73 name: Do you need <comment>PHPStan</comment> support?
74 type: question
75 - identifier: phpunit
76 name: Do you want to run tests with <comment>PHPUnit</comment>?
77 type: question
78
79 # Author
80 - identifier: author
81 name: About you
82 properties:
83 - identifier: name
84 name: Your name
85 type: staticValue
86 validators:
87 - type: notEmpty
88 - identifier: email
89 name: Your e-mail address
90 type: staticValue
91 validators:
92 - type: notEmpty
93 - type: email
Twig integration¶
Some configuration parts may be configured as Twig templates. For example, the
defaultValue
option of a configured property may contain the processed value
of a previously added property:
1properties:
2 - identifier: project
3 name: Project
4 properties:
5 - identifier: name
6 name: Name
7 type: staticValue
8 validators:
9 - type: notEmpty
10 - identifier: vendor
11 name: Vendor
12 type: staticValue
13 validators:
14 - type: notEmpty
15 - identifier: package_name
16 name: Package name
17 type: staticValue
18 defaultValue: '{{ project.vendor | slugify }}/{{ project.name | slugify }}'
19 validators:
20 - type: notEmpty
The following configuration options are currently processed by the Twig renderer:
steps.*.options.fileConditions.*.target
properties.*.value
properties.*.properties.*.defaultValue
properties.*.properties.*.options.*.value
Symfony Expression Language integration¶
Several configuration options use conditions to determine whether a property or step should be applied. All used conditions are parsed by the Symfony Expression Language.
Example:
1steps:
2 - type: processSharedSourceFiles
3 options:
4 fileConditions:
5 - path: composer.json
6 if: 'features["composer"] == true'
The following configuration options are currently evaluated by the Symfony Expression Language:
steps.*.options.fileConditions.*.if
properties.*.if
properties.*.properties.*.if
properties.*.properties.*.options.*.if
Mapping and hydration¶
Config files are located by the ConfigReader
and parsed by the internal ConfigFactory
.
With the help of the fantastic external library cuyz/valinor
, the parsed
config file is mapped to an object structure of value objects. The final configuration
ends up in an instance of Builder\Config\Config
:
1$configReader = \CPSIT\ProjectBuilder\Builder\Config\ConfigReader::create();
2$config = $configReader->readConfig('my-fancy-project');
3
4echo $config->getIdentifier(); // my-fancy-project
5echo $config->getName(); // My fancy project
Each configured property in the config file is now accessible from the
Config
object:
Property |
Accessor |
Type |
---|---|---|
|
|
|
|
|
|
|
|
See also
All hydrated value objects can be found at Builder\Config\ValueObject
.
Validation¶
Config files are validated against a JSON schema. The schema file is located
at resources/config.schema.json
. Schema
validation is handled by ConfigFactory::isValidConfig()
with the help of the great external library justinrainbow/json-schema
.
Warning
If a config file does not match the required schema, project generation will fail immediately.
Source files¶
Each project type may provide several source files. They must be stored in a
templates/src
folder.
Currently, the following file variants are supported:
Generic files can be any files other than Twig files. They will be copied as-is to the generated project. Example:
composer.json
Twig template files are pre-processed by the Twig renderer before they are copied to the generated project. The configured properties are used as template variables. Read more at
Architecture#Template rendering
. Example:composer.json.twig