From f764c5d3e91adb542695ccca40cb2dc93a4a040b Mon Sep 17 00:00:00 2001 From: cproudlock Date: Fri, 17 Jul 2026 14:40:55 -0400 Subject: [PATCH] Add development setup guide + shared VS Code config New docs/DEVELOPMENT-SETUP.md: clone-to-first-change onboarding (Docker fast path, manual venv+Node daily driver, VS Code, the dev loop, first-change pointer at the plugin lab, troubleshooting). Ship .vscode/ launch/tasks/extensions so F5 debugs the backend on 5001 and a task runs both servers; personal settings.json stays ignored. Fix the README manual path - it ran the backend on the default 5000, but the frontend dev server proxies to 5001, so nothing loaded; also add the plugin upgrade-all step and a VS Code pointer. --- .gitignore | 6 +- .vscode/extensions.json | 9 ++ .vscode/launch.json | 30 ++++++ .vscode/tasks.json | 43 ++++++++ README.md | 9 +- docs/DEVELOPMENT-SETUP.md | 213 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 307 insertions(+), 3 deletions(-) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 docs/DEVELOPMENT-SETUP.md diff --git a/.gitignore b/.gitignore index ba37481..d81657d 100644 --- a/.gitignore +++ b/.gitignore @@ -28,7 +28,11 @@ env/ # IDE .idea/ -.vscode/ +.vscode/* +# Share the team's launch/tasks/extensions; keep personal settings out. +!.vscode/launch.json +!.vscode/tasks.json +!.vscode/extensions.json *.swp *.swo *~ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..ef79aa0 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "ms-python.python", + "ms-python.vscode-pylance", + "Vue.volar", + "dbaeumer.vscode-eslint", + "ms-azuretools.vscode-docker" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b84a01f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,30 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Flask API (:5001)", + "type": "debugpy", + "request": "launch", + "module": "flask", + "cwd": "${workspaceFolder}", + "env": { + "FLASK_APP": "shopdb", + "FLASK_ENV": "development", + "FLASK_DEBUG": "1" + }, + "args": ["run", "--port", "5001", "--no-reload"], + "jinja": true, + "justMyCode": false, + "console": "integratedTerminal" + }, + { + "name": "Pytest (current file)", + "type": "debugpy", + "request": "launch", + "module": "pytest", + "cwd": "${workspaceFolder}", + "args": ["${file}", "-v"], + "console": "integratedTerminal" + } + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..955e81f --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,43 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Backend: flask run (:5001)", + "type": "shell", + "command": "${workspaceFolder}/venv/bin/flask run --port 5001", + "options": { + "cwd": "${workspaceFolder}", + "env": { "FLASK_APP": "shopdb" } + }, + "windows": { + "command": "${workspaceFolder}\\venv\\Scripts\\flask.exe run --port 5001" + }, + "isBackground": true, + "problemMatcher": [] + }, + { + "label": "Frontend: npm run dev (:5173)", + "type": "shell", + "command": "npm run dev", + "options": { "cwd": "${workspaceFolder}/frontend" }, + "isBackground": true, + "problemMatcher": [] + }, + { + "label": "Dev site (backend + frontend)", + "dependsOn": [ + "Backend: flask run (:5001)", + "Frontend: npm run dev (:5173)" + ], + "dependsOrder": "parallel", + "problemMatcher": [] + }, + { + "label": "Check: naming + tests + build", + "type": "shell", + "command": "bash scripts/check-naming-and-style.sh && venv/bin/python -m pytest tests/ -q && cd frontend && npx vitest run && npm run build", + "options": { "cwd": "${workspaceFolder}" }, + "problemMatcher": [] + } + ] +} diff --git a/README.md b/README.md index b510556..705500b 100644 --- a/README.md +++ b/README.md @@ -148,11 +148,13 @@ pip install -r requirements.txt cp .env.example .env # Edit .env with your database credentials and secrets. +export FLASK_APP=shopdb flask db upgrade +flask plugin upgrade-all # per-plugin schema (ADR-008) flask seed permissions flask seed settings flask seed reference-data -flask run +flask run --port 5001 # MUST be 5001 - the frontend dev server proxies here # Frontend (separate terminal) cd frontend @@ -162,7 +164,10 @@ npm run build # production build into frontend/dist (served by Flask) ``` Complete first-run setup at `/setup`, or run `flask seed admin` for a headless -admin account. +admin account. The repo ships VS Code config in `.vscode/` (F5 debugs the +backend; a "Dev site" task runs both servers). A fuller day-one walkthrough, +including VS Code and troubleshooting, is the DEVELOPMENT-SETUP page in the +project wiki. To import a site's legacy data, use the HTTP import surface: an admin API token plus [docs/IMPORT-API.md](docs/IMPORT-API.md) drive the whole migration diff --git a/docs/DEVELOPMENT-SETUP.md b/docs/DEVELOPMENT-SETUP.md new file mode 100644 index 0000000..ebab2fa --- /dev/null +++ b/docs/DEVELOPMENT-SETUP.md @@ -0,0 +1,213 @@ +# Development setup: from clone to first change + +The goal of this page: a new developer clones the repo and has a working dev +site plus a change they can see in the browser, in one sitting. Reference +material lives elsewhere - naming rules in `CONTRIBUTING.md`, every config +variable in the CONFIG guide, plugin authoring in the PLUGIN docs - this is +just the on-ramp. + +Two ways to run it. **Docker** is the fastest to a working site (one command +brings up MySQL + the app). **Manual (venv + Node)** is what most people +iterate with, because the frontend hot-reloads and the backend restarts on +save. Do Docker first to confirm the box is sane, then switch to manual for +day-to-day work - or go straight to manual if you already have a MySQL. + +--- + +## 0. Prerequisites + +| Need | Version | Check | +| --- | --- | --- | +| Python | 3.12 (64-bit) | `python --version` | +| Node.js | 18+ | `node --version` | +| MySQL | 8.0 (or Docker, below) | `mysql --version` | +| Git | any recent | `git --version` | + +--- + +## 1. Get the code + +```bash +git clone https://github.com/ge-aero/shopdb-flask.git +cd shopdb-flask +``` + +Never work on `main`. Branch for your change: + +```bash +git checkout -b feat/ +``` + +--- + +## 2a. Fast path - Docker (a working site in one command) + +```bash +cp .env.example .env +# Edit .env: set SECRET_KEY, JWT_SECRET_KEY, and the MYSQL_* passwords. +# Generate a secret: python -c "import secrets;print(secrets.token_urlsafe(64))" + +docker compose up -d --build # MySQL + the app (frontend built in-image) + +# Schema + platform data (idempotent, safe to re-run): +docker compose exec api flask db upgrade +docker compose exec api flask plugin upgrade-all +docker compose exec api flask seed permissions +docker compose exec api flask seed settings +docker compose exec api flask seed reference-data +docker compose exec api flask seed admin --username admin --email you@example.com +``` + +The app is on the port the compose file maps (see `docker-compose.yml`). Good +for a smoke test; for active development use the manual path so the frontend +hot-reloads. + +--- + +## 2b. Manual path - venv + Node (the daily driver) + +### Database + +Either point at an existing MySQL 8, or bring one up with just the db service +from compose: + +```bash +docker compose up -d db # MySQL on 127.0.0.1:3306 +``` + +Create the database + app user (skip if compose already did via env): + +```sql +CREATE DATABASE shopdb_flask CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +CREATE USER 'shopdb'@'%' IDENTIFIED BY 'devpassword'; +GRANT ALL PRIVILEGES ON shopdb_flask.* TO 'shopdb'@'%'; +FLUSH PRIVILEGES; +``` + +### Backend + +```bash +python -m venv venv +source venv/bin/activate # Windows: venv\Scripts\activate +pip install -r requirements.txt + +cp .env.example .env +# Set SECRET_KEY, JWT_SECRET_KEY, and +# DATABASE_URL=mysql+pymysql://shopdb:devpassword@127.0.0.1:3306/shopdb_flask?charset=utf8mb4 +# CORS_ORIGINS=http://localhost:5173 + +export FLASK_APP=shopdb +flask db upgrade # core schema +flask plugin upgrade-all # per-plugin schema (ADR-008) +flask seed permissions +flask seed settings +flask seed reference-data +flask seed admin --username admin --email you@example.com # password printed once +``` + +Enable the plugins you want visible (they install on a fresh box; some ship +disabled). To turn on everything for development: + +```bash +for p in computers employees machines measuringtools network notifications \ + printers slides usb warranty knowledgebase geenforce printedparts; do + flask plugin install "$p"; flask plugin enable "$p" +done +``` + +Run the backend ON PORT 5001 - the frontend dev server proxies `/api` and +`/static` there (a bare `flask run` uses 5000 and nothing will load): + +```bash +flask run --port 5001 +``` + +### Frontend (a second terminal) + +```bash +cd frontend +npm install +npm run dev # http://localhost:5173 +``` + +Open http://localhost:5173, log in as `admin` with the printed password. + +> Convenience: instead of two terminals you can run both under a process +> manager (pm2, honcho, foreman). Keep the backend on 5001. + +--- + +## 2c. VS Code (turnkey) + +The repo ships shared VS Code config in `.vscode/` (personal `settings.json` +stays git-ignored): + +- **Recommended extensions** - on first open VS Code offers to install them + (Python + Pylance, Vue Volar, ESLint, Docker). Accept. +- **Run the dev site** - Command Palette > "Tasks: Run Task" > + **Dev site (backend + frontend)** starts both servers in parallel (backend + on 5001, frontend on 5173). Individual tasks exist too. +- **Debug the backend** - the Run panel's **Flask API (:5001)** config runs + the app under the debugger (breakpoints in routes/services, full + stepping); **Pytest (current file)** debugs the open test file. +- **The CI gate** - task **Check: naming + tests + build** runs the same + three checks CI runs, before you commit. + +Prerequisite: the venv and `npm install` from 2b must be done first (the +tasks call `venv/` and `frontend/node_modules`). + +--- + +## 3. The development loop + +1. Make a change. Backend: `flask run` auto-reloads. Frontend: Vite hot-reloads. +2. Before committing, run the same three gates CI runs: + ```bash + bash scripts/check-naming-and-style.sh # the LOCKED naming convention + venv/bin/python -m pytest tests/ -q # backend + cd frontend && npx vitest run && npm run build + ``` +3. Commit in small, working steps. Subject: short, present tense, plain + English; body says WHY. Read `CONTRIBUTING.md` before naming anything - the + naming hook will reject snake_case DB columns, banned shorthand, and + non-ASCII. + +Seeing a change in the real app (not just tests) is the bar for "done" - +drive the actual flow in the browser. + +--- + +## 4. Your first change (suggested) + +Add a field to an existing list page, or better, build a plugin end to end: +`docs/PLUGIN-LAB-PRINTEDPARTS.md` is a literal type-along that constructs the +3D-printed-parts plugin from scratch, with the finished code on branch +`feat/printedparts-plugin` (tags `lab-stage-01`..`lab-stage-17`) as the +answer key. It touches every hook the framework has. + +--- + +## 5. Contributing back + +```bash +git push -u origin feat/ +``` + +Open a Pull Request against `main` on GitHub. Describe what changed, any +plugin hooks implemented, and any contract additions (those need a version +bump + `docs/PLUGIN-HOOKS.md` update in the same PR). See the contributor +section of the plugin lab for the full review checklist. + +--- + +## Common setup problems + +| Symptom | Cause / fix | +| --- | --- | +| Frontend loads but every API call fails / CORS error | backend not on 5001 (`flask run --port 5001`), or `CORS_ORIGINS` missing `http://localhost:5173`. | +| App refuses to boot in production config | a required `.env` var (`SECRET_KEY`, `JWT_SECRET_KEY`, `DATABASE_URL`, `CORS_ORIGINS`) missing or a dev default. | +| `flask db upgrade` error 1071 (key too long) | MySQL 5.6 without the `innodb_large_prefix`/Barracuda flags; use MySQL 8 for dev. | +| Nav missing Machines/PCs/... | plugins not installed/enabled (step 2b), or the backend not restarted after enabling. | +| "No time zone found with key America/New_York" | `tzdata` not installed - `pip install -r requirements.txt` includes it. | +| Naming hook rejects a commit | you used snake_case on a DB-mirrored field or a banned acronym - see `CONTRIBUTING.md`. | +| Plugin toggle throws an internal error | app cannot write `instance/` (the plugin registry lives there) - fix directory permissions. |