192 lines
6.8 KiB
YAML
192 lines
6.8 KiB
YAML
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
#
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
#
|
|
# FILE INFORMATION
|
|
# DEFGROUP: Gitea.Workflow
|
|
# INGROUP: MokoStandards.CI
|
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
|
# PATH: /.gitea/workflows/ci-generic.yml
|
|
# VERSION: 01.00.00
|
|
# BRIEF: CI pipeline — lint, validate, and test for generic projects (PHP + Node.js)
|
|
|
|
name: "Generic: Project CI"
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
env:
|
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
|
|
jobs:
|
|
# ── Lint & Validate ───────────────────────────────────────────────────
|
|
lint:
|
|
name: Lint & Validate
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Detect toolchain
|
|
id: detect
|
|
run: |
|
|
HAS_PHP=false
|
|
HAS_NODE=false
|
|
[ -f "composer.json" ] && HAS_PHP=true
|
|
[ -f "package.json" ] && HAS_NODE=true
|
|
echo "has_php=$HAS_PHP" >> "$GITHUB_OUTPUT"
|
|
echo "has_node=$HAS_NODE" >> "$GITHUB_OUTPUT"
|
|
echo "Toolchain: PHP=$HAS_PHP Node=$HAS_NODE"
|
|
|
|
- name: Setup PHP
|
|
if: steps.detect.outputs.has_php == 'true'
|
|
run: |
|
|
if ! command -v php &> /dev/null; then
|
|
sudo apt-get update -qq
|
|
sudo apt-get install -y -qq php-cli php-mbstring php-xml >/dev/null 2>&1
|
|
fi
|
|
php -v
|
|
|
|
- name: Setup Node.js
|
|
if: steps.detect.outputs.has_node == 'true'
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
|
|
- name: Install PHP dependencies
|
|
if: steps.detect.outputs.has_php == 'true'
|
|
run: |
|
|
if [ -f "composer.json" ]; then
|
|
composer install --no-interaction --prefer-dist --quiet 2>/dev/null || true
|
|
fi
|
|
|
|
- name: Install Node.js dependencies
|
|
if: steps.detect.outputs.has_node == 'true'
|
|
run: |
|
|
if [ -f "package.json" ]; then
|
|
npm ci --quiet 2>/dev/null || npm install --quiet 2>/dev/null || true
|
|
fi
|
|
|
|
- name: PHP syntax check
|
|
if: steps.detect.outputs.has_php == 'true'
|
|
run: |
|
|
ERRORS=0
|
|
while IFS= read -r -d '' file; do
|
|
if ! php -l "$file" 2>&1 | grep -q "No syntax errors"; then
|
|
echo "::error file=${file}::PHP syntax error"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
done < <(find . -name "*.php" -not -path "./.git/*" -not -path "./vendor/*" -not -path "./node_modules/*" -print0)
|
|
|
|
echo "## PHP Lint" >> $GITHUB_STEP_SUMMARY
|
|
if [ "$ERRORS" -eq 0 ]; then
|
|
echo "All PHP files passed syntax check." >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "${ERRORS} file(s) with syntax errors." >> $GITHUB_STEP_SUMMARY
|
|
exit 1
|
|
fi
|
|
|
|
- name: TypeScript/JavaScript lint
|
|
if: steps.detect.outputs.has_node == 'true'
|
|
run: |
|
|
if [ -f "node_modules/.bin/eslint" ]; then
|
|
npx eslint src/ --quiet 2>&1 || { echo "::error::ESLint errors found"; exit 1; }
|
|
echo "## ESLint" >> $GITHUB_STEP_SUMMARY
|
|
echo "All files passed ESLint." >> $GITHUB_STEP_SUMMARY
|
|
elif [ -f ".eslintrc.json" ] || [ -f ".eslintrc.js" ] || [ -f "eslint.config.js" ]; then
|
|
echo "::warning::ESLint config found but eslint not installed"
|
|
else
|
|
echo "No ESLint configured — skipping"
|
|
fi
|
|
|
|
- name: TypeScript compile check
|
|
if: steps.detect.outputs.has_node == 'true'
|
|
run: |
|
|
if [ -f "tsconfig.json" ] && [ -f "node_modules/.bin/tsc" ]; then
|
|
npx tsc --noEmit 2>&1 || { echo "::error::TypeScript compilation errors"; exit 1; }
|
|
echo "## TypeScript" >> $GITHUB_STEP_SUMMARY
|
|
echo "TypeScript compilation passed." >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
- name: PHPStan static analysis
|
|
if: steps.detect.outputs.has_php == 'true'
|
|
run: |
|
|
if [ -f "phpstan.neon" ] && [ -f "vendor/bin/phpstan" ]; then
|
|
vendor/bin/phpstan analyse --no-progress 2>&1 || { echo "::warning::PHPStan found issues"; }
|
|
fi
|
|
|
|
# ── Tests ─────────────────────────────────────────────────────────────
|
|
test:
|
|
name: Tests
|
|
runs-on: ubuntu-latest
|
|
needs: lint
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Detect toolchain
|
|
id: detect
|
|
run: |
|
|
HAS_PHP=false
|
|
HAS_NODE=false
|
|
[ -f "composer.json" ] && HAS_PHP=true
|
|
[ -f "package.json" ] && HAS_NODE=true
|
|
echo "has_php=$HAS_PHP" >> "$GITHUB_OUTPUT"
|
|
echo "has_node=$HAS_NODE" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Setup PHP
|
|
if: steps.detect.outputs.has_php == 'true'
|
|
run: |
|
|
if ! command -v php &> /dev/null; then
|
|
sudo apt-get update -qq
|
|
sudo apt-get install -y -qq php-cli php-mbstring php-xml >/dev/null 2>&1
|
|
fi
|
|
|
|
- name: Setup Node.js
|
|
if: steps.detect.outputs.has_node == 'true'
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
[ -f "composer.json" ] && composer install --no-interaction --prefer-dist --quiet 2>/dev/null || true
|
|
[ -f "package.json" ] && { npm ci --quiet 2>/dev/null || npm install --quiet 2>/dev/null || true; }
|
|
|
|
- name: Run PHP tests
|
|
if: steps.detect.outputs.has_php == 'true'
|
|
run: |
|
|
if [ -f "vendor/bin/phpunit" ]; then
|
|
vendor/bin/phpunit --testdox 2>&1
|
|
echo "## PHPUnit" >> $GITHUB_STEP_SUMMARY
|
|
echo "Tests passed." >> $GITHUB_STEP_SUMMARY
|
|
elif [ -f "phpunit.xml" ] || [ -f "phpunit.xml.dist" ]; then
|
|
echo "::warning::PHPUnit config found but phpunit not installed"
|
|
else
|
|
echo "No PHPUnit configured — skipping"
|
|
fi
|
|
|
|
- name: Run Node.js tests
|
|
if: steps.detect.outputs.has_node == 'true'
|
|
run: |
|
|
if jq -e '.scripts.test' package.json > /dev/null 2>&1; then
|
|
npm test 2>&1
|
|
echo "## Node.js Tests" >> $GITHUB_STEP_SUMMARY
|
|
echo "Tests passed." >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "No test script in package.json — skipping"
|
|
fi
|
|
|
|
- name: Build check
|
|
run: |
|
|
if [ -f "Makefile" ]; then
|
|
make build 2>&1 || echo "::warning::Build failed or not configured"
|
|
elif [ -f "package.json" ] && jq -e '.scripts.build' package.json > /dev/null 2>&1; then
|
|
npm run build 2>&1 || echo "::warning::Build failed"
|
|
fi
|