Skip to content

feat(git): classify git command timeouts as infra errors#235

Open
yushan8 wants to merge 7 commits into
mainfrom
yushan/set-timeout
Open

feat(git): classify git command timeouts as infra errors#235
yushan8 wants to merge 7 commits into
mainfrom
yushan/set-timeout

Conversation

@yushan8

@yushan8 yushan8 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Intent:

  • Git commands (checkout, fetch, clone, diff, apply patch, commit,
    submodule update) already run under a fixed timeout, but a timeout
    failure was indistinguishable from any other git error or context.Cancelled error.

Changes:

  • Added a sentinel git.ErrTimeout and a wrapError helper in
    core/git that wraps a failing git operation's error with its name,
    and additionally wraps ErrTimeout when the failure was caused by the
    command's own timeout (as opposed to a parent context cancellation).
  • Added orchestrator.classifyGitError, used at the checkout,
    apply-requests, and treehash-compute call sites in
    native_orchestrator.go, which classifies the error as
    tangoerrors.NewInfra when it wraps git.ErrTimeout, per the
    classification conventions in docs/errors/errors.md.

Test Plan

unit test

Issues

yushan8 added 5 commits July 23, 2026 15:51
Summary:
Intent:
- Git commands (checkout, fetch, clone, diff, apply patch, commit,
  submodule update) already run under a fixed timeout, but a timeout
  failure was indistinguishable from any other git error, so it always
  surfaced as an unclassified error at the top-level orchestrator.

Changes:
- Added a sentinel `git.ErrTimeout` and a `wrapError` helper in
  `core/git` that wraps a failing git operation's error with its name,
  and additionally wraps ErrTimeout when the failure was caused by the
  command's own timeout (as opposed to a parent context cancellation).
- Added `orchestrator.classifyGitError`, used at the checkout,
  apply-requests, and treehash-compute call sites in
  `native_orchestrator.go`, which classifies the error as
  `tangoerrors.NewInfra` when it wraps `git.ErrTimeout`, per the
  classification conventions in `docs/errors/errors.md`.

---

<sub>Generated by the 🪄 [pr-create](https://sg.uberinternal.com/code.uber.internal/uber-code/devexp-agent-marketplace/-/blob/claude-code/plugins/dev/uber-dev/skills/pr-create/SKILL.md) skill in devexp-agent-marketplace</sub>
blockingRunner never actually needed to block — the derived timeout
context is already Done before the runner is invoked in these tests,
since the parent's deadline/cancellation already elapsed. Reuse the
existing mockRunner with a returnCtxErr flag instead of a second
runner type.
core/git already wraps failures with the operation name, so
classifyGitError only needs to classify, not wrap again.
@yushan8
yushan8 marked this pull request as ready for review July 23, 2026 23:44
@yushan8
yushan8 requested review from a team as code owners July 23, 2026 23:44
recordStep(e, "checkout_duration", checkoutStart)
if err != nil {
return nil, fmt.Errorf("checkout %s@%s: %w", build.Remote, build.BaseSha, err)
return nil, classifyGitError(err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it inevitable that we'd lose the checkout %s@%s prefix? Wondering if this info is still useful in the error.

Comment thread orchestrator/errors.go Outdated
// classifyGitError classifies err as an infra error when it was caused by a
// git command timing out.
func classifyGitError(err error) error {
if errors.Is(err, git.ErrTimeout) {

@xytan0056 xytan0056 Jul 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the error is "exit status 128", then it wouldn't be classified as NewInfra. It should be infra? The unwrapped error if not timeout, would be treated as infra by tangoerrors.GetErrorCode, becuase it just happens to be unclassfied.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea it should be NewInfra. I can classify them in this PR.

yushan8 added 2 commits July 23, 2026 20:07
…outs

Unconditionally wrap git-command failures with NewInfra instead of only
timeouts. context.Canceled is still correctly reported as ErrorCancelled
downstream since GetErrorCode checks for it ahead of the TangoError code,
and context.DeadlineExceeded correctly falls through to ErrorInfra.
wrapError now includes the failing command's actual arguments (e.g. the
ref/remote being acted on) instead of just the operation name, and wraps
ErrFatal when a command exits with a fatal (128) or usage (129) exit
code, as opposed to a non-fatal, conditional exit code such as 1.

classifyGitError explicitly classifies git.ErrTimeout and git.ErrFatal
as infra; other git failures are returned unclassified, falling
through to core/errors' default infra classification.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants