# pipelines/tech Publishes tech blog posts from `mikkeli/tech-blogs` to `https://wiki.novoyuuparosk.org`. - Source-file contract (frontmatter and body conventions): [SCHEMA.md](SCHEMA.md) - Cross-cutting setup (wiki URL, bot identity, runner, Gitea secrets/variables): [repo root README](../../README.md) ## v1 scope - YAML frontmatter parsing per [SCHEMA.md](SCHEMA.md) - Pandoc-based markdown → wikitext body rendering (h1 elements preserved) - Auto-generated banner (`{{Auto-generated|source=...|commit=}}`) - Category injection: `[[Category:Tech blog]]` on every page; `[[Category:Blog:]]` from `date` field; `[[Category:]]` per tag entry - No title prefix — pages live at their bare title - MediaWiki bot API write with idempotency — no-op if wiki content matches generated output - Files without `wiki.publish: true` silently skipped - Pages with existing non-auto-generated content skipped (logged to stderr) ## Source repo Source repo: `mikkeli/tech-blogs` (not yet initialised — pipeline code is ready). The pipeline triggers on push to `master` and supports `workflow_dispatch` for manual runs. **Excluded paths** (won't trigger the pipeline): - `README.md`, `.gitignore`, `.claude/**` ## Invocation The pipeline runs as a self-contained Gitea Actions workflow in `mikkeli/tech-blogs` (`.gitea/workflows/publish.yml`). It clones this repo at runtime to get the renderer. Triggers: - `push` to `master` (path-filtered as above) - `workflow_dispatch` — manual trigger from the Gitea Actions UI ### Environment (secrets and variables) | Name | Kind | Source | Purpose | |---|---|---|---| | `WIKI_API_URL` | variable | Gitea (cross-cutting) | MediaWiki action API endpoint | | `WIKI_BASE_URL` | variable | Gitea (cross-cutting) | Wiki base URL | | `WIKI_BOT_USER` | secret | Gitea (cross-cutting) | Bot login | | `WIKI_BOT_PASSWORD` | secret | Gitea (cross-cutting) | BotPasswords value | | `URL_TO_GITEA` | variable | Gitea (cross-cutting) | Gitea instance base URL for cloning | | `FAPAT` | secret | Gitea (cross-cutting) | Full-Access PAT for cloning private repos | | `SOURCE_REF` | env (set in workflow) | `github.sha` | Pushed commit SHA, used in banner and edit summary | | `GITEA_REPO_URL` | env (set in workflow) | composed from vars | Source-file URL base for the banner link | ## Dependencies Job container: `novoyuuparosk-wiki-runner:latest` (pre-built, stored in the local Docker daemon on the runner host). Bakes in Python 3.12, Pandoc, and all pipeline Python packages — no install steps at job runtime. See the `Dockerfile` at the repo root and `requirements.txt` in this directory. Rebuild the image after changes to either. Shared code lives in `lib/wiki.py` (repo root). ## One-off wiki setup - [ ] **`Template:Auto-generated`** — must exist on the wiki (shared with all pipelines; already created). ## Decisions log (tech pipeline) | Decision | Value | Date | |---|---|---| | No title prefix | Tech posts live at bare titles — no namespace needed | 2026-06-10 | | Fixed category | Every post gets `Category:Tech blog` | 2026-06-10 | | Year category | `Category:Blog:` from `date` field; omitted if no date | 2026-06-10 | | Tag categories | Each tag → `[[Category:]]` with no prefix | 2026-06-10 | | WIP exclusion | None — `wiki.publish: false` is the only gate | 2026-06-10 | | Publish mode | Always `--all` | 2026-06-10 | | Idempotency | Commit SHA in banner | 2026-06-10 | | Manual-page protection | Bot skips pages without `{{Auto-generated` banner | 2026-06-10 | | Source repo | `mikkeli/tech-blogs` — pipeline ships before repo is initialised | 2026-06-10 | ## Status v1 pipeline ready. Source repo (`mikkeli/tech-blogs`) not yet initialised.