Integrate VictoriaLogs in milner #62
No reviewers
Labels
No labels
blocked
bug
duplicate
effort
high
effort
low
effort
medium
effort
minimal
enhancement
help wanted
invalid
pr
feedback
pr
reviewing
question
status
backlog
status
document
status
done
status
implement
status
pending
status
planning
status
reviewing
waiting
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
tepichord/milner!62
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/60-integrate-victorialogs"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #60
Automated PR created by forgejo-done adapter.
The per-namespace example used stream-filter syntax that LogsQL rejects: inside `{...}` is a Prometheus label selector, so it is `{kubernetes.pod_namespace="woodpecker"}`, not a `field: "value"` phrase filter. The endpoint list also called `/insert/native` a read endpoint; it is the write path the collector targets. The resize blocker undercounted Woodpecker: the durable claims are its server (10 GiB) plus its agent (1 GiB), which is what makes the total 51 GiB of 100. Refs: #60I checked the preview for the logs service and there is none, just a preview for oz again. I need the preview service to point to the new victoria logs service.
Navigating to
https://preview.faun-snapper.ts.net/select/vmui/?results only in a white screen with no console errors. The following payloads timeout when loading:`preview.faun-snapper.ts.net` dialled one Service, so a preview of the log store and a preview of the console were the same page and the only way to tell them apart was to read the router's configuration. The front door now follows the change set: each candidate Service declares the paths it previews (`milner.dev/preview-paths`), L3 publishes the pull request's changed files as `changed_paths` in the `preview-<n>-values` ConfigMap it already writes, Flux substitutes them onto every candidate as `milner.dev/preview-changed`, and the router dials the claimant. `oz` is the marked default and declares no paths, so it can neither shadow the app a change set is about nor be one side of a contention. The rule refuses rather than ranks. Two claimants, or several candidates with none claiming and no default, is not an ordering problem: the old narrowest-glob tie-break was a guess dressed as a rule, and it is deleted. The router answers 503 naming the candidates, and the console is where a human answers — `milner.dev/preview-app` on the preview's own namespace, rendered as one submit button per choice so swapping between contenders is one click, with the current choice inert. The pin survives a later push in the same pull request, dies with the preview, and is never written by a manifest or by L3. The rule is one module (`previewlib/selection.py`) with two readers, which is asserted: neither re-declares an annotation key. A router change is now exercised by its own pull request. For a change set touching `router/**` or `previewlib/**`, `build-router` pushes `preview/router:pr-<n>-<sha>` in addition to main's tag, and `publish-router-override` names it in `preview-router-tag`, which the layer reads through `postBuild.substituteFrom`. That has to be `substituteStrategy: Always` with no inline `substitute`, because an inline entry takes precedence and no override could ever win; for the same reason the committed default lives inside the manifest's `${router_image:=...}` placeholder. Rollback is deleting the ConfigMap, which every teardown path already does, so an override un-ships itself. The cost is accepted: one router pull request is live at a time, and while it is open its router serves every preview. `ci/router-tag-guard.sh` holds the invariant that makes the bump meaningful. `imagePullPolicy: IfNotPresent` plus a path-filtered build make both halves of a tag/source mismatch silent — source moved and the kubelet never re-pulls; tag moved and the build never fires — so a pull request is failed for either. The console's own image is bumped to 0.1.2 because this change set moves `oz/**` and `previewlib/**`, and nothing in CI builds `milner/oz:<pin>`: `build-oz` only ever pushes the disposable `preview/oz:pr-<n>-<sha>` a preview namespace runs. `oz/Dockerfile`'s build example reads the tag out of the manifest now rather than naming 0.1.0 — the drift `aa2b85e` fixed for the router and left out of scope there. `.dockerignore` is new because the build context is the repo root: a local build baked `oz/__pycache__/*.pyc` from a test run into the image, and the operator's `.env` was uploaded to the builder. The patterns carry `**/` since, unlike `.gitignore`, they match from the context root. The store keeps `preview.faun-snapper.ts.net` as its preview instead of taking a hostname of its own: one front door serves whichever app the change set is about, so a second one would be a second front door for what this rule already serves, plus another tailnet approval and certificate. Two of the layer's comments said otherwise and are corrected.The `test` step failed on `test_preview_paths_rejects_a_non_numeric_pull_request` with `assert '\n' == ''`, and only in CI. The suite runs inside a pipeline step, where `CI_COMMIT_PULL_REQUEST` holds the pull request under test. The script under test reads that variable on purpose — but the case in question passed an empty argument meaning "no pull request", and `${1:-...}` treats an empty argument as absent, so the case was answered by the pipeline's own number. It never reached the guard it was written for, and failed on the empty list coming back instead. Locally nothing is set, which is why it passed there. That test now names each of the two hand-set inputs where nothing else can speak for it: the argument alone, and each fallback variable alone. It also covers the fallback itself and the order of the two variables — the reason they are read at all, and previously untested. tests/conftest.py clears `CI_*` and `PREVIEW_PR` for the whole suite, so a test that spreads `os.environ` into a subprocess cannot mean something different in CI than it does locally. The failing case above would have been caught by that alone, and a test added later cannot forget it. Verified as load-bearing: with the fixture removed, the injected-environment run fails exactly as #68 did. The script itself is unchanged; its header now says what it prints — one line, empty when there is no list, and nothing at all when the number is refused — which is why two tests expect a newline and the refusal case expects no bytes.Issue: oz.faun-snapper.ts.net doesn't show "select between oz and victoria-logs" for preview-62, because: * the deployed console (milner/oz:0.1.1, three revisions behind the tree) has no Front door buttons, so the rule a person can press to disambiguate doesn't exist in the running image; * the rule itself refuses, but the candidate that the change set is about declares no paths, so it never reaches the refusal the rule writes — a change set two apps claim and one that nothing claims look the same; * the CI builds the router's main-push image but nothing builds the console's, so the console drifts behind the tree until an operator notices and pushes by hand. This change closes all three. Story 7 is the rule: oz is the only thing that picks when more than one app qualifies. The router never picks programmatically, and a change set two apps claim is refused by name, with the page pointing at the console that holds the answer. Story 17 is the infrastructure: every push to main rebuilds the console's image from the source the merge moved, and a tag bump without a source change fails the pull request before it merges. Symmetric with the router's guard and build, with the per-PR half kept as the preview variant so a preview namespace runs the simulation and not the console. Files: * USER_STORIES.md — story 7 stronger, story 17 new * apps/preview/oz.yaml — oz declares its own paths * router/app.py — refusal page names oz.<domain> * ci/oz-image.sh — symmetric with ci/router-image.sh * ci/oz-tag-guard.sh — symmetric with ci/router-tag-guard.sh * .woodpecker/gates.yaml — build-oz main-push half, oz-tag-guard step * tests/test_ci_guards.py — 8 tests for the oz tag guard * tests/test_preview_router.py — rule tests for the new candidate * tests/test_static.py — pipeline and overlay assertions 197 passed; ruff clean; shellcheck clean; per-step sh -n clean.