diff --git a/.github/workflows/changelog.yaml b/.github/workflows/changelog.yaml new file mode 100644 index 0000000..fead572 --- /dev/null +++ b/.github/workflows/changelog.yaml @@ -0,0 +1,29 @@ +# Do not edit this file! Make a pull request on changing +# github/workflows/changelog.yaml in +# https://github.com/itk-dev/devops_itkdev-docker if need be. + +### ### Changelog +### +### Checks that changelog has been updated + +name: Changelog + +on: + pull_request: + +jobs: + changelog: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 2 + + - name: Git fetch + run: git fetch + + - name: Check that changelog has been updated. + run: git diff --exit-code origin/${{ github.base_ref }} -- CHANGELOG.md && exit 1 || exit 0 diff --git a/.github/workflows/composer.yaml b/.github/workflows/composer.yaml new file mode 100644 index 0000000..5fb0ef0 --- /dev/null +++ b/.github/workflows/composer.yaml @@ -0,0 +1,85 @@ +# Do not edit this file! Make a pull request on changing +# github/workflows/composer.yaml in +# https://github.com/itk-dev/devops_itkdev-docker if need be. + +### ### Composer +### +### Validates composer.json and checks that it's normalized. +### +### #### Assumptions +### +### 1. A docker compose service named `phpfpm` can be run and `composer` can be +### run inside the `phpfpm` service. +### 2. [ergebnis/composer-normalize](https://github.com/ergebnis/composer-normalize) +### is a dev requirement in `composer.json`: +### +### ``` shell +### docker compose run --rm phpfpm composer require --dev ergebnis/composer-normalize +### ``` +### +### Normalize `composer.json` by running +### +### ``` shell +### docker compose run --rm phpfpm composer normalize +### ``` + +name: Composer + +env: + COMPOSE_USER: root + +on: + pull_request: + push: + branches: + - main + - develop + +jobs: + composer-validate: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v5 + + - name: Create docker network + run: | + docker network create frontend + + - run: | + docker compose run --rm phpfpm composer validate --strict + + composer-normalized: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v5 + + - name: Create docker network + run: | + docker network create frontend + + - run: | + docker compose run --rm --env COMPOSER=composer.lenient.json phpfpm composer init --no-interaction + docker compose run --rm --env COMPOSER=composer.lenient.json phpfpm composer config --no-plugins allow-plugins.mglaman/composer-drupal-lenient true + docker compose run --rm --env COMPOSER=composer.lenient.json phpfpm composer require mglaman/composer-drupal-lenient + docker compose run --rm --env COMPOSER=composer.lenient.json phpfpm rm composer.lenient.* + + docker compose run --rm phpfpm composer install + docker compose run --rm phpfpm composer normalize --dry-run + + composer-audit: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v5 + + - name: Create docker network + run: | + docker network create frontend + + - run: | + docker compose run --rm phpfpm composer audit diff --git a/.github/workflows/markdown.yaml b/.github/workflows/markdown.yaml new file mode 100644 index 0000000..ae83163 --- /dev/null +++ b/.github/workflows/markdown.yaml @@ -0,0 +1,44 @@ +# Do not edit this file! Make a pull request on changing +# github/workflows/markdown.yaml in +# https://github.com/itk-dev/devops_itkdev-docker if need be. + +### ### Markdown +### +### Lints Markdown files (`**/*.md`) in the project. +### +### [markdownlint-cli configuration +### files](https://github.com/igorshubovych/markdownlint-cli?tab=readme-ov-file#configuration), +### `.markdownlint.jsonc` and `.markdownlintignore`, control what is actually +### linted and how. +### +### #### Assumptions +### +### 1. A docker compose service named `markdownlint` for running `markdownlint` +### (from +### [markdownlint-cli](https://github.com/igorshubovych/markdownlint-cli)) +### exists. + +name: Markdown + +on: + pull_request: + push: + branches: + - main + - develop + +jobs: + markdown-lint: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Create docker network + run: | + docker network create frontend + + - run: | + docker compose run --rm markdownlint markdownlint '**/*.md' diff --git a/.github/workflows/php.yaml b/.github/workflows/php.yaml new file mode 100644 index 0000000..3b6415d --- /dev/null +++ b/.github/workflows/php.yaml @@ -0,0 +1,64 @@ +# Do not edit this file! Make a pull request on changing +# github/workflows/drupal-module/php.yaml in +# https://github.com/itk-dev/devops_itkdev-docker if need be. + +### ### Drupal module PHP +### +### Checks that PHP code adheres to the [Drupal coding +### standards](https://www.drupal.org/docs/develop/standards). +### +### #### Assumptions +### +### 1. A docker compose service named `phpfpm` can be run and `composer` can be +### run inside the `phpfpm` service. +### 2. [drupal/coder](https://www.drupal.org/project/coder) is a dev requirement +### in `composer.json`: +### +### ``` shell +### docker compose run --rm phpfpm composer require --dev drupal/coder +### ``` +### +### Clean up and check code by running +### +### ``` shell +### docker compose run --rm phpfpm vendor/bin/phpcbf +### docker compose run --rm phpfpm vendor/bin/phpcs +### ``` +### +### > [!NOTE] +### > The template adds `.phpcs.xml.dist` as [a configuration file for +### > PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#using-a-default-configuration-file) +### > and this makes it possible to override the actual configuration used in a +### > project by adding a more important configuration file, e.g. `.phpcs.xml`. + +name: PHP + +env: + COMPOSE_USER: root + +on: + pull_request: + push: + branches: + - main + - develop + +jobs: + coding-standards: + name: PHP - Check Coding Standards + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: Create docker network + run: | + docker network create frontend + + - run: | + docker compose run --rm --env COMPOSER=composer.lenient.json phpfpm composer init --no-interaction + docker compose run --rm --env COMPOSER=composer.lenient.json phpfpm composer config --no-plugins allow-plugins.mglaman/composer-drupal-lenient true + docker compose run --rm --env COMPOSER=composer.lenient.json phpfpm composer require mglaman/composer-drupal-lenient + docker compose run --rm --env COMPOSER=composer.lenient.json phpfpm rm composer.lenient.* + + docker compose run --rm phpfpm composer install + docker compose run --rm phpfpm vendor/bin/phpcs diff --git a/.github/workflows/project.yaml b/.github/workflows/project.yaml new file mode 100644 index 0000000..da5ae3d --- /dev/null +++ b/.github/workflows/project.yaml @@ -0,0 +1,30 @@ +name: Project + +env: + COMPOSE_USER: root + +on: + pull_request: + push: + branches: + - main + - develop + +jobs: + code-analysis: + name: PHP - Code analysis + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - run: | + ./scripts/code-analysis + + rector: + name: PHP - Rector + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - run: | + ./scripts/rector diff --git a/.github/workflows/yaml.yaml b/.github/workflows/yaml.yaml new file mode 100644 index 0000000..631e525 --- /dev/null +++ b/.github/workflows/yaml.yaml @@ -0,0 +1,41 @@ +# Do not edit this file! Make a pull request on changing +# github/workflows/yaml.yaml in +# https://github.com/itk-dev/devops_itkdev-docker if need be. + +### ### YAML +### +### Validates YAML files. +### +### #### Assumptions +### +### 1. A docker compose service named `prettier` for running +### [Prettier](https://prettier.io/) exists. +### +### #### Symfony YAML +### +### Symfony's YAML config files use 4 spaces for indentation and single quotes. +### Therefore we use a [Prettier configuration +### file](https://prettier.io/docs/configuration), `.prettierrc.yaml`, to make +### Prettier format YAML files in the `config/` folder like Symfony expects. + +name: YAML + +on: + pull_request: + push: + branches: + - main + - develop + +jobs: + yaml-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: Create docker network + run: | + docker network create frontend + + - run: | + docker compose run --rm prettier '**/*.{yml,yaml}' --check diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d8a7996 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +composer.lock +vendor/ diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc new file mode 100644 index 0000000..0253096 --- /dev/null +++ b/.markdownlint.jsonc @@ -0,0 +1,22 @@ +// This file is copied from config/markdown/.markdownlint.jsonc in https://github.com/itk-dev/devops_itkdev-docker. +// Feel free to edit the file, but consider making a pull request if you find a general issue with the file. + +// markdownlint-cli configuration file (cf. https://github.com/igorshubovych/markdownlint-cli?tab=readme-ov-file#configuration) +{ + "default": true, + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md013.md + "line-length": { + "line_length": 120, + "code_blocks": false, + "tables": false + }, + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md024.md + "no-duplicate-heading": { + "siblings_only": true + }, + // https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections#creating-a-collapsed-section + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md033.md + "no-inline-html": { + "allowed_elements": ["details", "summary"] + } +} diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 0000000..d143ace --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,12 @@ +# This file is copied from config/markdown/.markdownlintignore in https://github.com/itk-dev/devops_itkdev-docker. +# Feel free to edit the file, but consider making a pull request if you find a general issue with the file. + +# https://github.com/igorshubovych/markdownlint-cli?tab=readme-ov-file#ignoring-files +vendor/ +node_modules/ +LICENSE.md +# Drupal +web/*.md +web/core/ +web/libraries/ +web/*/contrib/ diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist new file mode 100644 index 0000000..083aa41 --- /dev/null +++ b/.phpcs.xml.dist @@ -0,0 +1,33 @@ + + + + + + The coding standard. + + . + + + vendor + rector.php + + + + + + + + + + + + + + + + + + + src/Settings/ + + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b337319 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +[Unreleased]: https://github.com/itk-dev/os2forms_f2 diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..b4d390e --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,118 @@ +# https://taskfile.dev + +version: "3" + +tasks: + compose: + cmds: + - docker compose {{.TASK_ARGS}} {{.CLI_ARGS}} + internal: true + + composer: + desc: Run composer inside docker compose setup, e.g. `task {{.TASK}} -- install` + cmds: + - task: compose + vars: + TASK_ARGS: run --rm phpfpm composer {{.TASK_ARGS}} + + composer:install: + desc: Run composer inside docker compose setup, e.g. `task {{.TASK}} -- install` + cmds: + - rm -fr composer.lock vendor + - | + # Create a temporary composer file to install https://github.com/mglaman/composer-drupal-lenient before the real install needs it. + docker compose run --rm --env COMPOSER=composer.lenient.json phpfpm composer init --no-interaction + docker compose run --rm --env COMPOSER=composer.lenient.json phpfpm composer config --no-plugins allow-plugins.mglaman/composer-drupal-lenient true + docker compose run --rm --env COMPOSER=composer.lenient.json phpfpm composer require mglaman/composer-drupal-lenient + docker compose run --rm --env COMPOSER=composer.lenient.json phpfpm rm composer.lenient.* + + - task: composer + vars: + TASK_ARGS: install + + coding-standards:apply: + desc: "Apply coding standards" + cmds: + - task: coding-standards:composer:apply + - task: coding-standards:markdown:apply + - task: coding-standards:php:apply + - task: coding-standards:yaml:apply + silent: true + + coding-standards:check: + desc: "Check coding standards" + cmds: + - task: coding-standards:composer:check + - task: coding-standards:markdown:check + - task: coding-standards:php:check + - task: coding-standards:yaml:check + silent: true + + coding-standards:composer:apply: + desc: "Apply coding standards for composer" + cmds: + - task: compose + vars: + TASK_ARGS: run --rm phpfpm composer normalize + + coding-standards:composer:check: + - task: coding-standards:composer:apply + - task: compose + vars: + TASK_ARGS: run --rm phpfpm composer normalize --dry-run + - task: compose + vars: + TASK_ARGS: run --rm phpfpm composer validate + + coding-standards:markdown:apply: + desc: "Apply coding standards for Markdown" + cmds: + # Cf. .github/workflows/markdown.yaml + - docker compose run --rm markdownlint markdownlint '**/*.md' --fix + + coding-standards:markdown:check: + desc: "Apply and check coding standards for Markdown" + cmds: + - task: coding-standards:markdown:apply + # Cf. .github/workflows/markdown.yaml + - docker compose run --rm markdownlint markdownlint '**/*.md' + + coding-standards:php:apply: + desc: "Apply coding standards for PHP" + cmds: + # Cf. .github/workflows/php.yaml + - docker compose run --rm phpfpm vendor/bin/phpcbf + silent: true + + coding-standards:php:check: + desc: "Apply and check coding standards for PHP" + cmds: + - task: coding-standards:php:apply + # Cf. .github/workflows/php.yaml + - docker compose run --rm phpfpm vendor/bin/phpcs + silent: true + + coding-standards:yaml:apply: + desc: "Apply coding standards for YAML" + cmds: + # Cf. .github/workflows/yaml.yaml + - docker compose run --rm prettier '**/*.{yml,yaml}' --write + + coding-standards:yaml:check: + desc: "Apply coding standards for YAML" + cmds: + - task: coding-standards:yaml:apply + # Cf. .github/workflows/yaml.yaml + - docker compose run --rm prettier '**/*.{yml,yaml}' --check + + test: + cmds: + - docker compose run --env PHP_XDEBUG_MODE --env PHP_XDEBUG_WITH_REQUEST + --env PHP_IDE_CONFIG --rm phpfpm vendor/bin/phpunit {{.CLI_ARGS}} + + xdebug:test: + cmds: + - PHP_XDEBUG_MODE=debug PHP_XDEBUG_WITH_REQUEST=yes + PHP_IDE_CONFIG=serverName=localhost docker compose run --env + PHP_XDEBUG_MODE --env PHP_XDEBUG_WITH_REQUEST --env PHP_IDE_CONFIG --rm + phpfpm vendor/bin/phpunit {{.CLI_ARGS}} diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..c4f59d0 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,32 @@ +services: + phpfpm: + image: itkdev/php8.3-fpm:latest + user: ${COMPOSE_USER:-deploy} + profiles: + - dev + volumes: + - .:/app-os2forms_f2 + working_dir: /app-os2forms_f2 + environment: + # https://getcomposer.org/doc/03-cli.md#composer-no-security-blocking + # @see https://github.com/OS2Forms/os2forms/issues/245 + COMPOSER_NO_SECURITY_BLOCKING: 1 + + # Code checks tools + markdownlint: + image: itkdev/markdownlint + profiles: + - dev + volumes: + - ./:/md + + prettier: + # Prettier does not (yet, fcf. + # https://github.com/prettier/prettier/issues/15206) have an official + # docker image. + # https://hub.docker.com/r/jauderho/prettier is good candidate (cf. https://hub.docker.com/search?q=prettier&sort=updated_at&order=desc) + image: jauderho/prettier + profiles: + - dev + volumes: + - ./:/work diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..8c574c2 --- /dev/null +++ b/composer.json @@ -0,0 +1,31 @@ +{ + "name": "os2forms/os2forms_f2", + "description": "OS2Forms: F2 integration", + "license": "MIT", + "type": "drupal-module", + "require": { + "itk-dev/f2-api-client": "dev-f2-api-client as 1.0.0", + "os2forms/os2forms": "^5.0" + }, + "require-dev": { + "drupal/coder": "^9.0", + "ergebnis/composer-normalize": "^2.52" + }, + "repositories": [ + { + "type": "composer", + "url": "https://packages.drupal.org/8" + } + ], + "minimum-stability": "dev", + "config": { + "allow-plugins": { + "cweagans/composer-patches": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "ergebnis/composer-normalize": true, + "mglaman/composer-drupal-lenient": true, + "simplesamlphp/composer-module-installer": true, + "zaporylie/composer-drupal-optimizations": true + } + } +} diff --git a/os2forms_f2.info.yml b/os2forms_f2.info.yml new file mode 100644 index 0000000..3e5f5ee --- /dev/null +++ b/os2forms_f2.info.yml @@ -0,0 +1,7 @@ +name: "os2forms_f2" +type: module +description: "OS2Forms: F2 integration" +package: OS2Forms +core_version_requirement: ^10 || ^11 +dependencies: + - os2forms:os2forms diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..716b6c6 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,14 @@ +parameters: + paths: + - . + level: 5 + customRulesetUsed: true + reportUnmatchedIgnoredErrors: false + excludePaths: + - rector.php + # Ignore any vendor folder (https://phpstan.org/user-guide/ignoring-errors#excluding-whole-files) + - vendor (?) + + ignoreErrors: + - '#Call to method Drupal\\Core\\Entity\\Query\\QueryInterface::accessCheck\(\) will always evaluate to true.#' + - '#Call to method PHPUnit\\Framework\\Assert::assertTrue\(\) with true will always evaluate to true.#' diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..44fe530 --- /dev/null +++ b/rector.php @@ -0,0 +1,21 @@ +withPaths([ + __DIR__ . '/src', + // __DIR__ . '/tests', + ]) + ->withSets([ + Drupal10SetList::DRUPAL_10, + ]) + ->withPhpSets(php83: TRUE) + ->withTypeCoverageLevel(0); diff --git a/scripts/.env b/scripts/.env new file mode 100644 index 0000000..da1e572 --- /dev/null +++ b/scripts/.env @@ -0,0 +1,2 @@ +COMPOSE_PROJECT_NAME=drupal-module +MODULE_NAME=os2forms_f2 diff --git a/scripts/base b/scripts/base new file mode 100644 index 0000000..def2c9d --- /dev/null +++ b/scripts/base @@ -0,0 +1,138 @@ +#!/usr/bin/env bash +set -o errexit -o errtrace -o noclobber -o nounset -o pipefail +IFS=$'\n\t' + +execute_name=execute + +usage() { + (cat >&2 </dev/null); then + (cat >&2 <&2 <