Skip to content

Add build timeout#1339

Merged
ije merged 4 commits into
mainfrom
build-timeout
Apr 1, 2026
Merged

Add build timeout#1339
ije merged 4 commits into
mainfrom
build-timeout

Conversation

@ije

@ije ije commented Mar 31, 2026

Copy link
Copy Markdown
Member
  • Introduced a new configuration option buildTimeout in config.example.jsonc to specify the maximum time allowed for a single build task, defaulting to 10 minutes.
  • Updated the BuildContext and related methods to support context cancellation, allowing for more robust handling of build operations.
  • Refactored various functions across the codebase to accept a context parameter, improving the ability to manage timeouts and cancellations during HTTP requests and package installations.
  • Enhanced error handling to provide clearer messages when build tasks exceed the specified timeout.

- Introduced a new configuration option `buildTimeout` in `config.example.jsonc` to specify the maximum time allowed for a single build task, defaulting to 10 minutes.
- Updated the `BuildContext` and related methods to support context cancellation, allowing for more robust handling of build operations.
- Refactored various functions across the codebase to accept a context parameter, improving the ability to manage timeouts and cancellations during HTTP requests and package installations.
- Enhanced error handling to provide clearer messages when build tasks exceed the specified timeout.
Copilot AI review requested due to automatic review settings March 31, 2026 14:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a configurable build-level timeout and threads context.Context through key build, fetch, and package-install paths so long-running builds can be canceled deterministically (e.g., on timeout).

Changes:

  • Added buildTimeout to server configuration (default 600s) and enforced it in the build queue via context.WithTimeout.
  • Extended BuildContext to carry a context and propagated it through npm metadata/tarball fetching, GitHub installs, loader execution, and supporting utilities.
  • Added context-aware HTTP fetching (FetchWithContext) and made supporting operations (sleep/backoff, downloads, extraction) cancellable.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
server/build_queue.go Applies per-build timeout and maps deadline exceeded into a clearer timeout error.
server/build.go Adds context to BuildContext and propagates cancellation checks throughout build stages.
server/build_resolver.go Propagates build context into dependency resolution and nested build contexts.
server/build_analyzer.go Ensures analyzer sub-builds inherit the parent build context.
server/npmrc.go Adds context-aware npm metadata fetch, tarball download/extract, GitHub install hook, and cancellable backoff.
server/git.go Adds context-aware GitHub ls-remote and GitHub tarball installation.
server/loader.go Runs Deno loader under a context-derived timeout rather than always using Background().
server/loader_implements.go Threads context through Svelte/Vue loader compilation and execution.
server/cjs_module_lexer.go Uses build context for subprocess timeouts and adds context-aware download/decompress for the lexer binary.
server/dts_transform.go Passes build context into nested type-build contexts.
internal/fetch/fetch.go Introduces FetchWithContext and makes Fetch delegate to it.
server/config.go Adds BuildTimeout config with default normalization.
config.example.jsonc Documents and provides an example value for buildTimeout.
Comments suppressed due to low confidence (1)

server/npmrc.go:645

  • gzip.NewReader returns a *gzip.Reader that should be closed to release resources and validate the gzip footer/CRC. Consider adding defer unziped.Close() after creation in extractPackageTarballContext.
	unziped, err := gzip.NewReader(&contextReader{ctx: ctx, reader: tarball})
	if err != nil {
		return
	}


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread server/npmrc.go
Comment on lines 474 to 477
mark.Add(markId)
installed, err := npmrc.installPackage(pkg)
installed, err := npmrc.installPackageContext(ctx, pkg)
if err != nil {
return

Copilot AI Mar 31, 2026

Copy link

Choose a reason for hiding this comment

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

installDependenciesContext now returns an error, but errors from dependency resolution/installation inside the goroutines are silently dropped (e.g. installPackageContext errors just return). This means callers may see nil even when dependency installs failed, which undermines the new error-handling path. Consider capturing the first non-context error from any goroutine (and optionally canceling the context) and returning it after wg.Wait().

Copilot uses AI. Check for mistakes.
Comment thread server/npmrc.go
Comment on lines 681 to +685
if err != nil {
return err
}
defer f.Close()
n, err := io.Copy(f, tr)
n, err := io.Copy(f, &contextReader{ctx: ctx, reader: tr})

Copilot AI Mar 31, 2026

Copy link

Choose a reason for hiding this comment

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

defer f.Close() is inside the tar extraction loop, so for large tarballs it can accumulate many open file descriptors until the function returns. Close the file explicitly after the copy (or use an inline func scope) to avoid FD exhaustion.

Copilot uses AI. Check for mistakes.
Comment thread server/build_queue.go

meta, err := task.ctx.Build(buildCtx)
if errors.Is(err, context.DeadlineExceeded) {
err = fmt.Errorf("build timeout after %d seconds", buildTimeout/time.Second)

Copilot AI Mar 31, 2026

Copy link

Choose a reason for hiding this comment

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

The timeout handling replaces context.DeadlineExceeded with a new error string, which loses the original cause and prevents downstream errors.Is(err, context.DeadlineExceeded) checks. Consider wrapping the original error (e.g. include %w) or using a typed error so the timeout remains programmatically detectable while still improving the message.

Suggested change
err = fmt.Errorf("build timeout after %d seconds", buildTimeout/time.Second)
err = fmt.Errorf("build timeout after %d seconds: %w", buildTimeout/time.Second, err)

Copilot uses AI. Check for mistakes.
@ije ije merged commit ed1319d into main Apr 1, 2026
5 checks passed
@ije ije deleted the build-timeout branch April 1, 2026 04:28
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