# ERPFlow CI/CD

**Tests run only on the developer machine** (`make ci-local` / pre-push). GitHub Actions does **not** run PHPUnit, frontend lint/build, or MySQL concurrency suites.

```text
feature push
  → local pre-push (coding-standard + tests + frontend + deploy-script dry-run)
  → GitHub (no Actions test jobs)

development          no deploy (integration branch)

staging push/merge   → Actions: staging-deploy only
                       server: fetch SHA → docker compose build/up → migrate → health

production           → Actions: workflow_dispatch (manual)
                       server: same deploy script path as staging, prod compose
```

Server deploy never runs the test suite. It uses `scripts/deploy-staging.sh` / `scripts/deploy-production.sh`:

1. DB backup  
2. `git checkout` exact SHA  
3. Docker Compose **rebuild + up**  
4. `composer install --no-dev`  
5. `php artisan migrate --force`  
6. cache / Horizon reload + health checks  

## Local pre-push gate

```text
git push
  → .githooks/pre-push
  → scripts/ci-local.sh
  → fail → push aborted
  → pass → push continues (no remote test CI)
```

```bash
make up      # app + enable hook
make hooks   # hook only
make ci-local
```

Bypass (emergency): `SKIP_LOCAL_CI=1 git push` or `git push --no-verify`.

## GitHub Actions jobs

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

| Job | When | What |
| --- | --- | --- |
| `staging-deploy` | push to `staging` | SSH → `STAGING_DEPLOY_PATH` → deploy SHA |
| `production-deploy` | manual `workflow_dispatch` | SSH → `PRODUCTION_DEPLOY_PATH` → deploy SHA |

Optional local/GHA bench (not part of merge CD): `.github/workflows/ci-bench-parallel.yml`.

## Required secrets

| Secret | Purpose |
| --- | --- |
| `PRODUCTION_SSH_HOST` / `USER` / `KEY` / `FINGERPRINT` / `PORT` | Shared SSH (staging + prod) |
| `PRODUCTION_DEPLOY_PATH` | Production clone path |
| `STAGING_DEPLOY_PATH` | Staging clone path (sibling folder) |

Environments: `staging`, `production` (or `PRODUCTION`). App secrets stay in each server’s `backend/.env`.

## Safety

- Failed backup / migrate / health → deploy stops; app SHA rollback (not migrate rollback)
- No `migrate:fresh` / `git clean`
- Staging ports: nginx `8014`, edge `8089`, frontend `3012`
- Production ports: nginx `8010`, edge `8088`, frontend `3010`
