Dev versions
This is the part I use most. Every app has a dev version at
https://<app>-dev.<your domain>, a place to try changes before they're
committed. It's built so coding agents can test their own work. From the
app's repo:
berth dev:push
That deploys the working tree exactly as it is on disk, uncommitted edits and
new files included (.gitignore is respected, so .env and node_modules
stay out). Your branch, index and stash aren't touched. A small change is
live in about 5 seconds. Production is never affected; it still only deploys
from pushes to its branch.
For agents, dev:push waits until it's done and has useful exit codes:
| Exit code | Meaning |
|---|---|
| 0 | live |
| 1 | the build failed (output above) |
| 2 | it built but didn't start (its last log lines are above) |
| 3 | the release command failed, e.g. a migration |
--json prints the result (status, stage, url, release, the base
commit and a summary of what's uncommitted) on stdout, with progress on
stderr. A failed push leaves the previous dev release serving.
berth dev:agents myapp prints a block for the repo's AGENTS.md that tells
an agent how to deploy, read logs and get in. Apps made with
berth new already have it.
Who can reach it
Dev versions run unreviewed code, so they're not public. With
sign-in set up they're open to the @owners group
(berth auth:group owners [email protected]); without it, they're LAN only.
Agents can't click through Google, so give them a token:
berth dev:token myapp --as [email protected] # prints export BERTH_DEV_TOKEN=…
curl -H "Authorization: Bearer $BERTH_DEV_TOKEN" https://myapp-dev.example.com/api/me
berth dev:token myapp --revoke # revoke them all
With --as, requests are signed in as that pretend user
(X-Berth-User-Id: dev:[email protected]), so an agent can test the signed-in
parts of the app too. Tokens only work on dev versions and previews.
Its data is its own
A dev version never touches production's data:
- Postgres: its own database (
<db>_dev) in the same Postgres, with a login that can't connect to production's. It starts empty.berth dev:db:copy myappreplaces it with a copy of production's and runs the release command on it. - Redis: its own small Redis.
- Storage: its own folders.
- Config: copied from the app when the dev version is first made, minus
the database URLs. API keys come along. Change it with
berth config:set myapp-dev KEY=value.
It's just another app
The dev version is the app myapp-dev, so every command works on it:
berth logs myapp-dev -f, berth run myapp-dev npm run migrate,
berth restart myapp-dev. It keeps 3 releases, and it doesn't run
scheduled jobs.
To save memory it goes to sleep after 12 hours with no pushes and no
requests, and the next dev:push wakes it up. Change that with
dev_idle_hours in ~/.berth/config.json.
berth dev:reset myapp deletes the dev version and its data, so the next
push starts fresh from the app's current config. berth dev:off myapp
removes the dev address altogether.
On your laptop, berth dev:push in the repo sends the snapshot to the Mac
over SSH and deploys it there, with the same exit codes and --json. See
Working from your laptop.