Skip to content

Redesign, Bugfixes, more improvements #674

Redesign, Bugfixes, more improvements

Redesign, Bugfixes, more improvements #674

Workflow file for this run

name: PHP CI
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
workflow_dispatch:
permissions:
contents: read
pull-requests: write
jobs:
# ─────────────────────────────────────────────
# 1. Build & Validate (PHP 8.1 – 8.4)
# ─────────────────────────────────────────────
build:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['8.1', '8.2', '8.3', '8.4']
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Setup PHP ${{ matrix.php-version }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: mbstring, pdo, pdo_mysql, json, curl, gd, intl
coverage: none
- name: Validate composer.json and composer.lock
run: composer validate --strict
- name: Cache Composer packages
uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-${{ matrix.php-version }}-
- name: Update lock file
run: composer update --lock
- name: Install dependencies
run: composer install --prefer-dist --no-progress
- name: PHP Lint
run: find . -name "*.php" -not -path "./vendor/*" -print0 | xargs -0 -n1 php -l
# ─────────────────────────────────────────────
# 2. Build PHP 8.5 (experimentell, blockiert nicht)
# ─────────────────────────────────────────────
build-experimental:
name: "experimental build (8.5)"
if: false # Pausiert – Zeile entfernen zum Reaktivieren
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Setup PHP 8.5
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
extensions: mbstring, pdo, pdo_mysql, json, curl, gd, intl
coverage: none
- name: Validate composer.json and composer.lock
run: composer validate --strict
- name: Cache Composer packages
uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-php-8.5-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-8.5-
- name: Update lock file
run: composer update --lock
- name: Install dependencies
run: composer install --prefer-dist --no-progress
- name: PHP Lint
run: find . -name "*.php" -not -path "./vendor/*" -print0 | xargs -0 -n1 php -l
# ─────────────────────────────────────────────
# 3. Security Audit
# ─────────────────────────────────────────────
security-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
- name: Install dependencies
run: composer install --prefer-dist --no-progress
- name: Check for known vulnerabilities
run: composer audit
# ─────────────────────────────────────────────
# 4. PHPStan – Statische Analyse
# ─────────────────────────────────────────────
phpstan:
runs-on: ubuntu-latest
needs: build
if: ${{ !cancelled() }}
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
extensions: mbstring, pdo, pdo_mysql, json, curl, gd, intl
- name: Cache Composer packages
uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-php-8.4-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-8.4-
- name: Install dependencies
run: composer install --prefer-dist --no-progress
# Inline-Annotations in geänderten Dateien im PR-Diff
- name: PHPStan – Inline Annotations
run: vendor/bin/phpstan analyse --no-progress --error-format=github || true
# JSON-Output für den PR-Kommentar
- name: PHPStan – Report generieren
id: phpstan
run: |
set +e
vendor/bin/phpstan analyse --no-progress --error-format=json > phpstan-result.json 2>/dev/null
echo "exit_code=$?" >> "$GITHUB_OUTPUT"
- name: PHPStan-Ergebnis im PR posten
if: always() && github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const exitCode = '${{ steps.phpstan.outputs.exit_code }}';
let json;
try {
json = JSON.parse(fs.readFileSync('phpstan-result.json', 'utf8'));
} catch {
json = null;
}
// ── Kommentar bauen ──
let body = '<!-- phpstan-report -->\n';
if (exitCode === '0') {
body += '## ✅ Keine Fehler\n\n';
body += 'Keine Probleme gefunden. 🎉\n';
} else if (json?.files && Object.keys(json.files).length > 0) {
const files = json.files;
const totalErrors = json.totals?.file_errors || 0;
const fileCount = Object.keys(files).length;
body += `## ⚠️ ${totalErrors} Fehler in ${fileCount} Dateien\n\n`;
// Runner-Workspace-Pfad entfernen, Projektpfade beibehalten
const workspacePrefix = process.env.GITHUB_WORKSPACE ? process.env.GITHUB_WORKSPACE + '/' : '';
const shortPath = (p) => workspacePrefix ? p.replace(workspacePrefix, '') : p;
// ── Zusammenfassung (immer sichtbar) ──
body += '| Datei | Fehler |\n';
body += '|-------|-------:|\n';
for (const [filePath, data] of Object.entries(files)) {
body += `| \`${shortPath(filePath)}\` | ${data.messages.length} |\n`;
}
// ── Details pro Datei (aufklappbar) ──
body += '\n---\n\n';
for (const [filePath, data] of Object.entries(files)) {
const short = shortPath(filePath);
body += `<details>\n<summary><strong>${short}</strong> (${data.messages.length} Fehler)</summary>\n\n`;
body += '| Zeile | Beschreibung |\n';
body += '|------:|--------------|\n';
for (const msg of data.messages) {
const desc = msg.message.replace(/\|/g, '\\|');
body += `| ${msg.line} | ${desc} |\n`;
}
body += '\n</details>\n\n';
}
} else {
body += '## ❌ Unbekannter Fehler\n\n';
body += 'Ergebnis konnte nicht verarbeitet werden. Siehe [Workflow-Log](' +
`${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}).\n`;
}
// ── Alten Kommentar ersetzen ──
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const old = comments.find(c => c.body?.includes('<!-- phpstan-report -->'));
if (old) {
await github.rest.issues.deleteComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: old.id,
});
}
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
});
- name: PHPStan Exit Code
if: always()
run: exit ${{ steps.phpstan.outputs.exit_code }}