diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..64f50d5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,109 @@ +# CI for shopdb-flask on GitHub Actions. +# +# Mirrors the internal gitea pipeline. Four jobs on push + pull_request: +# backend - pytest (SQLite via TestingConfig, no DB service needed) +# naming - the CONTRIBUTING.md naming/style gate +# frontend - vitest + Vue build +# migrations-mysql - the REAL multi-site deploy path: fresh flask db upgrade +# + every plugin's chain on utf8mb4 MySQL 8, idempotent on +# a second run. The pytest suite only exercises SQLite +# create_all(), so this is what catches an Alembic +# regression on MySQL before it ships. + +name: CI + +on: + push: + pull_request: + +jobs: + backend: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + cache: pip + - run: pip install -r requirements.txt + - run: python -m pytest -q + + naming: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: bash scripts/check-naming-and-style.sh + + frontend: + runs-on: ubuntu-latest + defaults: + run: + working-directory: frontend + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: npm + cache-dependency-path: frontend/package-lock.json + - run: npm ci + - run: npx vitest run + - run: npm run build + + migrations-mysql: + runs-on: ubuntu-latest + services: + mysql: + image: mysql:8.0 + env: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: shopdb_ci + ports: + - 3306:3306 + options: >- + --health-cmd="mysqladmin ping -h localhost -uroot -proot" + --health-interval=5s --health-timeout=5s --health-retries=20 + env: + FLASK_APP: shopdb + DATABASE_URL: mysql+pymysql://root:root@127.0.0.1:3306/shopdb_ci?charset=utf8mb4 + SECRET_KEY: ci-secret + JWT_SECRET_KEY: ci-jwt-secret + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + cache: pip + - run: pip install -r requirements.txt + - name: Force utf8mb4 on the CI database + run: | + mysql -h 127.0.0.1 -uroot -proot -e \ + "ALTER DATABASE shopdb_ci CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" + - name: Fresh core upgrade from empty + run: flask db upgrade + - name: Install every bundled plugin (runs its chain) + run: | + for p in computers employees geenforce knowledgebase machines \ + measuringtools network notifications printedparts printers \ + slides usb warranty; do + flask plugin install "$p" + done + flask plugin upgrade-all + - name: Assert schema built + utf8mb4 + run: | + python - <<'PY' + from shopdb import create_app + from shopdb.extensions import db + from sqlalchemy import text + app = create_app() + with app.app_context(): + tables = db.inspect(db.engine).get_table_names() + assert len(tables) >= 70, f'only {len(tables)} tables built' + row = db.session.execute(text( + "SELECT default_character_set_name FROM information_schema.schemata " + "WHERE schema_name = 'shopdb_ci'")).first() + assert row[0] == 'utf8mb4', f'charset is {row[0]}, not utf8mb4' + print(f'OK: {len(tables)} tables, charset {row[0]}') + PY + - name: Second core upgrade must be a clean no-op + run: flask db upgrade diff --git a/docs/DEVELOPMENT-SETUP.md b/docs/DEVELOPMENT-SETUP.md index 753a440..2551c67 100644 --- a/docs/DEVELOPMENT-SETUP.md +++ b/docs/DEVELOPMENT-SETUP.md @@ -182,12 +182,12 @@ tasks call `venv/` and `frontend/node_modules`). bash scripts/check-naming-and-style.sh # naming - runs via Git Bash ``` There is NO auto-installed git hook - you run these yourself (or the - VS Code task). On the internal server, CI runs all three on every push - and fails the build on a bad name. GitHub Actions is not set up on the - public mirror yet, so if you develop against GitHub these local checks - (or the opt-in hook below) are your only gate - run them. The naming - check is a shell script, so that one line needs Git Bash (installed with - Git for Windows). + VS Code task). CI runs all three on every push and pull request + (`.github/workflows/ci.yml` on GitHub Actions; the same gate runs on the + internal server) and fails the build on a bad name, so nothing bad + reaches `main` - running them locally just saves the round trip. The + naming check is a shell script, so that one line needs Git Bash + (installed with Git for Windows). Want it automatic? The repo ships a hook; enable it once per clone: ```powershell diff --git a/docs/PLUGIN-EXTERNAL-REPO.md b/docs/PLUGIN-EXTERNAL-REPO.md index 5b4c610..643de98 100644 --- a/docs/PLUGIN-EXTERNAL-REPO.md +++ b/docs/PLUGIN-EXTERNAL-REPO.md @@ -7,6 +7,12 @@ the framework ships a bundled set, and you drop your own plugin into `/plugins//` by clone, submodule, or symlink. No pip packaging is required for v1 (pip distribution is deferred to v2 per ADR-003). +> **Windows / VS Code:** command examples use the Linux venv path +> `venv/bin/python`; on Windows use `venv\Scripts\python` and +> `$env:FLASK_APP="shopdb"` (not `export`). Full Windows onboarding: +> [DEVELOPMENT-SETUP](DEVELOPMENT-SETUP). + + If you have not written a plugin before, start with [PLUGIN-QUICKSTART.md](PLUGIN-QUICKSTART.md) and the hook reference in [PLUGIN-HOOKS.md](PLUGIN-HOOKS.md). This document only covers the parts that are diff --git a/docs/PLUGIN-GUIDE.md b/docs/PLUGIN-GUIDE.md index 4bafe15..00240e8 100644 --- a/docs/PLUGIN-GUIDE.md +++ b/docs/PLUGIN-GUIDE.md @@ -5,6 +5,10 @@ running feature with its own list, detail, form, settings page, and report. It i the companion to [PLUGIN-QUICKSTART.md](PLUGIN-QUICKSTART.md): the quickstart gets you moving with `flask plugin new`; this guide explains *why* each piece looks the way it does by walking the shipped code of the exemplar plugin. +> **Windows / VS Code:** command examples use the Linux venv path +> `venv/bin/python`; on Windows use `venv\Scripts\python` and +> `$env:FLASK_APP="shopdb"` (not `export`). Full Windows onboarding: +> [DEVELOPMENT-SETUP](DEVELOPMENT-SETUP). `measuringtools` was chosen as the exemplar on purpose. It is the first plugin built after the framework matured (ADR-005 scoped it; ADR-008 changed how plugin diff --git a/docs/PLUGIN-LAB-PRINTEDPARTS.md b/docs/PLUGIN-LAB-PRINTEDPARTS.md index a6f2c55..ef5ac30 100644 --- a/docs/PLUGIN-LAB-PRINTEDPARTS.md +++ b/docs/PLUGIN-LAB-PRINTEDPARTS.md @@ -14,6 +14,12 @@ badge-scanned employee, a touch kiosk (scan bin barcode, scan badge, keypad quantity), 1x0.5in bin labels, low-stock email alerts, and reports. Spec with decision records: `docs/proposals/printedparts-plugin.md`. +> **Windows / VS Code:** command examples below use the Linux venv path +> `venv/bin/python`; on Windows use `venv\Scripts\python` and +> `$env:FLASK_APP="shopdb"` (not `export`). Full Windows onboarding: +> [DEVELOPMENT-SETUP](DEVELOPMENT-SETUP). + + Know before you start - BUNDLED plugin: frontend files live in core `frontend/src/`, and three core files get small edits (api client, sidebar icon map, PLUGIN_TABLE_OWNERS). diff --git a/docs/PLUGIN-QUICKSTART.md b/docs/PLUGIN-QUICKSTART.md index 2bed921..aaec1ad 100644 --- a/docs/PLUGIN-QUICKSTART.md +++ b/docs/PLUGIN-QUICKSTART.md @@ -3,6 +3,12 @@ Build a working shopdb-flask plugin in 30 minutes. This walks through generating, customizing, installing, and testing a plugin from scratch. For the full hook reference, see [PLUGIN-HOOKS.md](PLUGIN-HOOKS.md). + +> **Windows / VS Code:** command examples below use the Linux venv path +> `venv/bin/python`; on Windows use `venv\Scripts\python` and +> `$env:FLASK_APP="shopdb"` (not `export`). Full Windows onboarding: +> [DEVELOPMENT-SETUP](DEVELOPMENT-SETUP). + For the architectural decisions behind the contract, see [docs/adr/](../docs/adr/). ## Step 1: Generate the skeleton