diff --git a/CI/linters/phpcs.yml b/CI/linters/phpcs.yml new file mode 100644 index 0000000..fcbb574 --- /dev/null +++ b/CI/linters/phpcs.yml @@ -0,0 +1,49 @@ +phpcs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "8.2" + + - name: Cache Composer + uses: actions/cache@v4 + with: + path: vendor + key: composer-${{ hashFiles('composer.lock') }} + restore-keys: composer- + + - name: Install dependencies + run: composer install --no-interaction --prefer-dist + + - name: Run phpcs + run: | + set -euo pipefail + + CONFIG_FOUND=0 + for cfg in phpcs.xml phpcs.xml.dist .phpcs.xml .phpcs.xml.dist; do + if [[ -f "$cfg" ]]; then + CONFIG_FOUND=1 + break + fi + done + + if [[ $CONFIG_FOUND -eq 0 ]]; then + echo "::error::No phpcs ruleset found (expected phpcs.xml, phpcs.xml.dist, .phpcs.xml, or .phpcs.xml.dist)" + exit 1 + fi + + if [[ -x "vendor/bin/phpcs" ]]; then + PHPCS="vendor/bin/phpcs" + else + PHPCS="phpcs" + fi + + if "$PHPCS"; then + echo "✅ phpcs passed" + else + echo "❌ phpcs found issues" + exit 1 + fi diff --git a/README.md b/README.md index 2d2ca2d..dc435cf 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ that projects compose into their own workflows. | ktlint | linters | [CI/linters/ktlint.yml](https://github.com/prog-time/workflows/blob/main/CI/linters/ktlint.yml) | | markdownlint | linters | [CI/linters/markdownlint.yml](https://github.com/prog-time/workflows/blob/main/CI/linters/markdownlint.yml) | | mermaid-cli | linters | [CI/linters/mermaid.yml](https://github.com/prog-time/workflows/blob/main/CI/linters/mermaid.yml) | +| phpcs | linters | [CI/linters/phpcs.yml](https://github.com/prog-time/workflows/blob/main/CI/linters/phpcs.yml) | | RuboCop | linters | [CI/linters/rubocop.yml](https://github.com/prog-time/workflows/blob/main/CI/linters/rubocop.yml) | | Ruff | linters | [CI/linters/ruff.yml](https://github.com/prog-time/workflows/blob/main/CI/linters/ruff.yml) | | ShellCheck | linters | [CI/linters/shellcheck.yml](https://github.com/prog-time/workflows/blob/main/CI/linters/shellcheck.yml) | @@ -77,6 +78,7 @@ Workflows/ │ │ │ ├── ktlint.yml │ │ │ ├── markdownlint.yml │ │ │ ├── mermaid.yml +│ │ │ ├── phpcs.yml │ │ │ ├── rubocop.yml │ │ │ ├── ruff.yml │ │ │ ├── shellcheck.yml @@ -107,6 +109,7 @@ Workflows/ │ │ ├── ktlint.sh │ │ ├── markdownlint.sh │ │ ├── mermaid.sh +│ │ ├── phpcs.sh │ │ ├── rubocop.sh │ │ ├── ruff.sh │ │ ├── shellcheck.sh @@ -131,6 +134,7 @@ Workflows/ │ │ ├── hadolint.bats │ │ ├── htmlhint.bats │ │ ├── markdownlint.bats +│ │ ├── phpcs.bats │ │ ├── shellcheck.bats │ │ ├── stylelint.bats │ │ └── yamllint.bats @@ -226,6 +230,7 @@ shellcheck: | `CI/linters/ktlint.yml` | [ktlint](https://pinterest.github.io/ktlint) | Kotlin | | `CI/linters/markdownlint.yml` | [markdownlint](https://github.com/DavidAnson/markdownlint) | Markdown files | | `CI/linters/mermaid.yml` | [mermaid-cli](https://github.com/mermaid-js/mermaid-cli) | Mermaid diagrams | +| `CI/linters/phpcs.yml` | [phpcs](https://github.com/PHPCSStandards/PHP_CodeSniffer) | PHP (PSR-12 and custom rulesets) | | `CI/linters/rubocop.yml` | [rubocop](https://rubocop.org) | Ruby | | `CI/linters/ruff.yml` | [ruff](https://docs.astral.sh/ruff) | Python | | `CI/linters/shellcheck.yml` | [shellcheck](https://www.shellcheck.net) | Shell scripts | diff --git a/scripts/CI/linters/phpcs.yml b/scripts/CI/linters/phpcs.yml new file mode 100644 index 0000000..1fbd489 --- /dev/null +++ b/scripts/CI/linters/phpcs.yml @@ -0,0 +1,22 @@ +phpcs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "8.2" + + - name: Cache Composer + uses: actions/cache@v4 + with: + path: vendor + key: composer-${{ hashFiles('composer.lock') }} + restore-keys: composer- + + - name: Install dependencies + run: composer install --no-interaction --prefer-dist + + - name: Run phpcs + run: bash scripts/shell/linters/phpcs.sh diff --git a/scripts/shell/linters/phpcs.sh b/scripts/shell/linters/phpcs.sh new file mode 100644 index 0000000..3b1b4ff --- /dev/null +++ b/scripts/shell/linters/phpcs.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +set -euo pipefail + +CONFIG_FOUND=0 +for cfg in phpcs.xml phpcs.xml.dist .phpcs.xml .phpcs.xml.dist; do + if [[ -f "$cfg" ]]; then + CONFIG_FOUND=1 + break + fi +done + +if [[ $CONFIG_FOUND -eq 0 ]]; then + echo "::error::No phpcs ruleset found (expected phpcs.xml, phpcs.xml.dist, .phpcs.xml, or .phpcs.xml.dist)" + exit 1 +fi + +if [[ -x "vendor/bin/phpcs" ]]; then + PHPCS="vendor/bin/phpcs" +else + PHPCS="phpcs" +fi + +if "$PHPCS"; then + echo "✅ phpcs passed" +else + echo "❌ phpcs found issues" + exit 1 +fi diff --git a/tests/linters/phpcs.bats b/tests/linters/phpcs.bats new file mode 100644 index 0000000..6fd731c --- /dev/null +++ b/tests/linters/phpcs.bats @@ -0,0 +1,47 @@ +#!/usr/bin/env bats + +load "../helpers/common" + +SCRIPT="$BATS_TEST_DIRNAME/../../scripts/shell/linters/phpcs.sh" + +setup() { + setup_test_dir + mkdir -p "$TEST_DIR/bin" + export PATH="$TEST_DIR/bin:$PATH" +} + +teardown() { + teardown_test_dir +} + +make_phpcs_stub() { + local exit_code="$1" + cat > "$TEST_DIR/bin/phpcs" <