Skip to main content
When running /release, include a documentation review step before shipping.

Steps

  1. Scan commits since last release for features, UI changes, new roles, or workflow changes
  2. Check affected docs — map changes to relevant pages in docs/:
    • New/changed user features → docs/guider/ (deltaker, moteleder, sekretar, projektor)
    • New concepts or domain model changes → docs/konsepter.mdx
    • Getting started flow changes → docs/kom-i-gang.mdx
    • Architecture or setup changes → docs/utvikling/ (oppsett, arkitektur, bidra)
  3. Update docs if needed, following the Mintlify writing standards below
  4. Commit doc changes before creating the release tag
  5. Rehearse new migrations against the schema production runs before deploying. CI tests every migration against the final schema only, so a data migration that calls app models can pass CI and still fail on production: the models read columns that later migrations add. Load production’s db/schema.rb (from the deployed commit) into a scratch database, add rows shaped like production’s, and run db:migrate with the release code. lib/migration_rehearsal.rb does this, one MigrationRehearsal::Scenario per deploy that needs it: bin/rails migration_rehearsal:meeting_lifecycle for the VOT-432 – VOT-437 migrations and bin/rails "migration_rehearsal:projector_screens[<ref>]" for the VOT-444 projector-screen layout migrations (<ref> = the commit production runs, default 25ac00b = v0.35.0; it runs every pending migration, so it covers the lifecycle migrations too when they ship in the same deploy). Both exit 1 on a failed check. Add a scenario for the next deploy whose migrations transform data. Read <ref> off production, never off the last tag: the running container is named voteringsapp-web-<sha> (kamal app version prints the same commit), and production can run an untagged deploy (it ran e0211d9, schema 20261006210000, from 2026-10-06 until v0.36.0)
  6. Tag: an annotated tag vX.Y.Z on the release commit, then git push origin main and the tag
  7. Back up, then deploy outside a live meeting, from a clean checkout of the tag: kamal deploy (secrets from Doppler prd through .kamal/secrets). While production has no Litestream replica, first copy its four SQLite databases with sqlite3 .backup inside the web container to storage/predeploy-<timestamp>/ and off the host. Afterwards check /up, the schema version (bin/rails runner in the new container) and the app logs
  8. Publish the GitHub release (gh release create vX.Y.Z) with the release notes once production answers. Leave the included Linear issues In Review; the owner closes them

Mintlify documentation site

The docs/ directory contains a Mintlify documentation site with two tabs:
  • Brukerveiledning (Norwegian) — User-facing guides: getting started, concepts, role guides (deltaker, møteleder, sekretær, projektor)
  • Development (English) — Developer docs: setup, architecture, contributing
Configuration: docs/docs.json. Pages are MDX files. Mintlify components used: <Steps>, <Step>, <Info>, <Warning>, <Tip>, <Note>, <Card>, <CardGroup>, <Frame>. Mintlify parses every page as MDX, so a placeholder in prose goes in backticks (<page title>, never bare); mint broken-links, run in docs/, stops at a page it cannot parse and lists every broken internal link. Guide images live in docs/images/<guide>/ (today docs/images/projektor/, 1280×720 PNGs) and are committed with the guide. A page references them site-absolute (/images/projektor/<name>.png) inside a <Frame> with a caption. They are captured by an opt-in system test, never by hand: when a release changes a screen the guide shows, regenerate them and commit the result with the doc changes:

Writing standards

  • Norwegian pages: use Norwegian UI terms, keep sentences short, use du-form
  • English pages: standard technical writing
  • No placeholder content or Lorem ipsum
Last modified on October 13, 2026