Add CI/CD pipeline with automated testing and SFTP deployment

Introduces GitHub Actions workflows for continuous integration and
deployment. CI runs PHP linting (7.4, 8.1, 8.3), PHPCS with WordPress
coding standards, PHPUnit tests across PHP versions, and JS syntax
checks. Deployment to Hostinger via FTPS triggers on push to main
after all CI checks pass, with optional LiteSpeed cache purge.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Terence Ong
2026-04-06 13:41:47 +07:00
parent 6ed902394d
commit 849ffa1260
10 changed files with 830 additions and 0 deletions

90
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,90 @@
name: CI — Lint & Test
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
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/*' -not -path './peptide-news-plugin/*' -print0 | xargs -0 -n1 php -l
# ── 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
# ── 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 './peptide-news-plugin/*'); do
node --check "$f" || exit 1
done

76
.github/workflows/deploy.yml vendored Normal file
View File

@@ -0,0 +1,76 @@
name: Deploy to WordPress
on:
push:
branches: [ main ]
permissions:
contents: read
# Cancel previous deploys if a new push arrives while one is running.
concurrency:
group: deploy-production
cancel-in-progress: true
jobs:
# ── Run tests first ──────────────────────────────────────────────
test:
name: Pre-deploy tests
uses: ./.github/workflows/ci.yml
# ── Deploy via SFTP ──────────────────────────────────────────────
deploy:
name: Deploy to Hostinger
runs-on: ubuntu-latest
needs: test # Only deploy if all CI checks pass
environment: production
steps:
- uses: actions/checkout@v4
- name: Deploy plugin files via SFTP
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.SFTP_HOST }}
username: ${{ secrets.SFTP_USER }}
password: ${{ secrets.SFTP_PASS }}
port: ${{ secrets.SFTP_PORT || 22 }}
protocol: ftps
local-dir: ./
server-dir: ${{ secrets.WP_PLUGIN_PATH }}
exclude: |
**/.git*
**/.git*/**
.github/**
tests/**
vendor/**
node_modules/**
composer.json
composer.lock
phpunit.xml.dist
.phpcs.xml.dist
peptide-news-plugin/**
README.md
.editorconfig
- name: Purge LiteSpeed Cache
if: success()
run: |
# Trigger a cache purge via the WordPress REST API.
# This requires an Application Password set up in WordPress.
if [ -n "${{ secrets.WP_APP_PASSWORD }}" ]; then
curl -s -X POST \
-u "${{ secrets.WP_ADMIN_USER }}:${{ secrets.WP_APP_PASSWORD }}" \
"${{ secrets.WP_SITE_URL }}/wp-json/peptide-news/v1/cache-purge" \
--max-time 15 || echo "Cache purge skipped (endpoint not available)"
else
echo "No WP_APP_PASSWORD set — skipping remote cache purge."
echo "Remember to purge LiteSpeed Cache manually after deploy."
fi
- name: Deploy summary
run: |
echo "## Deployment Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Branch:** \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Commit:** \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Deployed to:** ${{ secrets.WP_SITE_URL || 'peptiderepo.com' }}" >> $GITHUB_STEP_SUMMARY