mirror of
https://gitea.com/gitea/act_runner.git
synced 2026-05-15 20:24:22 +02:00
feat: make pseudo-TTY allocation opt-in (#961)
Fixes #956. Pseudo-TTY allocation is now an explicit, runner-wide opt-in via `runner.allocate_pty`, applied to both host and docker backends. Default is off, matching GitHub `actions/runner`. ```yaml runner: allocate_pty: false # default ``` **Before:** the host backend hardcoded `if true /* allocate Terminal */` and the docker backend used `term.IsTerminal(os.Stdout.Fd())`. As a result, `docker build` (and other TTY-aware tools) saw a TTY and emitted cursor-control redraw frames that flooded captured logs with thousands of duplicate-looking progress lines — only on host-mode runners in production, and on docker-mode runners when the daemon happened to be launched from a shell rather than a service. **After:** both backends consult `Config.AllocatePTY`. The `term.IsTerminal` heuristic is gone, so behavior no longer depends on whether the daemon has a controlling terminal. **Reproduction:** running `docker build` through `HostEnvironment.Exec` with output captured to a buffer: | | Before (`if true`) | After (`AllocatePTY=false`) | |---|---:|---:| | bytes captured | 18,167 | 1,048 | | ANSI CSI sequences | 556 | 0 | | cursor-up `\e[1A` | 181 | 0 | **Side fix:** `ptyWriter.AutoStop` is now `atomic.Bool`. The field is written from the exec goroutine after `cmd.Wait()` and read from the `copyPtyOutput` goroutine via `ptyWriter.Write`; existing tests never tripped the race detector because their commands produced no output before exit. The new host-mode test does. --- This PR was written with the help of Claude Opus 4.7 --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: Nicolas <bircni@icloud.com> Reviewed-on: https://gitea.com/gitea/runner/pulls/961 Reviewed-by: Nicolas <bircni@icloud.com> Co-authored-by: silverwind <2021+silverwind@noreply.gitea.com> Co-committed-by: silverwind <2021+silverwind@noreply.gitea.com>
This commit is contained in:
@@ -41,7 +41,6 @@ import (
|
||||
"github.com/moby/moby/client"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/spf13/pflag"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
// NewContainer creates a reference to a container
|
||||
@@ -450,7 +449,6 @@ func (cr *containerReference) create(capAdd, capDrop []string) common.Executor {
|
||||
return nil
|
||||
}
|
||||
logger := common.Logger(ctx)
|
||||
isTerminal := term.IsTerminal(int(os.Stdout.Fd()))
|
||||
input := cr.input
|
||||
exposedPorts, err := convertPortSet(input.ExposedPorts)
|
||||
if err != nil {
|
||||
@@ -466,7 +464,7 @@ func (cr *containerReference) create(capAdd, capDrop []string) common.Executor {
|
||||
WorkingDir: input.WorkingDir,
|
||||
Env: input.Env,
|
||||
ExposedPorts: exposedPorts,
|
||||
Tty: isTerminal,
|
||||
Tty: input.AllocatePTY,
|
||||
}
|
||||
// For Gitea, reduce log noise
|
||||
// logger.Debugf("Common container.Config ==> %+v", config)
|
||||
@@ -604,7 +602,7 @@ func (cr *containerReference) exec(cmd []string, env map[string]string, user, wo
|
||||
}
|
||||
|
||||
logger.Debugf("Exec command '%s'", cmd)
|
||||
isTerminal := term.IsTerminal(int(os.Stdout.Fd()))
|
||||
isTerminal := cr.input.AllocatePTY
|
||||
envList := make([]string, 0)
|
||||
for k, v := range env {
|
||||
envList = append(envList, fmt.Sprintf("%s=%s", k, v))
|
||||
@@ -899,7 +897,7 @@ func (cr *containerReference) attach() common.Executor {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to attach to container: %w", err)
|
||||
}
|
||||
isTerminal := term.IsTerminal(int(os.Stdout.Fd()))
|
||||
isTerminal := cr.input.AllocatePTY
|
||||
|
||||
var outWriter io.Writer
|
||||
outWriter = cr.input.Stdout
|
||||
|
||||
Reference in New Issue
Block a user