-
Notifications
You must be signed in to change notification settings - Fork 4.5k
docs: codify the release confidence process with executable tooling #1052
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| # ADR-005: Releases pass a risk-based confidence process, gated on the real image | ||
|
|
||
| - **Status**: Accepted | ||
| - **Date**: 2026-07 (established during the v1.11.0 release) | ||
| - **Related**: [RELEASE_PROCESS.md](../../../.github/RELEASE_PROCESS.md), `scripts/release-test/`, [ADR-004](ADR-004-background-workers.md) | ||
|
|
||
| ## Context | ||
|
|
||
| Releases grew from a handful of fixes to 50+ commits spanning security | ||
| hardening, features, migrations and dependency changes. Verification was | ||
| ad-hoc: a green test suite on `main` plus whatever manual checks the release | ||
| owner remembered. v1.11.0 proved the gap empirically — the unit suite was | ||
| fully green while `sort_by=title` returned a 500 (a SEARCH-index interaction | ||
| only a real SurrealDB exhibits) and clearing credential fields silently | ||
| no-oped (two mirror-image bugs, frontend and API, that only an end-to-end | ||
| path reveals). Neither class of bug is catchable by mocked tests, and neither | ||
| was: both were found by the process this record establishes. | ||
|
|
||
| ## Decision | ||
|
|
||
| **Every stable release passes a risk-based confidence process before cutting, | ||
| and the final gate runs against the built Docker image — the artifact users | ||
| receive — not the repository.** | ||
|
|
||
| The process (mechanics in [RELEASE_PROCESS.md](../../../.github/RELEASE_PROCESS.md)): | ||
|
|
||
| 1. **Changelog audit first** — the release diff, fully represented in the | ||
| CHANGELOG, is the input for both the test plan and the communication. | ||
| 2. **Risk matrix over test list** — each change is classified by what it can | ||
| break and for whom, then assigned to a bucket: **A** (automated now), | ||
| **B** (automatable with investment — build the muscle when it compounds), | ||
| **C** (release-owner judgment: real credentials, real TTS, UX, the pushed | ||
| image). Security changes are probed for the inverse risk: does the | ||
| protection break legitimate use? | ||
| 3. **The image gate** — fresh-install and upgrade-with-data scenarios run | ||
| against real containers (`make release-test`), because packaging bugs | ||
| (supervisord flags, uv sync modes, migration ordering) never appear in the | ||
| suite. | ||
| 4. **Fix loop with a re-test policy** — findings become focused PRs; what | ||
| re-runs after each merge is defined up front. Pre-existing bugs that are | ||
| not release regressions become backlog issues, not scope creep. | ||
| 5. **Human gates stay human** — the pushed-image verification and the release | ||
| publication require the release owner explicitly; automation prepares, | ||
| people pull the trigger. | ||
| 6. **Retro closes the loop** — accepted improvements are applied to the | ||
| process docs and scripts in the same session. | ||
|
|
||
| ## Alternatives considered | ||
|
|
||
| - **Keep ad-hoc verification** — free, but v1.11.0 showed it misses exactly | ||
| the bug classes that hurt users most (integration and packaging). | ||
| - **Full CI-based E2E on every PR** — highest coverage, but a real | ||
| SurrealDB + worker + image build pipeline on every PR is slow and expensive; | ||
| the release boundary is where artifact-level confidence pays off. | ||
| - **Community soak (RC tags)** — previously abandoned: slow feedback and low | ||
| participation; a deliberate confidence process front-loads what soaking | ||
| found late. | ||
|
|
||
| ## Consequences | ||
|
|
||
| - Cutting a release costs hours, not minutes — deliberately: the cost scales | ||
| with release size, which is the point of the risk matrix. | ||
| - Release muscle is versioned in-repo (`scripts/release-test/`, make targets) | ||
| and compounds: bucket-B investments from one release become bucket-A | ||
| automation for the next. | ||
| - The upgrade scenario requires published previous images to remain available | ||
| on the registries. | ||
| - The process assumes a release owner in the loop for buckets B/C — it is a | ||
| confidence process, not full automation. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| services: | ||
| surrealdb: | ||
| image: surrealdb/surrealdb:v2 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Release-gate results can change without a repository change because Prompt for AI agents |
||
| command: start --log info --user root --pass root rocksdb:/mydata/test.db | ||
| user: root | ||
| volumes: | ||
| - ${DATA_DIR:?set DATA_DIR}/surreal:/mydata | ||
|
|
||
| app: | ||
| image: ${APP_IMAGE:?set APP_IMAGE} | ||
| ports: | ||
| - "127.0.0.1:${API_PORT:?set API_PORT}:5055" | ||
| - "127.0.0.1:${FE_PORT:?set FE_PORT}:8502" | ||
| environment: | ||
| # Without an explicit API_URL the frontend's /config points the BROWSER | ||
| # at host:5055 — on a dev machine that is the development API, not this | ||
| # stack (silent data crossover between environments!) | ||
| - API_URL=${RC_API_URL:-} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Browser UI checks against this release stack resolve their API to port 5055, not the stack's API port (15055/25055); they can hit a local dev API or fail. Pass each phase's API URL as Prompt for AI agents |
||
| - OPEN_NOTEBOOK_ENCRYPTION_KEY=${RC_ENCRYPTION_KEY:-release-test-key} | ||
| - SURREAL_URL=ws://surrealdb:8000/rpc | ||
| - SURREAL_USER=root | ||
| - SURREAL_PASSWORD=root | ||
| - SURREAL_NAMESPACE=${RC_SURREAL_NS:-open_notebook} | ||
| - SURREAL_DATABASE=${RC_SURREAL_DB:-open_notebook} | ||
| volumes: | ||
| - ${DATA_DIR}/notebook:/app/data | ||
| # Reach host services (e.g. Ollama on localhost:11434) via | ||
| # host.docker.internal on Linux too; Docker Desktop resolves it natively. | ||
| # Credentials pointing at local services must use | ||
| # http://host.docker.internal:<port> when the app runs in a container. | ||
| extra_hosts: | ||
| - "host.docker.internal:host-gateway" | ||
| depends_on: | ||
| - surrealdb | ||
|
|
||
| proxy: | ||
| image: nginx:alpine | ||
| ports: | ||
| - "127.0.0.1:${PROXY_PORT:?set PROXY_PORT}:80" | ||
| volumes: | ||
| - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro | ||
| depends_on: | ||
| - app | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # Reverse proxy in front of the frontend with default buffering ON — the SSE | ||
| # streaming fix must work anyway because the API sends X-Accel-Buffering: no, | ||
| # which nginx honors. Host is passed through verbatim to exercise the | ||
| # frontend's Host validation with a real proxy in the path. | ||
| server { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Uploads >1MB through the nginx proxy will silently return a 413 error because Prompt for AI agents |
||
| listen 80; | ||
| server_name _; | ||
|
|
||
| location / { | ||
| proxy_pass http://app:8502; | ||
| proxy_http_version 1.1; | ||
| proxy_set_header Host $http_host; | ||
| proxy_set_header X-Forwarded-Proto $scheme; | ||
| proxy_set_header Upgrade $http_upgrade; | ||
| proxy_set_header Connection "upgrade"; | ||
| proxy_read_timeout 300s; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: Dump paths containing spaces or shell glob characters are split before
rc-stack.shreceives them, causing import to fail or select an unintended file. QuoteDUMPwhen forwarding it.Prompt for AI agents