Files
stack/.gitea/workflows/ci.yml
kert 446f1b9398
All checks were successful
CI / lint (push) Successful in 34s
CI / notebooks-smoke (push) Successful in 1m28s
Deploy / notebooks (push) Has been skipped
Deploy / zotero (push) Has been skipped
Deploy / docs (push) Has been skipped
Deploy / api (push) Has been skipped
Deploy / mc (push) Has been skipped
Infra CI / notebooks (push) Successful in 53s
Infra CI / zotero (push) Successful in 16s
Infra CI / docs (push) Successful in 1m18s
Infra CI / api (push) Successful in 51s
Infra CI / mc (push) Successful in 12s
Deploy / report (push) Successful in 13s
CI / test (push) Successful in 15m7s
Notebooks Integration / notebooks-integration (push) Successful in 7m37s
feat(lake): M4 — DuckLakeContext write path + OPPS lake pilot (closes #513)
aco.lake.DuckLakeContext: the concrete lake context for the M3
decision (#512). Subclasses DuckDBContext — load/save are inherited
untouched; only the connection wiring differs (ducklake+httpfs
extensions, S3 secret for RustFS, ATTACH the catalog, USE it as the
default database so schema.table refs resolve in the lake). Postgres
DSN for multi-writer prod, plain file path for dev/tests. Explicit
close() added to the context family (releases locks/attachments).

Pilot: dev/scripts/publish_opps_to_lake.py reads the OPPS tables from
the replica and writes them through Context.save(mode=replace). Run
against prod (postgres catalog db 'ducklake' + RustFS): addendum_b
219,665 rows in 2.6s, apc_weight 7,776, skin_sub_addendum_b 2,520 —
all read-back verified through Context.load.

Config: stack.toml [lake.ducklake] (catalog DSN sans password, data
path, s3 endpoint). CI: ducklake added to the duckdb extension
preinstall (same xdist install race class as #515). 6 new tests use a
file catalog + local data path — same code paths, no services needed.
2026-07-10 23:03:29 -04:00

117 lines
3.9 KiB
YAML

# DO NOT EDIT — generated by gen_config.py from stack.toml
# Re-generate: uv run python dev/scripts/gen_config.py
name: CI
on:
push:
branches: ["**"]
pull_request:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: https://github.com/actions/checkout@v4
- name: Set up uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
env:
UV_INSTALL_DIR: /usr/local/bin
- name: Install dependencies
run: uv sync --dev
- name: Ruff check
run: uv run ruff check src/ tests/ --output-format=concise
- name: Ruff format
run: uv run ruff format --check src/ tests/
- name: Validate generated config
run: uv run python dev/scripts/gen_config.py --check
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: https://github.com/actions/checkout@v4
- name: Set up uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
env:
UV_INSTALL_DIR: /usr/local/bin
- name: Install dependencies
run: uv sync --dev
- name: Preinstall duckdb extensions
# tests/zot/test_duck.py runs INSTALL sqlite from every xdist
# worker; concurrent installs race the extension-file rename in
# ~/.duckdb ("Could not remove file ... sqlite_scanner", #515).
# Installing once up front makes the in-test INSTALL a no-op.
# ducklake: same race class, used by tests/aco DuckLakeContext.
run: uv run python -c "import duckdb; duckdb.connect().execute('INSTALL sqlite; INSTALL ducklake')"
- name: Pytest
# -n auto parallelizes across runner cores. Coverage combining
# is configured via [tool.coverage.run] parallel=true in
# pyproject.toml — without that the per-worker .coverage.* files
# don't merge reliably (see #388 for the prior revert).
run: uv run pytest tests/ -x --cov=src --cov-report=term-missing --cov-fail-under=99 -q -n auto
- name: File failure issue
if: failure()
env:
GITEA_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
run: |
uv sync --no-dev --quiet 2>/dev/null || true
uv run python -m api.diag.ci \
--workflow "CI" --job "test" \
--run "${{ github.run_number }}" \
--sha "${{ github.sha }}" \
--ref "${{ github.ref }}" || true
notebooks-smoke:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: https://github.com/actions/checkout@v4
- name: Set up uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
env:
UV_INSTALL_DIR: /usr/local/bin
- name: Install dependencies
run: uv sync --dev
- name: Stub aco.duckdb
# The checkout has no data volume; conf.connect.duckdb() opens
# data/aco.duckdb read-only and fails if it doesn't exist. An
# empty-but-valid database is enough for the ci-smoke notebooks
# (schema browsing over information_schema returns zero rows).
run: |
[ -f data/aco.duckdb ] || uv run python -c \
"import duckdb; duckdb.connect('data/aco.duckdb').close()"
- name: Run data-independent notebooks headless
# Executes the [ci_smoke] set from infra/marimo/nb-tests.toml via
# `marimo export session` and fails on any cell error. Runs on
# every push (not path-gated): notebooks import src/ modules, so
# src changes can break them too.
run: uv run python dev/scripts/nb_integration.py --set ci-smoke
- name: File failure issue
if: failure()
env:
GITEA_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
run: |
uv sync --no-dev --quiet 2>/dev/null || true
uv run python -m api.diag.ci \
--workflow "CI" --job "notebooks-smoke" \
--run "${{ github.run_number }}" \
--sha "${{ github.sha }}" \
--ref "${{ github.ref }}" || true