INTEGRATION-ONLY and KNOWN-LIMITATION are grep-able, but the grep answers the wrong question. Thirty-four Go sites share the two markers and they carry four different meanings: "declared, nothing implements it" reads exactly like "implemented, only its I/O is unreachable from here", and neither reads differently from a limitation that was accepted on purpose and is not coming back. docs/deferred-seams.md sorts them, following the bucketed shape internal/updater/doc.go already uses for its own package rather than starting a second convention. Sorting them turned up two markers that had outlived the condition they describe. config.go called the modpack upload transport a deferred integration after both backends had shipped -- LocalContextStore and S3ContextStore, selected in cmd/felis by the shape of user_uploads_context, with the uploads PVC mounted and the felis-uploads-s3 Secret rendered. What is still deferred is the far end: Kaniko reading that context from inside the build Pod. updater/doc.go listed the `felis update` CLI and the off-cluster Velocity jar read under REMAINING INTEGRATION. Both exist -- cmd/felis/update.go, and gatherer_host.go, which answers Velocity from the installed jar's manifest and felis-api from the running binary's build stamp. The two nil seams that bullet also names are real, but they belong to the in-cluster gatherer only, so the bullet now says which caller has what and which is still empty. The index also records the collision that makes a naive grep misleading: docs/troubleshooting.md uses [INTEGRATION-ONLY] for something else, defined in its own opening at :19 -- the symptom is produced by the kubelet, kaniko or a live handshake, so it cannot be reproduced from the repository. Those twelve marks say where a failure comes from, not that something is unbuilt, and are excluded. Both code changes are comments. Every file:line the index cites was checked against the line it points at.
56 lines
4.0 KiB
Go
56 lines
4.0 KiB
Go
// Package updater is the integration/caller side of the component self-update
|
|
// subsystem — it gives the pure decision core in internal/updates its first real
|
|
// caller. internal/updates declares the seams (ReleaseSource / Notifier / Applier)
|
|
// and orchestrates them (updates.Run) but performs no I/O; this package supplies the
|
|
// concrete wiring: the platform topology (which components Felis tracks and under
|
|
// what policy), the upstream release sources, and the Runner that gathers current
|
|
// versions, runs the plan against a maintenance window, and renders the "版本号状态"
|
|
// report.
|
|
//
|
|
// Verification boundary — stated honestly so a green test suite is not mistaken for
|
|
// "the updater works against real infra":
|
|
//
|
|
// - BUILT + UNIT-VERIFIED (Go tests, WSL oracle): the topology, BOTH release
|
|
// sources (PaperMC Fill v3 for Velocity; GitHub Releases for felis-api, k3s and
|
|
// cloudflared), the routing source, and the Runner's report-only composition. Each
|
|
// source's parser is a contract test whose fixture is captured from — and whose
|
|
// live call was exercised out-of-band against — the real endpoint: PaperMC on
|
|
// 2026-07-04 (3.4.0 is newest stable, 3.5.0-SNAPSHOT filtered), GitHub on
|
|
// 2026-07-05 (cloudflared 2026.6.1; k3s v1.36.2+k3s1, its "+k3s1"/"v" tolerated and
|
|
// its "-rcN"/prerelease builds rejected). These prove the parse/plan/compose LOGIC
|
|
// and that the core is wired to a caller for every tracked component.
|
|
//
|
|
// - CAVEATS on what the tests do NOT prove: they run against httptest, not the live
|
|
// hosts, so future upstream shape drift is not caught. On User-Agent the two APIs
|
|
// differ and the code reflects it: GitHub ENFORCES a UA (a bare request is 403'd,
|
|
// verified 2026-07-05) so Felis's UA is load-bearing there; PaperMC does NOT
|
|
// enforce (a bare request got HTTP 200 on 2026-07-04) so its UA is only etiquette.
|
|
// Also: felis-api's topology coord is now the real repository slug, not a placeholder,
|
|
// so that component resolves at runtime like the others — but only with a credential.
|
|
// The repo is private, so an unauthenticated poll gets GitHub's 404-for-hidden-repo and
|
|
// degrades to "latest unknown"; FELIS_GITHUB_TOKEN is what lights it up. k3s and
|
|
// cloudflared are public and need none.
|
|
//
|
|
// - ALSO BUILT + UNIT-VERIFIED: the VersionGatherer's extraction core and dispatch.
|
|
// Three pure extractors turn raw system text into a Version — a `--version` banner
|
|
// (k3s, cloudflared), a container image tag (felis-api), a proxy jar filename
|
|
// (velocity) — and sysGatherer routes each component to the right one over an
|
|
// injected seam, all exercised with a fake runner (gatherer_test.go). The
|
|
// load-bearing case is proven: k3s's registry tag "v1.36.2-k3s1" is repaired to the
|
|
// "+k3s1" build form the binary reports (a Docker tag cannot hold '+'), so an image
|
|
// read and a CLI read agree instead of the image masquerading as a prerelease. The
|
|
// CLI seam (execRunner) is wired for real; only its exec I/O is un-verified here.
|
|
//
|
|
// - REMAINING INTEGRATION (genuinely I/O-bound — needs a cluster/mailbox): the two
|
|
// current-version PRODUCING seams NewSysGatherer still leaves nil — the k8s read of
|
|
// the control-plane Deployment's image (felis-api) and the Velocity jar inspection —
|
|
// so an IN-CLUSTER caller surfaces a gather error rather than a wrong version. The
|
|
// ON-HOST caller has both: NewHostGatherer (gatherer_host.go) answers felis-api from
|
|
// the running binary's build stamp and Velocity from the installed jar's manifest,
|
|
// and that is what the built `felis update` CLI runs on. Still absent: the concrete
|
|
// Notifier (SMTP + in-game) and Applier (control-plane image bump, cloudflared swap)
|
|
// — the CLI passes nil for both on purpose, so it reports and never applies — the
|
|
// in-cluster CronJob entry point, and the runtime append of the live Pinned
|
|
// Minecraft fleet.
|
|
package updater
|