Restore f1-stream stack — undo accidental bundling into 63fe7d2b
Commit 63fe7d2b (fan-control) was made with a bare `git commit` in the shared infra working tree and inadvertently swept in a parallel session's staged f1-stream-extraction work (main.tf repoint, ~48 files/ removals, ci-cd.md + .claude docs, two extraction plan docs). This returns every f1-stream-related path to its pre-63fe7d2b state (3493c347) so that extraction can be committed cleanly by its own session. The fan-control files added in 63fe7d2b are untouched. [ci skip] Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
90ad6b9125
commit
147a8cff40
54 changed files with 9563 additions and 163 deletions
|
|
@ -58,9 +58,10 @@ graph LR
|
|||
|
||||
### Project Migration Status
|
||||
|
||||
**Migrated to GHA (8 projects)**:
|
||||
**Migrated to GHA (9 projects)**:
|
||||
- Website
|
||||
- k8s-portal
|
||||
- f1-stream
|
||||
- claude-memory-mcp
|
||||
- apple-health-data
|
||||
- audiblez-web
|
||||
|
|
@ -68,14 +69,6 @@ graph LR
|
|||
- insta2spotify
|
||||
- book-search (audiobook-search)
|
||||
|
||||
**Woodpecker-native owned-app builds** (build + push to the Forgejo private
|
||||
registry + `kubectl set image` rollout, all in one `.woodpecker.yml`; Keel
|
||||
stays enrolled as a redundant net):
|
||||
- `tuya_bridge`, `job-hunter`, `f1-stream`
|
||||
- `f1-stream` was extracted from this monorepo into its own repo
|
||||
(`viktor/f1-stream`) on 2026-06-04; its Woodpecker repo id is 166 (the old
|
||||
GHA-era id 10 is defunct).
|
||||
|
||||
**Woodpecker-only (infra + large apps)**:
|
||||
- `travel_blog`: 5.7GB content directory exceeds GHA limits
|
||||
- Infra pipelines: require cluster access (terragrunt apply, certbot, build-cli)
|
||||
|
|
@ -99,6 +92,7 @@ Woodpecker API uses numeric IDs (not owner/name):
|
|||
| travel_blog | 5 |
|
||||
| webhook-handler | 6 |
|
||||
| audiblez-web | 9 |
|
||||
| f1-stream | 10 |
|
||||
| plotting-book | 43 |
|
||||
| claude-memory-mcp | 78 |
|
||||
| infra-onboarding | 79 |
|
||||
|
|
|
|||
|
|
@ -1,78 +0,0 @@
|
|||
# f1-stream extraction + productionization — design (2026-06-04)
|
||||
|
||||
## Problem
|
||||
|
||||
`f1-stream` (FastAPI backend serving a SvelteKit SPA; ~15 pluggable stream
|
||||
extractors + a Playwright/chrome-service playback verifier) lived **inside**
|
||||
the infra monorepo at `infra/stacks/f1-stream/files/`. It had:
|
||||
|
||||
- no standalone repo — source coupled to the Terraform stack;
|
||||
- **no real CI** — only a manual `redeploy.sh` doing a local `docker buildx`
|
||||
push to DockerHub (`viktorbarzin/f1-stream`) + `kubectl rollout restart`;
|
||||
- no README, no tests, a loose unpinned `requirements.txt`, no semver tags;
|
||||
- a stale CI claim in docs ("migrated to GHA, Woodpecker repo id 10") that did
|
||||
not match reality (no GHA workflow ever existed for it).
|
||||
|
||||
## Goal
|
||||
|
||||
Extract the app into its own Forgejo repo `viktor/f1-stream` and productionize
|
||||
it, mirroring the established owned-app pattern (`tuya_bridge`, `job-hunter`,
|
||||
`tripit`, `travel-agent`).
|
||||
|
||||
## Decisions (with rationale)
|
||||
|
||||
- **Registry → Forgejo private** (`forgejo.viktorbarzin.me/viktor/f1-stream`),
|
||||
matching the fleet standard. Needs the `registry-credentials` pull secret
|
||||
(Kyverno-synced to every namespace) on the deployment.
|
||||
- **Packaging → Poetry + ruff + mypy** (replaces the loose pip
|
||||
`requirements.txt`). Python **package stays `backend`** — imports are
|
||||
`from backend.x` and the entrypoint is `uvicorn backend.main:app`; renaming
|
||||
would churn every module + the Dockerfile + the staticfiles path. Python
|
||||
**3.13 kept** (the live image already runs it; tripit's 3.12 pin is for
|
||||
zxing-cpp/pymupdf, which f1-stream lacks).
|
||||
- **Tests → pragmatic pure-logic only**. The extractors + verifier are
|
||||
network/browser-bound; full coverage is brittle. Unit-test the deterministic
|
||||
core: `m3u8_rewriter` (incl. the EXT-X tag rewriters), the `proxy` HLS
|
||||
parsers, `schedule` parsing/status, the extractor `registry`. 63 tests.
|
||||
- **CI → single `.woodpecker.yml`**: `lint-and-test` (ruff + mypy + pytest on
|
||||
`python:3.13-slim`) → `build-and-push` (buildx → Forgejo, tags `latest` +
|
||||
`${CI_COMMIT_SHA:0:8}`) → `deploy` (`kubectl set image` + `rollout status`).
|
||||
**Keel stays enrolled** as a redundant net. This is the `tuya_bridge`
|
||||
"build drives the rollout" model + a `travel-agent`-style test gate.
|
||||
- A Slack-notify step was prototyped but **dropped**: the
|
||||
`environment: { from_secret }` form is rejected by this Woodpecker
|
||||
version's pipeline-struct decoder (`yaml: did not find expected key`), and
|
||||
the canonical owned-app refs (`tuya_bridge`, `job-hunter`) have no Slack
|
||||
step. Deploy success is confirmed by `rollout status`.
|
||||
- **Versioning → first git tag `v2.0.1`** (continuity with the existing image
|
||||
lineage; a fresh `v0.1.0` on a production 2.x app would mislead
|
||||
monitoring/homepage). Deviates deliberately from the `v0.1.0` precedent of
|
||||
tripit/travel-agent.
|
||||
- **Runtime stays root** (matching the prior working image) to avoid a
|
||||
non-root regression on the `/data` NFS write path and the Playwright browser
|
||||
cache. Non-root is a possible future hardening.
|
||||
|
||||
## Terraform delta (the only infra change)
|
||||
|
||||
`infra/stacks/f1-stream/main.tf`:
|
||||
|
||||
- image `viktorbarzin/f1-stream:latest` (DockerHub) →
|
||||
`forgejo.viktorbarzin.me/viktor/f1-stream:${var.image_tag}` (new
|
||||
`var.image_tag`, default `latest`);
|
||||
- add `image_pull_secrets { name = "registry-credentials" }` to the pod spec;
|
||||
- delete `files/` (source now lives in the standalone repo) and `redeploy.sh`.
|
||||
|
||||
The image field is in the deployment's `ignore_changes` (KEEL_IGNORE_IMAGE), so
|
||||
the live tag is managed by CI/Keel, not Terraform. Everything else — namespace,
|
||||
ExternalSecrets (`f1-stream-secrets`, `chrome-service-client-secrets`), NFS data
|
||||
volume, Anubis PoW policy, `ingress_factory`, homepage + x402 annotations,
|
||||
Discord + chrome-service env — is unchanged.
|
||||
|
||||
## Blast radius
|
||||
|
||||
- The `f1-stream` K8s service is the only consumer; no other stack references
|
||||
`viktorbarzin/f1-stream` or the `files/` dir (verified: no `path.module` /
|
||||
`archive_file` / `null_resource` references the dir).
|
||||
- Adding `imagePullSecrets` triggers one Recreate rollout that pulls the
|
||||
*current* (still-DockerHub, public) image — safe; CI then switches it to the
|
||||
Forgejo image.
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
# f1-stream extraction + productionization — plan (2026-06-04)
|
||||
|
||||
Companion to `2026-06-04-f1-stream-extraction-design.md`.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Scaffold** `/home/wizard/code/f1-stream/` — copy `backend/`, `frontend/`,
|
||||
`Dockerfile`, `.dockerignore` from `infra/stacks/f1-stream/files/` by name
|
||||
(exclude the `.claude/` marker + `redeploy.sh`); add `README.md`,
|
||||
`.gitignore`. ✅
|
||||
2. **Poetry conversion** — `pyproject.toml` (dist `f1-stream` v2.0.1,
|
||||
`packages=[{include="backend"}]`, pinned deps), `poetry.lock`, ruff/mypy/
|
||||
pytest config (E501 per-file-ignored on the embedded-JS/scraper modules).
|
||||
Rewrite the Dockerfile to a Poetry multi-stage build (Poetry 2.1.3 to match
|
||||
the lock; python:3.13; keep Chromium libs + `playwright install chromium`;
|
||||
keep `backend/` + `frontend/build/` siblings under `/app`). ✅
|
||||
3. **Tests** — 63 pytest unit tests over the pure-logic core. ✅
|
||||
4. **CI** — single `.woodpecker.yml` (lint+test → buildx push to Forgejo →
|
||||
`kubectl set image` + rollout). ✅
|
||||
5. **Create + push** — Forgejo repo `viktor/f1-stream` (private), commit, push
|
||||
`master`, tag `v2.0.1`. ✅
|
||||
6. **Enable in Woodpecker** — activate via
|
||||
`scripts/woodpecker-register-forgejo-repo.sh` (Woodpecker repo id 166);
|
||||
org-level `forgejo_user`/`forgejo_push_token` secrets apply. ✅
|
||||
7. **Repoint Terraform** — `main.tf` image → Forgejo + `var.image_tag` +
|
||||
`image_pull_secrets`; `tg apply`. ✅
|
||||
8. **Untrack from infra** — `git rm -r stacks/f1-stream/files`; add
|
||||
`/f1-stream/` to the monorepo root `.gitignore`. ✅
|
||||
9. **Docs** — fix the stale "GHA / repo id 10" claim in `.claude/CLAUDE.md` +
|
||||
`docs/architecture/ci-cd.md`; update `service-catalog.md`; this design/plan
|
||||
pair. ✅
|
||||
10. **Verify** — pipeline green; pod runs the Forgejo image; `/health` 200;
|
||||
ingress reachable through Anubis.
|
||||
|
||||
## Verification commands
|
||||
|
||||
```bash
|
||||
# pipeline
|
||||
curl -s https://ci.viktorbarzin.me/api/repos/166/pipelines/<n> -H "Authorization: Bearer <jwt>"
|
||||
# running image is the Forgejo one
|
||||
kubectl get deploy f1-stream -n f1-stream \
|
||||
-o jsonpath='{.spec.template.spec.containers[0].image}'
|
||||
kubectl get pods -n f1-stream -l app=f1-stream
|
||||
# health
|
||||
kubectl exec -n f1-stream deploy/f1-stream -- \
|
||||
python -c "import urllib.request;print(urllib.request.urlopen('http://localhost:8000/health').read())"
|
||||
```
|
||||
|
||||
## Rollback
|
||||
|
||||
The DockerHub image `viktorbarzin/f1-stream` and its tags still exist. To
|
||||
revert: `kubectl -n f1-stream set image deployment/f1-stream
|
||||
f1-stream=viktorbarzin/f1-stream:<tag>` and restore the `main.tf` image string.
|
||||
The standalone repo + Forgejo image are additive; nothing is destroyed.
|
||||
Loading…
Add table
Add a link
Reference in a new issue