From 0716d602e27a35627031efd5c6b492917e02d936 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Sun, 22 Mar 2026 13:52:47 +0300 Subject: [PATCH] docs: add CI/CD context file and pre-commit lint rule Create contexts/ci-cd.md documenting release pipeline, build scripts, CI runners, and versioning. Reference it from CLAUDE.md context table. Add mandatory pre-commit lint check rule to CLAUDE.md. --- CLAUDE.md | 11 +++++-- contexts/ci-cd.md | 80 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 contexts/ci-cd.md diff --git a/CLAUDE.md b/CLAUDE.md index 368720b..d1d1567 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -38,6 +38,7 @@ ast-index changed --base master # Show symbols changed in current bran | [contexts/graph-editor.md](contexts/graph-editor.md) | Visual graph editor changes | | [contexts/server-operations.md](contexts/server-operations.md) | Server restart, startup modes, demo mode | | [contexts/chrome-tools.md](contexts/chrome-tools.md) | Chrome MCP tool usage for testing | +| [contexts/ci-cd.md](contexts/ci-cd.md) | CI/CD pipelines, release workflow, build scripts | | [server/CLAUDE.md](server/CLAUDE.md) | Backend architecture, API patterns, common tasks | ## Task Tracking via TODO.md @@ -64,9 +65,15 @@ This applies to: file paths in `StorageConfig`, JSON root keys (e.g. `picture_ta **Incident context:** A past rename of `picture_targets.json` → `output_targets.json` was done without migration. The app created a new empty `output_targets.json` while the user's 7 targets sat unread in the old file. Data was silently lost. -## CI/Release Workflow +## Pre-Commit Checks (MANDATORY) -When modifying the release workflow (`.gitea/workflows/release.yml`), **always keep the release description body in sync with actual build artifacts**. If you add/remove/rename a build artifact (ZIP, installer, tarball, Docker image), update the release description table in the `create-release` job to match. +Before every commit, run the relevant linters and fix any issues: + +- **Python changes**: `cd server && ruff check src/ tests/ --fix` +- **TypeScript changes**: `cd server && npx tsc --noEmit && npm run build` +- **Both**: Run both checks + +Do NOT commit code that fails linting. Fix the issues first. ## General Guidelines diff --git a/contexts/ci-cd.md b/contexts/ci-cd.md new file mode 100644 index 0000000..ce03c53 --- /dev/null +++ b/contexts/ci-cd.md @@ -0,0 +1,80 @@ +# CI/CD & Release Workflow + +## Workflows + +| File | Trigger | Purpose | +|------|---------|---------| +| `.gitea/workflows/test.yml` | Push/PR to master | Lint (ruff) + pytest | +| `.gitea/workflows/release.yml` | Tag `v*` | Build artifacts + create Gitea release | + +## Release Pipeline (`release.yml`) + +Four parallel jobs triggered by pushing a `v*` tag: + +### 1. `create-release` +Creates the Gitea release with a description table listing all artifacts. **The description must stay in sync with actual build outputs** — if you add/remove/rename an artifact, update the body template here. + +### 2. `build-windows` (cross-built from Linux) +- Runs `build-dist-windows.sh` on Ubuntu with NSIS + msitools +- Downloads Windows embedded Python 3.11 + pip wheels cross-platform +- Bundles tkinter from Python MSI via msiextract +- Builds frontend (`npm run build`) +- Pre-compiles Python bytecode (`compileall`) +- Produces: **`LedGrab-{tag}-win-x64.zip`** (portable) and **`LedGrab-{tag}-setup.exe`** (NSIS installer) + +### 3. `build-linux` +- Runs `build-dist.sh` on Ubuntu +- Creates a venv, installs deps, builds frontend +- Produces: **`LedGrab-{tag}-linux-x64.tar.gz`** + +### 4. `build-docker` +- Plain `docker build` + `docker push` (no Buildx — TrueNAS runners lack nested networking) +- Registry: `{gitea_host}/{repo}:{tag}` +- Tags: `v0.x.x`, `0.x.x`, and `latest` (stable only, not alpha/beta/rc) + +## Build Scripts + +| Script | Platform | Output | +|--------|----------|--------| +| `build-dist-windows.sh` | Linux → Windows cross-build | ZIP + NSIS installer | +| `build-dist.sh` | Linux native | tarball | +| `server/Dockerfile` | Docker | Container image | + +## Release Versioning + +- Tags: `v{major}.{minor}.{patch}` for stable, `v{major}.{minor}.{patch}-alpha.{n}` for pre-release +- Pre-release tags set `prerelease: true` on the Gitea release +- Docker `latest` tag only applied to stable releases +- Version in `server/pyproject.toml` should match the tag (without `v` prefix) + +## CI Runners + +- Two TrueNAS Gitea runners with `ubuntu` tags +- No Windows runner available — Windows builds are cross-compiled from Linux +- Docker Buildx not available (networking limitations) — use plain `docker build` + +## Test Pipeline (`test.yml`) + +- Installs `opencv-python-headless` and `libportaudio2` for CI compatibility +- Display-dependent tests are skipped via `@requires_display` marker +- Uses `python` not `python3` (Git Bash on Windows resolves `python3` to MS Store stub) + +## Common Tasks + +### Creating a release +```bash +git tag v0.2.0 +git push origin v0.2.0 +``` + +### Creating a pre-release +```bash +git tag v0.2.0-alpha.1 +git push origin v0.2.0-alpha.1 +``` + +### Adding a new build artifact +1. Update the build script to produce the new file +2. Add upload step in the relevant `build-*` job +3. **Update the release description** in `create-release` job body template +4. Test with a pre-release tag first