Files
peptide-news-plugin/.github/workflows/ci.yml
Terence b7da4f42b9 feat: add LLM cost tracking with budget enforcement and admin dashboard
- New Cost_Tracker class: logs every API call (model, tokens, cost), enforces
  monthly budgets with hard-stop mode, provides aggregated reporting
- New llm_costs database table with indexes on created_at, model, operation
- Modified LLM class: call_openrouter_with_usage() extracts token usage from
  OpenRouter responses; budget gate checks before each API call
- Admin settings: monthly budget (USD), enforcement mode (disabled/warn/hard-stop),
  cost log retention period
- Admin cost dashboard: budget progress bar, daily cost chart (Chart.js),
  per-model and per-operation breakdowns, recent API call log
- PHPUnit tests: 16 tests covering cost calculation, pricing lookups,
  budget enforcement logic, and model validation
- Updated ARCHITECTURE.md with new table schema, data flow, and key decisions
- Updated CONVENTIONS.md with "how to add cost tracking for a new operation"
- Version bump to 2.4.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 04:18:30 +07:00

134 lines
4.6 KiB
YAML
Executable File

name: CI — Lint & Test
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_call:
permissions:
contents: read
jobs:
# ── PHP Syntax Check ─────────────────────────────────────────────
lint-php:
name: PHP Lint (${{ matrix.php }})
runs-on: ubuntu-latest
strategy:
matrix:
php: ['7.4', '8.1', '8.3']
steps:
- uses: actions/checkout@v4
- name: Set up PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer
- name: Syntax check all PHP files
run: find . -name '*.php' -not -path './vendor/*' -print0 | xargs -0 -n1 php -l
# ── Security Audit ───────────────────────────────────────────────
security-audit:
name: Security Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for common PHP security issues
run: |
echo ":: Checking for direct SQL queries without prepare..."
# Exclude uninstall.php (DROP TABLE is standard WP pattern), activator (table DDL),
# and logger (TRUNCATE) — these use $wpdb->prefix which is safe internal state.
if grep -r "query\s*(\s*['\"].*\$" --include="*.php" --exclude-dir=vendor . 2>/dev/null \
| grep -v "\\\$wpdb->prepare" \
| grep -v "uninstall\.php" \
| grep -v "class-peptide-news-activator\.php" \
| grep -v "class-peptide-news-logger\.php" \
| grep -v "DROP TABLE" \
| grep -v "TRUNCATE" \
&& [ ${PIPESTATUS[0]} -eq 0 ]; then
echo "WARNING: Found potential unescaped SQL queries. Use wpdb->prepare() for all dynamic SQL."
exit 1
fi
echo ":: Checking for eval() usage..."
if grep -r "eval\s*(" --include="*.php" --exclude-dir=vendor . 2>/dev/null; then
echo "ERROR: eval() found. This is a critical security risk."
exit 1
fi
echo ":: Checking for base64_decode without validation..."
if grep -r "base64_decode\s*(" --include="*.php" --exclude-dir=vendor . 2>/dev/null; then
echo "WARNING: Found base64_decode(). Ensure the input is properly validated."
fi
echo ":: Checking for file_get_contents with user input..."
if grep -r "file_get_contents\s*(\s*\$" --include="*.php" --exclude-dir=vendor . 2>/dev/null; then
echo "WARNING: Found file_get_contents with variable. Ensure input is validated and restricted."
fi
echo "All security checks passed."
# ── PHPCS Coding Standards ───────────────────────────────────────
phpcs:
name: PHPCS
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: composer
- name: Install dependencies
run: composer install --prefer-dist --no-progress
- name: Run PHPCS
run: vendor/bin/phpcs --standard=.phpcs.xml.dist --runtime-set ignore_warnings_on_exit 1
# ── PHPUnit Tests ────────────────────────────────────────────────
phpunit:
name: PHPUnit (${{ matrix.php }})
runs-on: ubuntu-latest
strategy:
matrix:
php: ['7.4', '8.1', '8.3']
steps:
- uses: actions/checkout@v4
- name: Set up PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer
coverage: xdebug
- name: Install dependencies
run: composer install --prefer-dist --no-progress
- name: Run PHPUnit
run: vendor/bin/phpunit --testdox
# ── JavaScript Lint ──────────────────────────────────────────────
lint-js:
name: JS Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Check JS syntax
run: |
for f in $(find . -name '*.js' -not -path './vendor/*' -not -path './node_modules/*' -not -path '*/vendor/*'); do
node --check "$f" || exit 1
done