Fix omitWriter.Write returning 0, aborting native-steps stream on stderr
Problem
With native steps on the Docker executor, Connect (executors/docker/steps.go:152) splits the attached docker exec stream with stdcopy.StdCopy: stdout goes into an io.Pipe that the step-runner client reads, and stderr goes into omitwriter.New().
omitWriter.Write (executors/docker/internal/omitwriter/omit_writer.go) declares a named result n and never assigns it, so it stores the bytes and returns 0, nil. stdcopy.StdCopy treats a write that reports fewer bytes than the frame as io.ErrShortWrite. So the first stderr frame from steps proxy stops the copy: the pipe is closed with short write: <stderr text>, and the stdout frames after it never reach the client.
Solution
Return len(p), nil from Write instead of the never-assigned named result n, per the io.Writer contract (all bytes of p are consumed). This mirrors the identical fix already merged for the same writer in fleeting (gitlab-org/fleeting/fleeting@ade46f38, fleeting!117).
Also strengthened Test_OmitWriter to assert Write returns exactly len(input), so the contract can't regress.
Testing
- Read the writer source and the
StdCopycall site insteps.goto confirm the short-write path. - Verified the change compiles logically: single-expression return replacing the never-assigned named result; the write loop is untouched.
- Extended the existing unit test (
Test_OmitWriter) to assertn == len(input)for every write; the pre-fix code returns 0 and fails this assertion, the fixed code passes it. - Go toolchain is not installed on this machine, so
go test ./executors/docker/internal/omitwriter/could not be executed here; relied on manual reasoning plus the issue's own analysis (fleeting's identical fix is already merged and working).
Closes #40100