Files
wan e1810facd6
tests / pytest (push) Successful in 7s
Split the public banner URL from the runner-internal clone URL
Every auto-published page, in all three pipelines, carried a source link to
`localhost:3005`. The template was never at fault — it links `{{{source}}}`
verbatim; the bad URL was baked into each page's wikitext by the publisher.

Root cause was one variable serving two incompatible purposes. `URL_TO_GITEA`
has to be an address the runner container can clone from, and since the runner
uses host networking that is `http://localhost:3005`. All three workflows then
composed `GITEA_REPO_URL` — the base of the public banner link, written into
the wiki for anyone to read — out of that same loopback value.

Adds a second org variable, `PUBLIC_URL_TO_GITEA`, for the public base
(`https://git.novoyuuparosk.org`), and points the banner at it. Cloning keeps
using `URL_TO_GITEA`. The two are now documented as deliberately separate,
because collapsing them looks like tidying up.

`lib/wiki.public_source_base()` validates the banner base rather than trusting
it: unset, relative, loopback, mDNS (`*.local`) or private-range values raise
with the variable to set. A misconfiguration that would publish an unreachable
link now stops the run instead. Note the failure mode this creates on purpose:
until `PUBLIC_URL_TO_GITEA` exists, publishing aborts rather than proceeding
with a wrong URL.

Also builds the source path with `rel.as_posix()`, so the separator in a URL
does not depend on the OS the publisher runs on — it produced backslashes when
the renderer was exercised on Windows.

Prerequisites before this can publish:

1. Add the org variable `PUBLIC_URL_TO_GITEA` = https://git.novoyuuparosk.org
2. Flush the act_runner callee cache — `docker compose up -d --force-recreate
   act_runner`. Per the cross-cutting decisions log, edits to `publish-*.yml`
   keep executing the stale cached copy, and this change is in those files.

Pages already published still carry the old URL in their stored wikitext. They
are only corrected by re-publishing each pipeline in full.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 16:37:06 +09:00
..

pipelines/tech

Publishes tech blog posts from novoyuuparosk-wiki/tech-blogs to https://wiki.novoyuuparosk.org.

  • Source-file contract (frontmatter and body conventions): SCHEMA.md
  • Cross-cutting setup (wiki URL, bot identity, runner, Gitea secrets/variables): repo root README

v1 scope

  • YAML frontmatter parsing per SCHEMA.md
  • Pandoc-based markdown → wikitext body rendering (h1 elements preserved)
  • Auto-generated banner ({{Auto-generated|source=...|commit=<sha>}})
  • Category injection: [[Category:Tech blog]] on every page; [[Category:Blog:<year>]] from date field (falling back to the action's execution year); [[Category:<tag>]] 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: novoyuuparosk-wiki/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 novoyuuparosk-wiki/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) Runner-internal Gitea base URL, for cloning only
PUBLIC_URL_TO_GITEA variable Gitea (cross-cutting) Public Gitea base URL, for the banner source link only
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) PUBLIC_URL_TO_GITEA + repo path Source-file URL base for the banner link. Validated by public_source_base(): a loopback, mDNS or private-range host aborts the run rather than publishing an unreachable 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:<year> from date field; falls back to the execution year if no date 2026-06-10
Tag categories Each tag → [[Category:<tag>]] 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 novoyuuparosk-wiki/tech-blogs — pipeline ships before repo is initialised 2026-06-10

Status

v1 pipeline ready. Source repo (novoyuuparosk-wiki/tech-blogs) not yet initialised.