diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a00b6522d..7bcc356c7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -124,7 +124,8 @@ jobs: echo "Before merging:" echo "- [ ] The notes below describe what a deployment does differently" echo "- [ ] The smoke journey passed against a licensed deployment, and the result is" - echo " pasted in a comment: \`bash scripts/start.sh && bun run test:smoke\`" + echo " pasted in a comment: \`bash scripts/start.sh && bun run test:smoke\`," + echo " with OPENBOT_SMOKE_COOKIE set to a signed-in session (docs/releasing.md)" echo echo "Merging runs the full suite against this commit before it builds, so there is" echo "nothing to check about CI here. The journey is the part CI cannot do: it needs a" diff --git a/README.md b/README.md index 63dad2a47..9766eed70 100644 --- a/README.md +++ b/README.md @@ -113,11 +113,20 @@ One image carries the app, the API, the browser the Bots drive, and optionally P `.env`, no Kubernetes. ```sh +# The published image. Nothing to clone and nothing to build. +docker run -p 3001:3001 --env-file .env \ + -e EMBEDDED_POSTGRES=on -v openbot-data:/var/lib/postgresql \ + ghcr.io/copilotkit/openbot:latest + +# Or the tree you have in front of you. docker build -t openbot . docker run -p 3001:3001 --env-file .env \ -e EMBEDDED_POSTGRES=on -v openbot-data:/var/lib/postgresql openbot ``` +Everything is on 3001 here, the app included, rather than the 3010 the clone uses. `latest` is the +most recent release and a version tag such as `:v0.0.9` pins one. + Leave `EMBEDDED_POSTGRES` off and set `DATABASE_URL` to point at a database you already run. [docs/deployment.md](docs/deployment.md) has the minimum sizes, the platform notes, and how it behaves behind more than one replica. diff --git a/docs/deployment.md b/docs/deployment.md index ba2d76a9b..204e2fce1 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -4,16 +4,22 @@ OpenBot ships as one container. It carries the app, the API that serves it, and drive, and it can carry its own PostgreSQL as well. It does what it does on a laptop. ```sh -docker build -t openbot . +# Every release publishes this image, so a deployment needs no clone and no build. +# `latest` is the most recent; a version tag such as `:v0.0.9` pins one. +image=ghcr.io/copilotkit/openbot:latest # A database you already run. -docker run -p 3001:3001 --env-file .env openbot +docker run -p 3001:3001 --env-file .env "$image" # Or one inside the container. Nothing else to provision. docker run -p 3001:3001 --env-file .env \ - -e EMBEDDED_POSTGRES=on -v openbot-data:/var/lib/postgresql openbot + -e EMBEDDED_POSTGRES=on -v openbot-data:/var/lib/postgresql "$image" ``` +`docker build -t openbot .` from a clone produces the same thing, for anyone deploying a tree of +their own. What a release publishes is digest-pinned in its `container-images.json`, and deploying +those digests rather than a moving tag is what [releasing.md](releasing.md) recommends. + ## What is in the image, and what is not **In it:** the built app, the API, and Chromium. One port, 3001. The browser listens on 4100 inside diff --git a/docs/development.md b/docs/development.md index c58c007fd..dd9b17a15 100644 --- a/docs/development.md +++ b/docs/development.md @@ -45,6 +45,18 @@ Use `bun run dev` only when you want the app and API server without starting the `start.sh` leaves existing matching services alone and reports when a port is held by another process. +**Nothing here sweeps staged attachments.** A file dropped into the composer is stored before the +message is sent, and the only thing that reclaims the ones never sent is +`bun scripts/cull-staged-attachments.ts` from `server/`, which the Helm chart runs hourly and which +neither `docker-compose.yml` nor `start.sh` starts. It needs only `DATABASE_URL`, and takes a +retention window in hours as its one optional argument, defaulting to 24. On a laptop that is +usually nothing, because the rows are small and the database is yours. It stops being nothing at +thirty-two: one person may hold that many unsent files across every channel at once, the refusal on +the next one promises they are cleared within a day, and where nothing sweeps they are not, so a +long-lived local deployment can reach a state where attaching anything is refused. Removing a file +in the composer deletes it outright, so it takes abandoned drafts rather than ordinary use. +[deployment.md](deployment.md) says the same for a real deployment. + ## Migrations After changing the Drizzle schema: @@ -107,10 +119,11 @@ reports. Point `DATABASE_URL` at a database of their own to keep the two apart. CI uses `bun run test:ci` to verify the expected test count in addition to normal tests. -`bun run test:smoke` is separate and needs a deployment that is up: +`bun run test:smoke` is separate and needs a deployment that is up, and a session on it: ```sh bash scripts/start.sh +export OPENBOT_SMOKE_COOKIE='better-auth.session_token=...' bun run test:smoke ``` @@ -119,6 +132,13 @@ suite cannot reach: server to supervisor to computer, the gateway deciding befor and the audit row landing. Point it elsewhere with `OPENBOT_API_URL`. Without a deployment it is skipped by `bun run test` and says what to start when asked for by name. +The session is not optional and not a convenience. Every route the journey proves is behind +`requireUser`, so without one the three tests that act on a computer answer 401 and the run reports +a broken deployment when nothing is broken. Take the cookie from a browser already signed in to the +deployment under test, from DevTools under Application, Cookies. It is a credential with that +person's reach: it belongs in the environment of the run, not in a file or a pull request comment. +Asked for without it, the run stops before the first test and names the variable. + `bun run test:live-screen` is separate for a related reason and needs no deployment, only this directory's own dependencies: diff --git a/docs/releasing.md b/docs/releasing.md index b646f6886..6d68c4ce1 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -120,8 +120,13 @@ the release PR: ```sh bash scripts/start.sh +export OPENBOT_SMOKE_COOKIE='better-auth.session_token=...' # from a signed-in browser bun run test:smoke ``` +The session is the second half of "a machine with real credentials": the routes the journey proves +are behind `requireUser`, so a run without one answers 401 three times and says nothing about the +release. See [development.md](development.md#quality-checks) for where the cookie comes from. + The release PR asks for the result in a comment. That is deliberately a person rather than a robot: it is the one gate that cannot be automated, so it is the one gate worth naming.