# fvcms Deploy Pipeline

Single-command deploy from source to all 3 layers.

## The 3 Layers

| Layer | Path | Purpose | How it updates |
|---|---|---|---|
| **Source** | `/workspace/freshvibe-cms` | Authoritative. Edit here. Bump version here. | Mavis edits |
| **Consumer** | `/workspace/fvcms-web-src/fvcms-web` | Versioned. Vendored copy. Has its own git repo. | `fvcms-update-local.mjs` |
| **Deployed** | VPS `185.249.73.178:/var/www/freshvibeapps/{fvcms-web,fvcms-web-2}/` | Live site. Should always equal consumer. | **Cron auto-pull from GitHub every 2 min** |

**Since 2026-07-30 21:00 BST**: the VPS no longer receives paramiko file copies. It is a working git clone of `avidtech6/fvcms-web` on GitHub, and `/etc/cron.d/freshvibe-deploy` runs `/usr/local/bin/git-deploy.sh` every 2 minutes to snap to the latest `origin/main`. This matches the Cloudflare-Pages model: push to GitHub, the deployed layer catches up on its own.

## Edit → Deploy → Verify

```bash
# 1. Edit files in /workspace/freshvibe-cms (source)
# 2. Bump version
echo "0.7.3" > FV-CMS-VERSION.txt
# Update FV-CMS-MANIFEST.json (vendoredMarker, releasedAt, releasedBy)

# 3. Commit + push source
git add -A
git commit -m "feat: <description>"
git push origin main --follow-tags
git tag -a v0.7.3 -m "..."

# 4. Run fvcms-deploy — this pushes to consumer (fvcms-web-src) and verifies
#    the cron-based VPS deploy will happen within 2 min
node scripts/fvcms-deploy.mjs

# 5. Verify (after waiting ~2 min for the VPS cron to fire)
node scripts/fvcms-version-matrix.mjs
# Optional: ssh root@185.249.73.178 "tail -5 /var/log/freshvibe-deploy.log"
```

**The deploy is fire-and-forget**: by the time you've switched windows, the VPS
has the new code. No more paramiko copy dance.

## What `fvcms-deploy` does

1. **Verifies source** is clean (no uncommitted changes)
2. **Pushes to consumer**: runs `fvcms-update-local`, commits + pushes to GitHub
3. **Confirms cron will deploy**: prints a reminder that the VPS cron will pick up the new commit within 2 min
4. **Reports final state** via `fvcms-version-matrix`

**The VPS is not touched by fvcms-deploy** — it's the cron's job.

## What `fvcms-version-matrix` shows

```
┌─────────────────┬────────────┬────────┬────────────────────────────────────────────┐
│ Layer           │ Version    │ Files  │ Status                                      │
├─────────────────┼────────────┼────────┼────────────────────────────────────────────┤
│ source          │ 0.7.2      │ 383    │ SOURCE OF TRUTH                            │
│ consumer        │ 0.7.2      │ 383    │ UP TO DATE                                 │
│ deployed        │ 0.7.2      │ 383    │ UP TO DATE                                 │
│ deployed2       │ 0.7.2      │ 383    │ UP TO DATE                                 │
└─────────────────┴────────────┴────────┴────────────────────────────────────────────┘
```

A layer is "UP TO DATE" if its version matches source AND its file count matches the manifest.

## The FV-CMS-VENDORED Rule

**ANY file with this marker is a VENDORED copy. NEVER edit in place.**
```
/* FV-CMS-VENDORED v0.7.2 — DO NOT EDIT IN PLACE. Source: github.com/avidtech6/freshvibe-cms. To update, run: fvcms-update */
```

If you need to change a vendored file:
1. Edit the source repo (`/workspace/freshvibe-cms`)
2. Bump version
3. Run `fvcms-deploy` to propagate to consumer + deployed
4. Verify with `fvcms-version-matrix`

Editing in place creates drift: you fix the bug in production but the source still has the old code, so next deploy wipes your fix (or worse, 5 sites end up with 5 slightly different versions).

## When the matrix shows BEHIND

| Layer | Cause | Fix |
|---|---|---|
| `consumer` BEHIND | You edited source but didn't run fvcms-update | `node scripts/fvcms-deploy.mjs --target=consumer` |
| `deployed` BEHIND | You updated consumer but didn't deploy to VPS | `node scripts/fvcms-deploy.mjs --target=vps` |
| `consumer` AHEAD | Someone manually edited consumer (revert!) | Restore from source, then re-vendor |
| `deployed` AHEAD | Someone manually edited deployed (revert!) | Restore from consumer, deploy normally |

## Single-target tools

```bash
# Check a single target
node scripts/fvcms-version-check.mjs --target=/workspace/fvcms-web-src/fvcms-web
node scripts/fvcms-version-check.mjs --target=https://fvcms-web.freshvibeapps.com

# Update a single target (e.g. when chain breaks)
node scripts/fvcms-update.mjs --target=../fvcms-web --version=0.7.2      # from GitHub
node scripts/fvcms-update-local.mjs --target=../fvcms-web                # from local

# Stamp an existing site with the vendored marker (one-time setup)
node scripts/fvcms-stamp.mjs --target=../fvcms-web
```
