also looking at this
fix(deploy): keep SQLite across deploys, and preflight an attached host's services
#174
16 files
+916
-12
Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.
| @@ -344,6 +344,54 @@ clean. If a site targets a server (`deploy: 'server'`, or `start` set) but no | ||
| 344 | 344 | actionable error instead of failing silently at runtime — set `deploy: 'bucket'` |
| 345 | 345 | or add a server. |
| 346 | 346 | |
| 347 | ### State that must survive a deploy | |
| 348 | ||
| 349 | Each deploy unpacks into a NEW `releases/<id>` directory and flips `current` at | |
| 350 | it; old releases are pruned. Anything the app writes and must keep therefore has | |
| 351 | to live in the site's `shared/` directory and be symlinked in, which is what | |
| 352 | `site.sharedPaths` declares. `.env` is always shared. | |
| 353 | ||
| 354 | ```typescript | |
| 355 | sites: { | |
| 356 | app: { | |
| 357 | start: 'bun run server.ts', | |
| 358 | sharedPaths: ['storage', 'public/uploads'], | |
| 359 | }, | |
| 360 | } | |
| 361 | ``` | |
| 362 | ||
| 363 | A **SQLite database is shared automatically**. The deploy already knows the | |
| 364 | connection and the file path from the environment it writes to the box, so when | |
| 365 | `DB_CONNECTION` is `sqlite` and `DB_DATABASE` names a path inside the release, | |
| 366 | that file is added to `sharedPaths` for you and the deploy log says so. Without | |
| 367 | it the database sits inside a release directory and the next deploy starts the | |
| 368 | app on an empty one — silently, with the data still in a release that is about | |
| 369 | to be pruned. | |
| 370 | ||
| 371 | Two cases it does not cover: | |
| 372 | ||
| 373 | - **`DB_DATABASE` unset.** An app can default its own path internally, which the | |
| 374 | deploy never sees. Guessing the filename would report the data as safe while | |
| 375 | sharing a path the app may not use, so the deploy warns instead — set | |
| 376 | `DB_DATABASE`, or list the file in `sharedPaths` yourself. | |
| 377 | - **An absolute path.** A database outside the release tree already survives; a | |
| 378 | deploy replaces the release, not the filesystem around it. | |
| 379 | ||
| 380 | Turning existing on-box state into shared state does not throw it away: the | |
| 381 | first deploy to share a path copies the live release's copy into `shared/` | |
| 382 | (SQLite's `-wal`/`-shm` sidecars included), and a site's first deploy seeds a | |
| 383 | still-empty shared file from the copy the artifact shipped. | |
| 384 | ||
| 385 | Several sites of one project can share ONE file — an app and its API on one | |
| 386 | SQLite database — with the object form, which names an absolute `target`: | |
| 387 | ||
| 388 | ```typescript | |
| 389 | sharedPaths: [{ path: 'database/app.sqlite', target: '/var/www/acme-app/shared/database/app.sqlite', seed: false }] | |
| 390 | ``` | |
| 391 | ||
| 392 | Each site installs under its own base, so a plain string would give each of them | |
| 393 | a database of its own. `seed: false` marks the sites that do not own the file. | |
| 394 | ||
| 347 | 395 | ### CDN / caching |
| 348 | 396 | |
| 349 | 397 | The `cache` hint applies to either origin: |
| @@ -1243,6 +1243,11 @@ export interface SiteConfig { | ||
| 1243 | 1243 | * A release is a fresh directory, so anything the app WRITES and must keep |
| 1244 | 1244 | * has to be listed here or the next deploy silently starts it from empty. |
| 1245 | 1245 | * |
| 1246 | * A SQLite database is the one exception, added for you: when the site's | |
| 1247 | * resolved env says `DB_CONNECTION=sqlite` and `DB_DATABASE` names a path | |
| 1248 | * inside the release, the deploy shares that file without being asked. An | |
| 1249 | * env that says SQLite but not WHERE is warned about rather than guessed at. | |
| 1250 | * | |
| 1246 | 1251 | * An entry may instead be a {@link SharedPathSpec} naming an absolute |
| 1247 | 1252 | * `target`, which is how SEVERAL sites of one project point at ONE file — |
| 1248 | 1253 | * an app and its API sharing a single SQLite database, say. Each site |