Repository navigation
fix(report): keep a clean check clean under the issue channel, and deliver a long report - #598
Conversation
…liver a long report Two defects in the issue channels of private-report. A converged check reported drift and wrote. The marker label was declared for every target an issue channel reports on, so a repository that never held the label showed it as missing: a check answered drift and exit 1, and issue-on-failure then created the label and a report issue. The channel now reads the marker label before the target's work and declares it unless the answer is 404. A repository without the label plans nothing, and one that holds it keeps it, in check and in apply. A read that fails any other way declares the label, as every target did before, so an unread label is never deleted. An apply no longer creates the label on a healthy repository, and the issue channels cost one more GET per private target per run. A report over GitHub's 65536-character issue-body limit earned a 422 on every run. The issue channel now composes its report under that limit: lines that do not fit are left out, section detail kept ahead of the transcript that repeats it, and the body says how many lines were left out and marks each cut. The artifact channel still delivers the whole report. The e2e mock serves the marker read for a delivery target, and the fuzzer lets a raw target receive it, since the read precedes the parse.
File size check0 over a hard cap (fails), 6 warning(s).
Split the file, wrap the line, shorten or exempt the comment, or list the path in 5 managed file(s) skipped; repo-platform owns them. |
Member shape check1 finding(s).
Add the blank lines, make the comment one line directly above the item, comment every field or none, or list the path in 4 generated file(s) skipped. |
There was a problem hiding this comment.
🟡 Changes recommended
A long backtick run in a discarded transcript causes excessive fence-budget reservation, dropping section diagnostics that otherwise fit within the issue-body limit.
1 open issue
What changed in this PR
This PR updates private issue reporting so a missing marker label does not create false settings drift, and long reports can fit GitHub's issue-body limit.
Changes:
- Read the marker label before target processing and inject it only when present or the read fails.
- Limit issue reports with counted omissions, prioritizing section detail; artifact reports remain complete.
- Update regression tests, mock routes, fuzz allowances, and private-report documentation.
| File | Description |
|---|---|
test/report/issue-report.test.ts |
Tests marker-label reads and failure handling. |
test/report/delivery.test.ts |
Verifies long artifact reports remain complete. |
test/report/composer.test.ts |
Tests report limits, detail allocation, and omission counts. |
test/flows/multi.test.ts |
Covers clean targets, long-report delivery, and read-trace redaction. |
test/flows/deliver.test.ts |
Tests conditional marker injection and request ordering. |
test/e2e/scenarios/multi-report-issue-on-failure-healthy-quiet.yml |
Checks healthy behavior without a seeded marker label. |
test/e2e/mock/core-paths.ts |
Adds the marker-label read route. |
test/e2e/mock/chaos.ts |
Adds fault injection for marker-label reads. |
test/e2e/fuzz.ts |
Allows label reads before settings parsing. |
src/report/issue-report.ts |
Adds marker-label probing and the issue-body limit. |
src/report/delivery.ts |
Exposes marker decisions and limits issue reports. |
src/report/composer.ts |
Adds length budgeting and omission notices. |
src/flows/deliver.ts |
Awaits the marker decision before target work. |
docs/operate/private-repositories.md |
Documents report truncation and revised marker behavior. |
Review effort: Balanced
… the marker rule's remaining cells composeReport is again composeReport(input) for a library caller. The cut is composeReportWithin, which the library entry does not export and the issue channel calls with GitHub's limit, so no caller can ask for a limit below the report's fixed part. The cut's contract is stated as the code keeps it: detail and transcript lines never push the body past the limit, and the fixed part (the heading, the notice, the run table, each section's status, the marks) is never cut, so a limit below that part is not met. The composer test asserts both sides of that part instead of excusing one. The page states the marker rule as a table of the read's answer by mode, including what a failed read costs on a repository without the label (drift in check, a created label in apply), and no longer says that a healthy run only reads. The flow table covers all eight cells of that rule, and a new scenario applies and then checks a private target that holds the marker label without declaring it.

Before
After
issue-on-failureit no longer creates the marker label on a healthy private repository, unless the marker read fails.healthy-quietno longer seeds it.How
issue-report.tsand prints nothing.markdown-truncate,mdast-excerpt,remark-excerpt) and this repository, and none keeps whole lines per section or counts the fence.Proof
test/reportandtest/flows/{deliver,multi}.test.ts, and 10 of them fail onorigin/main.multi-report-issue-*scenarios pass, one of them new.FUZZ_SEED=20261111, 25 of 25 iterations ok.Technical details
origin/mainholding this PR's scenario file, then on this branch.bun capture-limit.ts /repo, the script below, on a copy oforigin/main, then on this branch.::debug::request lines and the runner's own PASS and FAIL lines.multi,deliver, anddeliverytest files on a copy oforigin/maingive 80 pass and 10 fail.composer.test.tscannot load onorigin/main, since it imports the cut.FUZZ_SEED=20261111 bun test/e2e/fuzz.ts --iterations 25, afterbun run build:schema.GET /repos/{owner}/{repo}/labels/{name}, one request per proven-private target, whether or not its settings declarelabels.withDeliveryasks the channel before each target's work, and the artifact channel answers no.driftand apply creates the label under "nothing to deliver", and the flow table pins both.multi-report-issue-on-failure-marker-keptapplies, then checks, a private target that holds the label without declaring it.origin/main: it fails only for the missing read, sincemaindeclares the marker for every target.DELETE /repos/e2e-owner/svc-kept/labels.issue-on-failure, since underissueevery run writes the report issue and the check could not show zero writes.composeReport(input)is as onmain, and the cut iscomposeReportWithin, whichsrc/index.tsdoes not export.GET <redacted> -> 404.test/report/delivery.test.tspins a 700-line report uploaded whole.test/e2e/mock/core-paths.tsserves the read for a delivery target, under the fault keycore.reportLabelRead.bug.withDeliveryinjection table routes and counts the read, and the ordered-events case gains it as the first request.multi-report-issue-on-failure-healthy-quietdeclared and seeded the marker label to stay clean, and now does neither.runUrl, and no action input.docs/operate/private-repositories.mdstates the marker rule as a table of the read's answer by mode, and drops the caveat that an apply creates the label on healthy repositories.issue: the label is still created on the first healthy run, by the delivery, since that channel always writes its report issue.openReportChannelreturns has one more method,declaresMarker. Nothing is renamed or removed, andcomposeReportis as onmain.src/report/{composer,delivery,issue-report}.ts,src/flows/deliver.ts,test/report/{composer,delivery,issue-report}.test.ts,test/flows/{deliver,multi}.test.ts,test/e2e/{fuzz.ts,mock/chaos.ts,mock/core-paths.ts}, the two scenarios, the page.