Repository navigation
DB migration smoke test · push · main #305
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Migrate database | |
| run-name: "DB migration smoke test · ${{ github.event_name }} · ${{ github.head_ref || github.ref_name }}" | |
| # Migrating a REAL database is manual only. Merging to `main` runs the migration-chain SMOKE TEST, | |
| # and structurally cannot do more than that -- see the safety property below. | |
| # | |
| # Migration is deliberately separate from seeding: `keel init` seeds the strategy (rules) library | |
| # on a FRESH deployment, while `keel migrate` only evolves an existing database's schema. Seeding | |
| # on migrate would resurrect rules that were deliberately deleted or refuted. | |
| # | |
| # ⚠️ THE SAFETY PROPERTY THAT MAKES THE `push` TRIGGER SOUND, and it is a property of the event, not | |
| # of anyone's discipline: `db_path` is a `workflow_dispatch` INPUT. A `push` event carries no | |
| # inputs, so on a merge `${{ inputs.db_path }}` renders EMPTY and the job below takes its | |
| # `migration_smoke.py` branch -- always. There is no value a merge can supply that would make it | |
| # migrate a real database. Only a human dispatching it by hand can pass a `db_path`. | |
| # Do not "helpfully" add a default target or read a path from a repo variable: either would remove | |
| # this property and let a merge write to a live database. | |
| # | |
| # DEFERRED SEAM: today `keel.db` is local, git-ignored and single-user, so CI has no database to | |
| # reach. Once the app is server-hosted, that deployment's database becomes the `db_path` target | |
| # (via a self-hosted runner or a mounted volume) and the release workflow can call this job. | |
| # ── WHY THIS SKIPS DOCUMENTATION, AND WHY `ci.yml` DELIBERATELY DOES NOT (#644) ────────────── | |
| # This workflow reads no documentation, so a docs-only change can produce no signal from it and | |
| # the run is pure cost. Seven docs-only pull requests merged on 2026-08-30/31 fired it for | |
| # nothing. | |
| # | |
| # ⚠️ DO NOT COPY THIS BLOCK INTO `ci.yml`. keel's documentation is UNDER TEST, on purpose, and | |
| # `ci.yml` is what runs those tests: | |
| # | |
| # * `tests/test_python_floor.py` reads README.md, README.ar.md and docs/desktop-install.md and | |
| # fails when they disagree with the RELEASE's `requires-python`. It exists because five | |
| # places said 3.11 while the wheels required 3.14 (#595/#607). | |
| # * `tests/test_doc_links.py` pins the documented `SHA256SUMS-*` filenames against what | |
| # `release.yml` actually emits -- the docs promised one file, the workflow shipped three | |
| # (#605/#618). | |
| # | |
| # A docs-only pull request is the ONLY kind those pins are for. Filtering docs out of `ci.yml` | |
| # would disable them on exactly the changes they were built to catch. | |
| # | |
| # SAFE HERE for two independent reasons: `main` carries no branch protection, so no check is | |
| # "required" and a skipped run cannot leave a pull request permanently unmergeable; and | |
| # `paths-ignore` applies only to `push`/`pull_request` -- `schedule` fires regardless, so this | |
| # workflow's push run is a no-input migration smoke test -- zero docs signal, zero risk. | |
| # | |
| # `docs/**` sweeps up the experiment drivers and ledgers under `docs/experiments/`. Correct | |
| # here, since this workflow reads none of it; NOT correct for `ci.yml`, where | |
| # `docs/experiments/trials-ledger.jsonl` is a hash-chained artifact the research tests reason | |
| # about. | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| db_path: | |
| description: "Database to migrate. Leave empty to run the migration smoke test instead." | |
| required: false | |
| type: string | |
| default: "" | |
| push: | |
| branches: [main] | |
| paths-ignore: | |
| - "docs/**" | |
| - "**/*.md" | |
| - "LICENSE" | |
| permissions: | |
| contents: read | |
| jobs: | |
| migrate: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| run: uv python install # version comes from .python-version; never pin it here twice | |
| - name: Sync dependencies | |
| run: uv sync --all-extras --dev | |
| - name: Migrate, or smoke-test the migration chain | |
| run: | | |
| set -euo pipefail | |
| DB="${{ inputs.db_path }}" | |
| if [ -n "$DB" ]; then | |
| if [ ! -f "$DB" ]; then | |
| echo "::error::no database at '$DB' -- refusing to create one here." | |
| echo "::error::A fresh deployment is bootstrapped with 'keel init', not this workflow." | |
| exit 1 | |
| fi | |
| echo "migrating $DB" | |
| uv run keel migrate --db "$DB" | |
| else | |
| echo "no db_path given -- verifying the migration chain instead" | |
| uv run python scripts/migration_smoke.py | |
| fi |