Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Deploy Production

on:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read

concurrency:
group: production-deploy
cancel-in-progress: false

jobs:
deploy:
name: Build and deploy theme
runs-on: ubuntu-latest
environment: production
defaults:
run:
shell: bash
env:
THREEW_DEPLOY_TARGET: production
THREEW_PROD_FTP_HOST: ${{ secrets.THREEW_PROD_FTP_HOST }}
THREEW_PROD_FTP_PORT: ${{ secrets.THREEW_PROD_FTP_PORT }}
THREEW_PROD_FTP_USER: ${{ secrets.THREEW_PROD_FTP_USER }}
THREEW_PROD_FTP_PASS: ${{ secrets.THREEW_PROD_FTP_PASS }}
THREEW_PROD_REMOTE_THEME_DIR: ${{ secrets.THREEW_PROD_REMOTE_THEME_DIR }}
THREEW_PROD_DEPLOY_SCHEME: ${{ secrets.THREEW_PROD_DEPLOY_SCHEME }}
THREEW_PROD_SSL_VERIFY: ${{ secrets.THREEW_PROD_SSL_VERIFY }}
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: wp-content/themes/3w-2025/package-lock.json

- name: Install lftp
run: |
sudo apt-get update
sudo apt-get install -y lftp

- name: Install theme dependencies
working-directory: wp-content/themes/3w-2025
run: npm ci

- name: Lint CSS
working-directory: wp-content/themes/3w-2025
run: npm run lint:css

- name: Lint JavaScript
working-directory: wp-content/themes/3w-2025
run: npm run lint:js

- name: Build theme assets
working-directory: wp-content/themes/3w-2025
run: npm run build

- name: Check theme PHP files
run: find wp-content/themes/3w-2025 -name '*.php' -print0 | xargs -0 -n1 php -l

- name: Verify deployment secrets
run: |
missing=0
for name in \
THREEW_PROD_FTP_HOST \
THREEW_PROD_FTP_USER \
THREEW_PROD_FTP_PASS \
THREEW_PROD_REMOTE_THEME_DIR \
THREEW_PROD_DEPLOY_SCHEME; do
if [[ -z "${!name:-}" ]]; then
echo "Missing required secret-backed env: ${name}" >&2
missing=1
fi
done
if [[ "${missing}" -ne 0 ]]; then
exit 1
fi

- name: Deploy theme with existing script
run: ./scripts/deploy-theme.sh --target production
127 changes: 127 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
name: PR Checks

on:
pull_request:
branches:
- main

permissions:
contents: read
pull-requests: read
security-events: write
actions: read

concurrency:
group: pr-checks-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
quality:
name: Theme lint and build
runs-on: ubuntu-latest
defaults:
run:
working-directory: wp-content/themes/3w-2025
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: wp-content/themes/3w-2025/package-lock.json

- name: Install dependencies
run: npm ci

- name: Lint CSS
run: npm run lint:css

- name: Lint JavaScript
run: npm run lint:js

- name: Build theme assets
run: npm run build

php-syntax:
name: PHP syntax check
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Check theme PHP files
run: find wp-content/themes/3w-2025 -name '*.php' -print0 | xargs -0 -n1 php -l

dependency-review:
name: Dependency review
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Review dependency changes
uses: actions/dependency-review-action@v4
with:
fail-on-severity: moderate

npm-audit:
name: npm audit
runs-on: ubuntu-latest
defaults:
run:
working-directory: wp-content/themes/3w-2025
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: wp-content/themes/3w-2025/package-lock.json

- name: Install dependencies
run: npm ci

- name: Run production dependency audit
run: npm audit --omit=dev --audit-level=moderate

secret-scan:
name: Secret scan
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

codeql:
name: CodeQL analysis
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
actions: read
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript-typescript

- name: Autobuild
uses: github/codeql-action/autobuild@v3

- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@v3
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ test-results/
scripts/logs/
.playwright-mcp/

# Agent/local metadata
.pi/
.claude/

# Local screenshots and visual review captures
*.png
!wp-content/themes/3w-2025/**/*.png

# Product data files
scraped-products*.json
woocommerce-products*.json
Expand Down
83 changes: 83 additions & 0 deletions docs/deployment-pipeline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Production deployment pipeline

## Overview

GitHub Actions owns CI/security gates and production deployment. Secrets stay in GitHub Actions secrets or protected environments only; no production secret belongs in repository files.

## Pull request checks

Workflow: `.github/workflows/pr-checks.yml`

Runs on pull requests targeting `main`:

- Theme dependency install with `npm ci`
- CSS lint with `npm run lint:css`
- JavaScript lint with `npm run lint:js`
- Theme asset build with `npm run build`
- PHP syntax validation for theme PHP files
- Production dependency audit with `npm audit --omit=dev --audit-level=moderate`
- GitHub dependency review, failing on moderate or higher severity
- Gitleaks secret scan
- CodeQL JavaScript/TypeScript analysis

Recommended branch protection for `main`:

- Require pull request before merge
- Require all PR check jobs to pass
- Require conversation resolution
- Block force pushes
- Restrict who can dismiss reviews

## Production deployment

Workflow: `.github/workflows/deploy.yml`

Runs on pushes to `main` and manual `workflow_dispatch`.

Deployment reuses the existing script:

```bash
./scripts/deploy-theme.sh --target production
```

The workflow performs quality gates before calling the script:

- `npm ci`
- `npm run lint:css`
- `npm run lint:js`
- `npm run build`
- PHP syntax validation
- required deployment secret presence check

The deploy script then builds the theme again and mirrors runtime-safe theme files through `lftp`, using the script's existing exclude rules.

## Required GitHub configuration

Create a protected GitHub environment named `production`.

Recommended environment protection:

- Required reviewers enabled
- Deployment branches limited to `main`
- Environment secrets scoped to `production`

Required secrets:

| Secret | Purpose |
| --- | --- |
| `THREEW_PROD_FTP_HOST` | Production FTP/FTPS/SFTP host |
| `THREEW_PROD_FTP_PORT` | Production port; optional if default protocol port is acceptable |
| `THREEW_PROD_FTP_USER` | Production deploy username |
| `THREEW_PROD_FTP_PASS` | Production deploy password |
| `THREEW_PROD_REMOTE_THEME_DIR` | Remote theme directory, e.g. `public_html/wp-content/themes/3w-2025` |
| `THREEW_PROD_DEPLOY_SCHEME` | `ftp`, `ftps`, or `sftp` |
| `THREEW_PROD_SSL_VERIFY` | `yes` or `no`; prefer `yes` for FTPS |

Do not add `.env`, passwords, deploy keys, or host credentials to git.

## Notes

- `scripts/deploy-theme.sh` loads `.env` for local runs only. GitHub Actions supplies the same variable names from GitHub Secrets.
- The npm audit gate omits development dependencies because the WordPress build toolchain currently reports dev-only advisories that require breaking tool upgrades; production dependency exposure is still gated, while CodeQL, Gitleaks, dependency review, linting, and builds cover PR quality/security.
- The production deploy job is attached to the `production` environment so GitHub can enforce approvals before secrets are exposed to the runner.
- If SFTP key auth is required later, update `scripts/deploy-theme.sh` to support a production-specific key secret materialized into a temporary runner file, then pass `THREEW_SSH_KEY_PATH` to the script.
3 changes: 2 additions & 1 deletion wp-content/themes/3w-2025/src/styles/sections/hero-panel.css
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@
}

.threew-hero__panel-shell {
max-width: clamp(360px, 34vw, 520px);
max-width: none;
width: 100%;
padding: clamp(0.65rem, 1.3vw, 1.1rem);
}
}
Expand Down
Loading