Add Forgejo CI: ruff lint + pytest unit + gated image publish
CI / lint (push) Successful in 3s
CI / unit (push) Successful in 4s
CI / publish (push) Successful in 13s

Family-consistent CI for StashHandler (mirrors the NhenArchiver Python
sibling, minus the integration lane — StashHandler is SQLite-only with no
service containers).

- .forgejo/workflows/ci.yml: lint (ruff) -> unit (pytest) -> publish.
  publish builds + pushes git.fabledsword.com/bvandeusen/stashhandler with
  the family rule-46 tag scheme (dev->:dev+:c-<sha>, main->:latest+:c-<sha>,
  v* tag->:<version>+:latest). Gated on lint+unit. Needs REGISTRY_TOKEN.
- tests/: starter unit suite — hashing, SQLite dedup, media filter, transfer
  modes.
- pyproject.toml: ruff target + pytest pythonpath/testpaths.
- ci-requirements.md (family rule 39), .dockerignore.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016nyYC9dTQ78SqhpNFtpMvT
This commit is contained in:
2026-06-26 10:44:49 -04:00
parent 5bcb35e737
commit 31217498ce
7 changed files with 319 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
# CI Requirements — StashHandler
> Spec lives in [`docs/process.md`](https://git.fabledsword.com/bvandeusen/CI-runner/src/branch/main/docs/process.md)
> in the CI-Runner repo.
## Runtime image
The runner image this project's CI consumes via `container.image`.
```
git.fabledsword.com/bvandeusen/ci-python:3.14
```
CI lints and tests under 3.14; the **shipped** runtime is Python 3.12 (the app
`Dockerfile` is `FROM python:3.12-slim`). The code targets 3.12+ features only
(walrus, `datetime.now(timezone.utc)`), so the version gap is intentional and
harmless.
## Image deps used
Tools/libraries already in the image that this project actually relies on:
- python 3.14 (test interpreter)
- ruff (lint lane — runs with no per-job install)
- docker CLI + buildx (used by the `publish` job's build-push step)
## Per-job tool installs
Anything CI installs *at job time* (not in the image):
- `pip`/`uv install -r requirements.txt pytest blake3` in the **unit** job.
- `pytest` — test runner (not in the image).
- `blake3` — optional runtime hash backend (`HASH_ALGORITHM=blake3`),
exercised by the hasher tests. Not in `requirements.txt` because the
default `sha256` path uses stdlib `hashlib`.
## Notes
Friction, expectations, and anything the maintainer wouldn't see otherwise:
- **No integration lane.** StashHandler persists to SQLite (per-run tmpfiles in
tests) and talks to qBittorrent/Stash over HTTP at runtime only — there is no
service container to stand up, so family rules 7982 don't apply here.
- **Three lanes:** `lint` (ruff) → `unit` (pytest) → `publish` (gated image
build+push, family rule 46 tag scheme). Publish image is
`git.fabledsword.com/bvandeusen/stashhandler` (lowercase — matches the prod
compose pull).
- Unit suite is a starter set covering the pure logic (hashing, SQLite dedup,
media-extension filter, file transfer modes). Grow it as behavior is added.
- Requires repo Actions secret **`REGISTRY_TOKEN`** (Forgejo PAT,
`read:package` + `write:package`) for the publish lane — the injected
`GITHUB_TOKEN` can't push to the registry (family rule 7).