Repository navigation
fix: keep only the tail of git's stderr in every git runner's error - #776
Conversation
The git runners outside gitread and the write path kept all of git's stderr and quoted it in their errors, which reach the log: githttp's runGitCtx, its for-each-ref stream, update-ref --stdin and the commit-graph write, jobs' runGitStdin, sync's runGitTo, the three lfsscan scan children and simtest's simGit. Each now writes git's stderr into gitlimit.TailBuffer (the last 64 KiB). update-ref --stdin used CombinedOutput for its error text: it prints nothing on stdout, so it now reads only stderr. Their command lines stay as they are: Each runner gets a test with a git that prints 1 MiB to stderr (each lfsscan child on its own). With the old code the errors were 1,048,606 to 1,048,629 bytes. deploy-production.md states the bound that #757 put on the method and path fields of the API's log lines (moved from #761, which #757 superseded). Change-Id: I32251053afd0f88122bfae3715c94486bc8dcd02 Signed-off-by: Thomas Kosiewski <tk@coder.com>
wcBlobSink kept all of git hash-object's stderr in a bytes.Buffer and finish() quoted it in its error, which the commit-pack handler logs. It now writes stderr into gitlimit.TailBuffer. TestWriteGitErrorsKeepStderrTail gets the sink: with the old buffer its error was 1,048,618 bytes. Change-Id: I32a66facd0bd0bf547a8bbfdad78689aa9c6e394 Signed-off-by: Thomas Kosiewski <tk@coder.com>
Change-Id: I857bd6d7ae9c39cc01b3671d77ba317dfda2e817 Signed-off-by: Thomas Kosiewski <tk@coder.com>
…err tail change Change-Id: I42a000fc02f487178ffc115c099fb987eb77e43f Signed-off-by: Thomas Kosiewski <tk@coder.com>
Change-Id: I40ff8ea02948b8dc6e75cfe1cb75d65e262bf90a Signed-off-by: Thomas Kosiewski <tk@coder.com>
… main Change-Id: Iade359fede2b7d4e21f9fb609d010f3696cb87b1 Signed-off-by: Thomas Kosiewski <tk@coder.com>
|
@codex review |
|
@codex security review |
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
quoted it in an error that reaches the repack log. It now keeps the tail in gitlimit.TailBuffer. verifyCommit kept all of git verify-commit's output in memory. The verifier's reason comes first, so it now keeps the head in gitlimit.HeadBuffer (the first 64 KiB) and names the count of dropped bytes. gitlimit.CombinedOutput has no caller left and goes. Change-Id: Ib945877dead7e2dc9526243c4980f038f558addf Signed-off-by: Thomas Kosiewski <tk@coder.com>
…g verify-commit's output Change-Id: I01b8acd8a9864862cc8b68accc4815e5ab79ccb9 Signed-off-by: Thomas Kosiewski <tk@coder.com>
|
@codex review |
|
@codex security review |
Change-Id: Ieb677c1826d164c3be3b6167f44dff07f936818c Signed-off-by: Thomas Kosiewski <tk@coder.com>
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
… main again Change-Id: I8388359579c3f2624bb7db4d8d1fb9b2d69ecf59 Signed-off-by: Thomas Kosiewski <tk@coder.com>
…at a character TailBuffer that kept everything passed them. One Write of 64 MiB did keep a 64 MiB backing array. Write now copies only the last 64 KiB of a large write. A cut can land inside a UTF-8 sequence, so String drops the continuation bytes at the start of a tail that was cut. Change-Id: Id69fe6e000505a4f9c67292bfaa0434c2b3b7208 Signed-off-by: Thomas Kosiewski <tk@coder.com>
|
@codex review |
|
@codex security review |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
Why
#759 bounded git's stderr in
gitread.Runand the write path's git helpers withgitlimit.TailBuffer, the last 64 KiB. The other git runners still kept all of git's stderr and quoted it in their errors, and those reach the log:runGitCtx, the for-each-ref stream (localRefSeq),update-ref --stdinand the commit-graph write.runGitStdin.runGitTo.ReachableLFSOIDs(rev-list,cat-file --batch-check,cat-file --batch).simGit, whose errors reach the test log.wcBlobSink(hash-object -w --stdin), whosefinisherror the commit-pack handler logs.A git that prints 1 MiB to stderr gave an error of about 1 MB in each.
What changes
gitlimit.TailBuffer. git prints its fatal message last.update-ref --stdinusedCombinedOutputfor its error text. It prints nothing on stdout, so it now reads only stderr, through refactor(gitlimit): hold a shared lease in every git child of a cache repository #768'sRunIn.streamShowIndex(git show-index) keeps its stderr ingitlimit.TailBuffertoo: its error reaches the repack job's log.verifyCommit(git verify-commit) kept all of the verifier's output in memory. The verifier prints its reason first, so it now keeps the head in the newgitlimit.HeadBuffer(the first 64 KiB), and the hook-errors log line names how many bytes it dropped. The pusher still gets the fixed reason.gitlimit.TailBufferheld a backing array as large as the largest single write (64 MiB for one Write of 64 MiB). It now copies only the last 64 KiB of a large write, so it holds about 128 KiB at most. A cut can land inside a UTF-8 sequence, so a tail that was cut now starts at the next character.gitlimit.CombinedOutputhas no caller left and is removed. refactor(gitlimit): hold a shared lease in every git child of a cache repository #768'sCombinedOutputInstays: its lease audit names it.applyPatch(diff-commit'sgit apply), as fix(gitlimit): keep only the tail of git's stderr in git errors #759 chose, because its status comes from every line of stderr. Its plain error (a cancelled request or a killed git) quotes only the last 64 KiB. Its status answer (wcApplyRejection: 409, 400 or 500) quotes the first 4096 bytes. The buffer grows with the patch, to about the patch's size or a little more: git apply prints a line per file or hunk that fails, and diff-commit caps each chunk at 4 MiB but not the whole patch. With git 2.55.0, a 1,735,560-byte patch of 20,000 files gave 848,890 bytes of stderr, and one failing one-hunk diff repeated 20,000 times (1,060,000 bytes) gave 1,120,000 bytes. A follow-up PR (fix(api): cap diff-commit's patch, and read git apply's stderr as it streams #778) caps the patch and reads the stderr as it streams.runGitCtx,localRefSeqandupdateRefStdin, the hook'sverifyCommit, and sync'srunGitTo, and their imports, are covered by the verify-lane-schedule fingerprints, so this PR re-records them and moves the SKILL.md sync commit. The model does not change.docs/how-to/deploy-production.mdstates the bound that fix(api): clip long client values in git error names and log lines #757 put on themethodandpathfields of the API's log lines. The sentence moved here from fix(api): cap the request path and method in log records #761, which fix(api): clip long client values in git error names and log lines #757 superseded.Verification
Each runner gets a test with a git that prints 1 MiB and then
fatal: the endto stderr (each lfsscan child on its own, through a git that fails only that child). With the old code (go test -overlay):TestVerifyCommitKeepsTheHeadOfItsOutputuses a git that writesgpg: the reasonand then 64 MiB. Against main'sTailBuffer:A
TailBufferthat keeps everything and cuts only inString()fails the first of them, and one without the character rule fails the second.Each lfsscan child with a plain buffer fails its own case: 1,048,615 bytes for rev-list, 1,048,629 for
--batch-checkand 1,048,623 for--batch. The lfsscan test passed 20 of 20 runs with-race.Lanes at b40b177, each test lane under the host's shared heavy-validation lock:
go build ./...,go vet ./..., golangci-lint (0 issues) andscripts/check-doc-links.py(0 broken links): pass.go test -raceofinternal/api,internal/gitlimit,internal/jobs,internal/lfsscan,internal/simtest,internal/syncandcmd/openstorage, and ofinternal/githttpon its own, on PostgreSQL, local and S3-WAL: ok.internal/synctests at setup, for examplelocal_schedule_test.go:921: heldport: listen 127.0.0.1:0: listen tcp4 127.0.0.1:0: bind: address already in use: the host had run out of local ports (11,621 sockets in TIME_WAIT just after it ended). The third one passed.Round 2 and 3 heads, each test lane under the heavy-validation lock: after the merge of main at f3fc471 (#768),
check.sh --record(TLC,RESULT: PASS), both--fingerprints-onlychecks, build, vet, golangci-lint (0 issues) and the link check pass on 2f32d8e, and so dogo test -raceofinternal/gitlimit/...and the touched tests ofinternal/jobsandinternal/githttp(StderrTail|VerifyCommit|VerifySig|Repack|ShowIndex) on PostgreSQL, SQLite and S3-WAL. On the round-3 head,internal/gitlimitpasses with-race, and the stderr tests of githttp, jobs, lfsscan and api pass on SQLite.After the merge of main at 536ab6a, at 5b5a29e:
check.sh --record(TLC,RESULT: PASS), the--fingerprints-onlycheck of verify-lane-schedule and verify-orphan-sweep, build, vet, lint and the link check pass. I did not run the test lanes again locally on this head. CI runs them.Size
490 changed lines: 122 of production Go, 338 of tests, 16 of docs (the gitlimit README included) and 14 of the verify-lane-schedule record.
Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:xhigh