Repository navigation
fix(engine): run retention keeps the run a baseline names, so regression checks keep working - #378
Merged
Merged
Conversation
…ion checks keep working
baseline_runs names a run by id, and neither retention query left that run
out. Set a LOAD baseline on a run, and 90 days later the daily sweep, or an
earlier kates test prune, deleted it like any other finished run. From then
on GET /api/tests/{id}/report/regression answered 404 "Baseline run not
found" for every LOAD run, so kates test baseline checks and the MCP
assess_run regression part failed until someone set a new baseline by hand.
Both queries behind RunRetention, the count and the ids, now leave out a run
any baseline names, so DELETE /api/tests and the sweep keep it however old
it is, and matched still equals what a call can delete: remaining reaches 0
and callers stop. DELETE /api/tests/{id} can still delete a baseline's run.
TestResourcePruneTest covers both queries on H2 through the endpoint. The
OpenAPI description, kates/docs/api-reference.md and the book's retention
passages name the exception, and the anchored findWithResults caveat ref
moves down by the six lines added above it.
This was referenced Oct 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A baseline names a run by id.
baseline_runs(V22) holds one row per test type, with arun_idcolumn that has no foreign key. Run retention ignored it.TestRunRepository.countByStatusCreatedBeforeandfindIdsByStatusCreatedBefore, the two queries behindRunRetention, matched on status andcreatedAtonly. So the run a baseline names was deleted like any other finished run.Checked in the code:
kates.cleanup.retention-days=90), the daily sweep deletes X. Akates test pruneorDELETE /api/testswith a later cutoff deletes it sooner.BaselineService.compareRegressionfinds the baseline row but not its run, and returnsBaseline run not found: X.ReportResourceanswers that with404, soGET /api/tests/{id}/report/regressionfails for every LOAD run.kates report regressionand the regression part of the MCPassess_runtool fail the same way, until someone sets a new baseline by hand.The failure is loud, not silent: the
404names the missing run. The run's data is gone, though. The chart's cleanup CronJob is off by default (cleanup.enabled: false), so on a default install the in-app 90-day sweep is the path that deletes it.Both queries have to change together. If only the id query left the baseline's run out, the count would still include it.
remainingwould then never reach 0,kates test prunewould stop after a call that deleted nothing and exit 1 with a run "left", and the daily sweep would log one still matching every day.Changes
TestRunRepositorycountByStatusCreatedBeforeandfindIdsByStatusCreatedBeforeboth addAND r.id NOT IN (SELECT b.runId FROM BaselineEntity b).BaselineEntity.runIdisNOT NULL, soNOT INis safe.findWithResults.TestResourceDELETE /api/testsOpenAPI description ends with "A run a test type's baseline names is never pruned." The description keeps its 7 lines, so no ref intoTestResource.javamoves.kates mcpfindWithResultsref inmcp_caveats.go:171moves fromTestRunRepository.java:354-374to360-380, by the 6 lines added above it. Its anchors are unchanged.Docs
kates test prunekeep the run it names.kates test deletecan still delete it, and the regression check then answers404until a new baseline is set.test pruneand its daily-sweep paragraph say the run a test type's baseline names is kept, however old it is.DELETE /api/testssays that run never matches. The daily-sweep paragraph leaves it alone too.kates/docs/api-reference.md: the same two sentences as book 11.The docs state the behaviour plainly, with no version in them. The CLI help for
kates test pruneis unchanged.Older Kates APIs. A Kates API up to 1.25.1 still deletes baseline runs. The CLI talks to both, and the behaviour belongs to the API.
Tests
Added:
TestResourcePruneTest.aBaselineRunIsNeverPruned, on H2 throughDELETE /api/tests, so it runs both queries against a real database.matched1. The prune answersmatched1,deleted1 andremaining0. The baseline's run is still stored and the other is gone. The audit log has a row for the other run only.TestResourcePruneTestnow injectsBaselineServiceand unsets the LOAD baseline in@AfterEach.TestCleanupSchedulerTestandTestResourceDeleteTestmock the repository, so they cannot see the queries. They are unchanged, and so isTestRunRepositoryTest, which fix(engine): a status poll writes only over the status it read, so a cancelled run stays cancelled #377 edits.Run locally, all passing:
git diff --name-only origin/main...HEAD:cli/cmd/mcp_caveats.go,docs/book/{02,10,11,12},kates/docs/api-reference.md,TestResource.java,TestRunRepository.javaandTestResourcePruneTest.java. That triggers the Java, CLI and Book/docs sets. Nothing changed undercharts/,.github/orscripts/, nor in theMakefileor any YAML file.cd kates && ./mvnw -o test -Dquarkus.grpc.codegen.skip=true -Dquarkus.http.test-port=0: 1,467 tests, 0 failures, 1 error.AdvisorResourceTest.analyzeReturns404ForMissingRun, with MockitoWrongTypeOfReturnValue.TestCleanupScheduler(@Scheduled every=24h) fires when the app starts. It calls the mockedTestRunRepository.countByStatusCreatedBeforewhile this first test class is stubbingfindById.RunRetention, so it is recorded as a flake.-Dtest='AdvisorResourceTest,TestResourcePruneTest,RunRetention*Test,TestCleanupScheduler*Test' -Dsurefire.failIfNoSpecifiedTests=false: 32 tests, 0 failures.AdvisorResourceTest2/2,TestResourcePruneTest24/24 with the new test,TestCleanupSchedulerTest6/6.cd kates && JAVA_HOME=$HOME/.sdkman/candidates/java/25.0.2-graalce ./mvnw -o spotless:check -Dquarkus.grpc.codegen.skip=true: BUILD SUCCESS.cd cli && go test ./...: every package ok.TestMCPCaveat*again with-count=1also passes, so the re-pointedTestRunRepository.java:360-380ref resolves.cd cli && go vet ./...: clean.cd cli && golangci-lint run --new-from-rev=origin/main ./...: 0 issues.cd cli && govulncheck ./...: no vulnerabilities.scripts/check-cli-style.shandscripts/check-cli-compat.sh: OK.scripts/check-book-style.sh: OK. The structure ratchet passes, with 38 pages within the baseline.scripts/gen-version-matrix.sh --checkandscripts/gen-chart-table.sh --check: in sync.python3 scripts/check-book-contrast.py: all 170 colour pairs meet WCAG AA.scripts/check-mermaid.sh --quiet: 156 diagrams, 0 invalid.scripts/prepare-book-render.sh && quarto render docs/book --to html, on a scratch copy ofdocs/andscripts/: 39 chapters prepared, all 38 pages rendered.python3 scripts/check-book-fragments.pyon that render: all 7,458 fragment links in 38 pages land on an id.Not run, because nothing they check changed:
helm lint,helm template,check-versions.shandyamllint(nocharts/**or YAML changes);actionlint,shellcheckandmake check-help(no.github/**,scripts/**orMakefilechanges).Run only in CI:
ci.ymlJava job,./mvnw verify: the*ITfailsafe tests, which need Docker.native.yml: the native image build and smoke test, triggered bykates/**.integration.yml: the Kind tests.ci-docker.yml: the Docker image builds.book.yml: the PDF render.github-advanced-securityAI scan, which fails on every PR on GitHub's side.Decisions
kates test prunehelp is unchanged (cli/cmd/prune.go). The behaviour is the API's, and the book covers it.DELETE /api/tests/{id}on a baseline's run still deletes it. Whether that delete should refuse, or unset the baseline, is a follow-up.kates test baseline set <run-id>. This belongs in the next release notes.Deliberately not done
DELETE /api/tests/{id}can still leave a baseline dangling. After it deletes a baseline's run, the regression check answers404until a new baseline is set, as book 02 now says. Left as a follow-up, by decision.baseline_runs.run_id. The queries leave the run out, so retention needs none, and the table has at most one row per test type. No index is needed either.RunRetention.javaandTestCleanupScheduler.javaare not touched. Refs cite their lines (RunRetention.java:82,TestCleanupScheduler.java:97), so their javadoc stays as it is.charts/kates/README.mdis not touched. It defers to the API, and an edit there would need a chart version bump.404in code and splits the baseline cell into two sentences.Landing
Lands after #373 (plan PR 4), #375 (plan PR 6), #376 (plan PR 7) and #377 (plan PR 8), because each edits files this PR also edits:
docs/book/10-cli-reference.md: it inserts after :1451, and this PR edits :714 and :720. Disjoint.docs/book/02-architecture.md(:230, :522; here :382, :384),docs/book/10-cli-reference.md(:1070) anddocs/book/11-api-reference.md(:711 and below; here :376, :380). Disjoint.cli/cmd/mcp_caveats.go(it turns :105-106 into four lines and edits :117-118) anddocs/book/11-api-reference.md(:197). Disjoint. Line 171 here moves to 173.kates/src/main/java/com/bmscomp/kates/service/TestRunRepository.javaandcli/cmd/mcp_caveats.go:TestRunRepository.java: fix(engine): a status poll writes only over the status it read, so a cancelled run stays cancelled #377 inserts 3 lines after :40, edits :42 and :157-159, and deletes :59-80, 19 lines fewer in all. This PR edits :286-320. Disjoint.mcp_caveats.go:171. Both PRs re-point the samefindWithResultsref: fix(engine): a status poll writes only over the status it read, so a cancelled run stays cancelled #377 to335-355, this PR to360-380. Resolve it with fix(engine): a status poll writes only over the status it read, so a cancelled run stays cancelled #377's 335 plus the 6 lines this PR adds:TestRunRepository.java:341-361.Recipe once those have merged:
TestRunRepository.javafrom this branch's base to the merged file.cd cli && go test ./cmd -run TestMCPCaveat.Main has also gained #370 since this branch's base. It touches only
Makefileanddocs/kates-chaos-chart.md, so it does not overlap this PR.