From ea939a2789deb303253e63417564449ec88aefc2 Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Thu, 25 Apr 2024 13:43:40 +0200 Subject: [PATCH] ITKDev: Added code style checking --- .github/workflows/pr.yml | 137 +++++++++++++++++++++++++++++++++++++++ .gitignore | 2 + CHANGELOG.md | 16 +++++ composer.json | 62 ++++++++++++++++++ package.json | 13 ++++ phpcs.xml.dist | 27 ++++++++ phpstan.neon | 20 ++++++ scripts/code-analysis | 35 ++++++++++ src/Service/Logger.php | 15 +++-- 9 files changed, 320 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/pr.yml create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 composer.json create mode 100644 package.json create mode 100644 phpcs.xml.dist create mode 100644 phpstan.neon create mode 100755 scripts/code-analysis diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..42565ef --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,137 @@ +on: pull_request +name: Review +jobs: + changelog: + runs-on: ubuntu-latest + name: Changelog should be updated + strategy: + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v2 + 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 + + test-composer-files: + name: Validate composer + runs-on: ubuntu-latest + strategy: + matrix: + php-versions: [ '8.1' ] + dependency-version: [ prefer-lowest, prefer-stable ] + steps: + - uses: actions/checkout@master + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: json + coverage: none + tools: composer:v2 + # https://github.com/shivammathur/setup-php#cache-composer-dependencies + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + - name: Validate composer files + run: | + composer validate --strict composer.json + # Check that dependencies resolve. + composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction + + php-coding-standards: + name: PHP coding standards + runs-on: ubuntu-latest + strategy: + matrix: + php-versions: [ '8.1' ] + steps: + - uses: actions/checkout@master + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: json + coverage: none + tools: composer:v2 + # https://github.com/shivammathur/setup-php#cache-composer-dependencies + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + - name: Install Dependencies + run: | + composer install --no-interaction --no-progress + - name: PHPCS + run: | + composer coding-standards-check/phpcs + + php-code-analysis: + name: PHP code analysis + runs-on: ubuntu-latest + strategy: + matrix: + php-versions: [ '8.1' ] + steps: + - uses: actions/checkout@master + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: json + coverage: none + tools: composer:v2 + # https://github.com/shivammathur/setup-php#cache-composer-dependencies + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + - name: Code analysis + run: | + ./scripts/code-analysis + + markdownlint: + runs-on: ubuntu-latest + name: markdownlint + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + - name: Cache yarn packages + uses: actions/cache@v2 + id: yarn-cache + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + - name: Yarn install + uses: actions/setup-node@v2 + with: + node-version: '20' + - run: yarn install + - name: markdownlint + run: yarn coding-standards-check/markdownlint 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/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a482c8e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ + +# OS2 Audit Change Log + +All notable changes to this project should be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +See ["how do I make a good changelog record?"](https://keepachangelog.com/en/1.0.0/#how) +before starting to add changes. Use example [placed in the end of the page](#example-of-change-log-record) + +## [Unreleased] + +- First version of the module + +[Unreleased]: https://github.com/OS2web/os2web_audit/compare/develop...HEAD diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..aed5abc --- /dev/null +++ b/composer.json @@ -0,0 +1,62 @@ +{ + "name": "os2web/os2web_audit", + "type": "drupal-module", + "description": "Drupal OS2 module that provides audit logging for Danish Municipalities", + "minimum-stability": "dev", + "prefer-stable": true, + "license": "EUPL-1.2", + "repositories": { + "drupal": { + "type": "composer", + "url": "https://packages.drupal.org/8" + }, + "assets": { + "type": "composer", + "url": "https://asset-packagist.org" + } + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", + "drupal/coder": "^8.3", + "mglaman/phpstan-drupal": "^1.1", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpunit/phpunit": "^9.5" + }, + "extra" : { + "composer-exit-on-patch-failure": false, + "enable-patching" : true, + "patches": { + } + }, + "scripts": { + "code-analysis/phpstan": [ + "phpstan analyse" + ], + "code-analysis": [ + "@code-analysis/phpstan" + ], + "coding-standards-check/phpcs": [ + "phpcs --standard=phpcs.xml.dist" + ], + "coding-standards-check": [ + "@coding-standards-check/phpcs" + ], + "coding-standards-apply/phpcs": [ + "phpcbf --standard=phpcs.xml.dist" + ], + "coding-standards-apply": [ + "@coding-standards-apply/phpcs" + ] + }, + "config": { + "sort-packages": true, + "allow-plugins": { + "phpstan/extension-installer": true, + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..52fcd34 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "license": "UNLICENSED", + "private": true, + "devDependencies": { + "markdownlint-cli": "^0.32.2" + }, + "scripts": { + "coding-standards-check/markdownlint": "yarn markdownlint --ignore LICENSE.md --ignore vendor --ignore node_modules '*.md' 'modules/os2forms_digital_post/**/*.md'", + "coding-standards-check": "yarn coding-standards-check/markdownlint", + "coding-standards-apply/markdownlint": "yarn markdownlint --ignore LICENSE.md --ignore vendor --ignore node_modules '*.md' 'modules/os2forms_digital_post/**/*.md' --fix", + "coding-standards-apply": "yarn coding-standards-apply/markdownlint" + } +} diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..07c8814 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,27 @@ + + + OS2Forms PHP Code Sniffer configuration + + . + vendor/ + node_modules/ + + modules/webform_embed/ + + modules/os2forms_webform_maps/modules/field_color/ + + + + + + + + + + + + + + + + diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..8ece9b1 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,20 @@ +parameters: + level: 6 + paths: + - modules/os2forms_digital_post/ + excludePaths: + # @see https://github.com/mglaman/drupal-check/issues/261#issuecomment-1030141772/ + - vendor + - '*/node_modules/*' + ignoreErrors: + - + # Ignore some weird errors reported by PHPStan + # @todo Investigate further + messages: + # These errors may be related to classes that don't add anything to their base class (e.g. `class BrugerFlerRelationType extends FlerRelationType {}`) + - '#expects (DataGovDk\\Model\\Core\\)(.+)(\|null)?, \1\2\\\2AType given.#' + - '#expects (DigitalPost\\MeMo\\)(.+)(\|null)?, \1\2\\\2AType given.#' + - '#expects (Oio\\(?:.+\\)*)(.+)(\|null)?, \1\2Type given.#' + - '#expects array<(DigitalPost\\MeMo\\)(.+)>(\|null)?, array given.#' + - '#should return (DigitalPost\\MeMo\\)(.+) but returns \1\2\\\2AType.#' + - '#should return (Oio\\Fjernprint\\)(.+) but returns \1\2Type.#' diff --git a/scripts/code-analysis b/scripts/code-analysis new file mode 100755 index 0000000..f8ace6c --- /dev/null +++ b/scripts/code-analysis @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +script_dir=$(pwd) +module_name=$(basename "$script_dir") +drupal_dir=vendor/drupal-module-code-analysis +# Relative to $drupal_dir +module_path=web/modules/contrib/$module_name + +cd "$script_dir" || exit + +drupal_composer() { + composer --working-dir="$drupal_dir" --no-interaction "$@" +} + +# Create new Drupal 9 project +if [ ! -f "$drupal_dir/composer.json" ]; then + composer --no-interaction create-project drupal/recommended-project:^9 "$drupal_dir" +fi +# Copy our code into the modules folder +mkdir -p "$drupal_dir/$module_path" +# https://stackoverflow.com/a/15373763 +rsync --archive --compress . --filter=':- .gitignore' --exclude "$drupal_dir" --exclude .git "$drupal_dir/$module_path" + +drupal_composer config minimum-stability dev + +# Allow ALL plugins +# https://getcomposer.org/doc/06-config.md#allow-plugins +drupal_composer config --no-plugins allow-plugins true + +drupal_composer require wikimedia/composer-merge-plugin +drupal_composer config extra.merge-plugin.include "$module_path/composer.json" +# https://www.drupal.org/project/drupal/issues/3220043#comment-14845434 +drupal_composer require --dev symfony/phpunit-bridge + +# Run PHPStan +(cd "$drupal_dir" && vendor/bin/phpstan --configuration="$module_path/phpstan.neon") diff --git a/src/Service/Logger.php b/src/Service/Logger.php index 1d28fb4..84c59ae 100644 --- a/src/Service/Logger.php +++ b/src/Service/Logger.php @@ -3,6 +3,7 @@ namespace Drupal\os2web_audit\Service; use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Session\AccountProxyInterface; use Drupal\os2web_audit\Form\PluginSettingsForm; use Drupal\os2web_audit\Form\SettingsForm; use Drupal\os2web_audit\Plugin\LoggerManager; @@ -17,6 +18,7 @@ class Logger { public function __construct( private readonly LoggerManager $loggerManager, private readonly ConfigFactoryInterface $configFactory, + private readonly AccountProxyInterface $currentUser, ) { } @@ -37,7 +39,7 @@ public function __construct( * * @throws \Drupal\Component\Plugin\Exception\PluginException */ - public function info(string $type, int $timestamp, string $line, bool $logUser = false, array $metadata = []): void { + public function info(string $type, int $timestamp, string $line, bool $logUser = FALSE, array $metadata = []): void { $this->log($type, $timestamp, $line, $logUser, $metadata + ['level' => 'info']); } @@ -58,7 +60,7 @@ public function info(string $type, int $timestamp, string $line, bool $logUser = * * @throws \Drupal\Component\Plugin\Exception\PluginException */ - public function error(string $type, int $timestamp, string $line, bool $logUser = false, array $metadata = []): void { + public function error(string $type, int $timestamp, string $line, bool $logUser = FALSE, array $metadata = []): void { $this->log($type, $timestamp, $line, $logUser, $metadata + ['level' => 'error']); } @@ -79,19 +81,18 @@ public function error(string $type, int $timestamp, string $line, bool $logUser * * @throws \Drupal\Component\Plugin\Exception\PluginException */ - private function log(string $type, int $timestamp, string $line, bool $logUser = false, array $metadata = []): void { + private function log(string $type, int $timestamp, string $line, bool $logUser = FALSE, array $metadata = []): void { $config = $this->configFactory->get(SettingsForm::$configName); $plugin_id = $config->get('provider'); - // @todo: default logger (file) - // @todo: Fallback logger on error. + // @todo default logger (file) + // @todo Fallback logger on error. $configuration = $this->configFactory->get(PluginSettingsForm::getConfigName())->get($plugin_id); $logger = $this->loggerManager->createInstance($plugin_id, $configuration ?? []); if ($logUser) { // Add user id to the log message metadata. - $user = \Drupal::currentUser(); - $metadata['userId'] = $user->id(); + $metadata['userId'] = $this->currentUser->id(); } $logger->log($type, $timestamp, $line, $metadata);