-
@TODO: Document that when using
find
,-print0
MUST be the last argument, and thatxargs
MUST use-0
as an argument. -
@TODO: Explain
working-directory: "solid"
in the solid-nextcloud repo PHP GHA -
@TODO: Document the CHECKS SHOULD ALWAYS BE GREEN (✅) on the
main
branch! -
@TODO: Document the reason for
fail-fast: false
whenstrategy.matrix
is used! -
@TODO: Explain that, when using docker://pipelinecomponent/*, the
with.options
MUST include the command that is being called. -
@TODO: Document that
continue-on-error: $
is not used, as (although the MR could still be merged) there would be a red cross ❌ in the PR checks. -
@TODO: Document that EOL version do not have to be supported but MAY be in matrix as long as they do not fail Support for failing EOL versions is, deppendant on effort/cost to support them
-
@TODO: Explain why
find
uses-name '*.sh'
instead of\(-name '*.sh' -o -name '*.bash'\)
GitHub Actions
This repository contains building blocks to construct GitHub Actions (GHA) with
An effort has been made to create a CI/CD pipeline that is:
- Performant Runs only when needed, in as short a time as possible
- Portable Uses tools that can be run locally or on other CI/CD platforms
- Reusable Can be used in other projects with minimal changes
To achieve this certain choices have been made, for instance, using a Docker container for the CI/CD pipeline (instead of a GitHub Action) or GitHub Actions provided by Pipeline Components (as they can also be run locally and on other CI/CD platforms).
This document contains these choices and other information regarding GHA.
Available “Building blocks”
- _TBD: Explain files:
00.header
01.preflight.json.lint-syntax
01.preflight.php.lint-syntax
01.preflight.php.validate.dependencies-file
01.preflight.xml.lint-syntax
01.preflight.yaml.lint
02.test.php.test-unit
03.quality.docker.lint
03.quality.markdown.lint-spelling
03.quality.markdown.lint-syntax
03.quality.php.lint-version-compatibility
03.quality.php.scan.dependencies-vulnerabilities
03.quality.shell.lint
- _TBD: Explain:
- Paths
- Dependencies between jobs (in the same workflow file)
- Dependencies between workflows (in separate files)
Configuration
Instead of adding configuration as parameters to GHA calls, configuration files should be used where possible.
Configuration files (for GHA, CI, or other purposes) should live in the .config
directory, unless explicitly stated otherwise in the projects README and/or CONTRIBUTING files.
This means that calls to tools that require configuration files include the path to the configuration file.
Examples of configuration files are:
.github_changelog_generator
.remarkrc
.yamllint
phpcs.xml.dist
phpunit.xml.dist
Config files that can not be placed in the .config
directory (for instance because the companion tool does not support this), should be placed in the root of the repository.
@TODO: In later itteration, logic should be added to move these files to the root (from the `.config` directory) before the CI/CD pipeline is run.
Examples of these are:
.spelling
When to add what
Which GitHub Actions are used depends mostly on which programming or markup language is used.
For most of these language, the rule of thumb is that if a language is present, GitHub Actions are added for quality control or other automation.
The list of languages contains, but is not limited to:
Indicates workflows are available
Indicates workflows are not (yet) available
- CSS (
*.css
,*.scss
) - Docker (
Dockerfile
,.dockerignore
) - HTML (
*.html
) - Images (
*.png
,*.jpg
,*.svg
) - Javascript (
*.js
,*.mjs
) - JSON (
*.json
) - Markdown (
*.md
) - PHP (
*.php
) - PlantUML (
*.puml
,*.iuml
) - Shell (
*.bash, *.sh
) - YAML (
*.yaml
,*.yml
) - XML (
*.xml
)
Docker files
- Paths:
paths: # Docker generic, Files or folders used in the creation of the docker image. - '.dockerignore' - 'docker-compose.yml' - 'Dockerfile' - '.config/hadolint.yml' # Docker project specific, Dockerfile "COPY" and "ADD" entries. # Ideally, these all live in a single folder, for instance called `/docker/` - 'src/' - 'site.conf'
Dockerfile files
- Paths:
paths: - 'Dockerfile' - '.config/hadolint.yml'
JSON files
- Paths:
paths: - '**.json' - '.github/workflows/json.yml' - '!composer.json' - '!**/composer.json' - '!package.json' - '!package-lock.json' - '!**/package.json' - '!**/package-lock.json'
Exceptions and Caveats
-
composer.json
files are not linted using a JSON Linter. These file should be checked using PHP Composer specific workflow(s). -
package.json
andcomoer-lock.json
files are not linted using a JSON Linter. These file should be checked using NPM specific workflow(s).
Markdown files
- Config file(s):
.remarkrc
,.spelling
- Paths:
paths: - '**.md' - '.github/workflows/markdown.yml'
Markdown files can be checked for three things:
- Correct Content (check spelling)
- Correct Form (check syntax and code style inconsistencies)
- Correct Tone (check for insensitive or inconsiderate writing)
Where content and form should be checked as part of common quality control, the tone is checked as per the Code Manifesto “Discrimination limits us” and “Boundaries honor us” values (part of the Contributor Code of Conduct)
PHP files
- Config file(s):
phpcs.xml.dist
,phpunit.xml.dist
- Paths:
paths: - '**.php' - '.config/phpcs.xml.dist' - '.config/phpunit.xml.dist'
PHP dependencies
- Paths:
paths: - 'composer.json' - 'composer.lock'
If a PHP project uses other packages (declared in the composer.json
and optional composer.lock
files), these will also need to be checked. there are two checks for this. One to check if the declared dependencies are up to date, and one to check whether the dependencies contain possible security issues.
Validate dependencies file (composer validate
)
This workflow will check if the composer.json
file is valid.
If a composer.lock
file exists, it will also check if it is up to date with the composer.json
.
To make sure a project remains in a deployable state, composer validate
should be run before changes to the composer.json
(and composer.lock
) file are committed, or before a release is tagged.
As this command can not be configured through a config file, settings needs to be configured through parameters.
Which settings are desirable depends on the project. Available parameters are:
--check-lock
/--no-check-lock
: Check if lock file is up to date with declarations incomposer.json
--no-check-all
: Do not emit a warning if requirements in composer.json use unbound or overly strict version constraints.--no-check-publish
: Do not emit an error ifcomposer.json
is unsuitable for publishing as a package on Packagist but is otherwise valid.--no-check-version
: Do not emit an error if the version field is present.--strict
: Return a non-zero exit code for warnings as well as errors.--with-dependencies
: Also validate the composer.json of all installed dependencies.
For full details visit: https://getcomposer.org/doc/03-cli.md#validate
Scan dependencies vulnerabilities (composer audit
)
This workflow will audit packages for potential security issues. It also detects abandoned packages.
The Security vulnerability advisories listing is taken from the Packagist.org API.
Only the “abandoned” setting can be configured in the composer.json
file, under config.audit.abandoned
.
It defaults to report
in Composer 2.6, and to fail
from Composer 2.7 onwards.
fail
means abandoned packages will cause audits to fail with a non-zero code.ignore
means the audit command does not consider abandoned packages at all.report
means abandoned packages are reported as an error but do not cause the command to exit with a non-zero code.
As this command can not be configured through a config file, settings needs to be configured through parameters. Available parameters are:
--abandoned <fail|ignore|report>
: Behavior on abandoned packages. This flag overrides the config value and the environment variable.--format <json|plain|table|summary>
: Audit output format, the default is “table”.--ignore-severity <low|medium|high|critical>
: Ignore advisories of a certain severity level. Can be passed multiple times to ignore multiple severities.--locked
: Audit packages from the lock file, regardless of what is currently in vendor dir.--no-dev
: Disables auditing of require-dev packages.
For full details visit: https://getcomposer.org/doc/03-cli.md#audit
Shell files
- Paths:
paths: - '**.bash' - '**.sh' - '.github/workflows/shell.yml'
XML files
- Paths:
paths: - '**.xml' - '**.xml.dist' - '.github/workflows/xml.yml'
YAML files
- Config file(s):
.yamllint
- Paths:
paths: - '**.yml' - '**.yaml' - '!.github/workflows/**.yml' - '!.github/workflows/**.yaml'
Exceptions and Caveats
GitHub Actions YAML files are not linted using a YAML linter. The reason for this is that, opposed to other YAMl files, GHA will tell us when things are wrong. So, unless other YAML files are present in a repository, a YAML Lint is not used.
Other file types
- Paths:
paths: # OTHERS - /src/** - solid/lib/** - solid/templates/** -
A few words about GitHub Actions YAML
Filter patterns (in branch
, path
, and tag
entries)
Special characters can be used to filter path, branch, and tag values (similar to “globbing”).
For instance when paths
is used in a GHA to only trigger a workflow when specific files or folders have changed.
The following characters can be used:
*
: Matches zero or more characters, but does not match the/
character. For example,Octo*
matchesOctocat
but notOcto/cat
.**
: Matches zero or more of any character (including/
). For example,Octo**
matchesOctocat
andOcto/cat
.?
: Matches zero or one of the preceding character.+
: Matches one or more of the preceding character.[
and]
Matches one alphanumeric character listed in the brackets or included in ranges. Ranges can only includea-z
,A-Z
, and0-9
. For example, the range[0-9a-z]
matches any digit or lowercase letter. For example,[CB]at
matchesCat
andBat
and[1-2]00
matches100
and200
.!
: At the start of a pattern makes it negate previous positive patterns. It has no special meaning if not the first character.
If a pattern starts with *
, [
, and !
, or contains [
and/or ]
, the pattern MUST be quoted.
For full details visit: the Filter Pattern Cheat Sheet in the GitHub Workflow Syntax documentation
A few words about YAML
Strings (or: To quote, or not to quote?)
There are subtle differences in how YAML behaves when it encounters values that are unquote, single quoted, or double-quoted.
If a value is meant to be an integer, boolean or null value, it does not need quotes.
If a value is meant as a string, it is best to use single or double quotes, to avoid unexpected behaviour.
The main difference between single and double quotes is:
- Single quotes does not parse escape codes. For example,
'\n'
would be returned as the string “\n”. - Double quotes parse escape codes. “\n” would be returned as a line break (i.e. newline character)
So, if a value is meant to be a string, use single quotes, unless it contains escape codes that should be parsed.
For longer, or more complex strings, block Style and Chomping indicators can be used. These also allow to spread a string across multiple lines.
Multiline strings (“Blocks”)
TBD: Explain Blocks (edit text below)
Block Scalar Style
>
Replace newlines with spaces (“folded”)|
Keep newlines (“literal”)
The block style indicates how newlines inside the block should behave. If you would like them to be kept as newlines, use the literal style, indicated by a pipe (|). If instead you want them to be replaced by spaces, use the folded style, indicated by a right angle bracket (>). (To get a newline using the folded style, leave a blank line by putting two newlines in. Lines with extra indentation are also not folded.)
Block Chomping
- Single newline at end (“clip”)
-
No newline at end (“strip”)+
All newlines from end (“keep”)
The chomping indicator controls what should happen with newlines at the end of the string. The default, clip, puts a single newline at the end of the string. To remove all newlines, strip them by putting a minus sign (-) after the style indicator. Both clip and strip ignore how many newlines are actually at the end of the block; to keep them all put a plus sign (+) after the style indicator.
For full details visit: https://www.yaml.info/learn/quote.html