Skip to content

Commit 3e2e854

Browse files
iapershinalexey-igrychev
authored andcommitted
fix(server): fix artifact export and build commands leak
Signed-off-by: Yaroslav Pershin <62902094+iapershin@users.noreply.github.com>
1 parent 5bb4fc5 commit 3e2e854

File tree

4 files changed

+49
-19
lines changed

4 files changed

+49
-19
lines changed

e2e/tests/flow/_fixtures/complete_cycle/trdl.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
dockerImage: alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a
22
commands:
3-
- '[ "$(cat /run/secrets/secretId0)" = "secretData" ] || (echo "Env does not match the expected value" && exit 1)'
3+
- '[ "$(cat /run/secrets/secretId0-test)" = "secretData" ] || (echo "output does not match the expected value" && exit 1)'
4+
- '[ "$(cat /run/secrets/secretId1-test)" = "secretData" ] || (echo "output does not match the expected value" && exit 1)'
45
- mkdir -p /result/any-any/bin
56
- printf "echo {{ .Tag }}\n" > /result/any-any/bin/script.sh
67
- mkdir -p /result/windows-any/bin

e2e/tests/flow/complete_cycle_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ var _ = Describe("Complete cycle", func() {
225225
req.Path = "configure/build/secrets"
226226
req.Operation = logical.CreateOperation
227227
req.Data = map[string]interface{}{
228-
"id": fmt.Sprintf("secretId%d", i),
228+
"id": fmt.Sprintf("secretId%d-test", i),
229229
"data": "secretData",
230230
}
231231
_, err = backend.HandleRequest(context.Background(), req)

server/pkg/docker/build.go

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"io"
1010
"os/exec"
1111
"path"
12-
"strings"
12+
"regexp"
1313

1414
"github.com/djherbis/buffer"
1515
"github.com/djherbis/nio/v3"
@@ -91,7 +91,7 @@ func BuildReleaseArtifacts(ctx context.Context, opts BuildReleaseArtifactsOpts,
9191
return fmt.Errorf("unable to set cli args: %w", err), nil
9292
}
9393

94-
if err := RunCliBuild(contextReader, opts.TarWriter, args...); err != nil {
94+
if err := RunCliBuild(ctx, contextReader, opts.TarWriter, args...); err != nil {
9595
return fmt.Errorf("can't build artifacts: %w", err), nil
9696
}
9797

@@ -106,9 +106,9 @@ func BuildReleaseArtifacts(ctx context.Context, opts BuildReleaseArtifactsOpts,
106106
return nil, cleanupFunc
107107
}
108108

109-
func RunCliBuild(contextReader *nio.PipeReader, tarWriter *nio.PipeWriter, args ...string) error {
109+
func RunCliBuild(ctx context.Context, contextReader *nio.PipeReader, tarWriter *nio.PipeWriter, args ...string) error {
110110
finalArgs := append([]string{"buildx", "build"}, args...)
111-
cmd := exec.Command("docker", finalArgs...)
111+
cmd := exec.CommandContext(ctx, "docker", finalArgs...)
112112
cmd.Stdout = tarWriter
113113
cmd.Stdin = contextReader
114114

@@ -121,31 +121,54 @@ func RunCliBuild(contextReader *nio.PipeReader, tarWriter *nio.PipeWriter, args
121121
return fmt.Errorf("error starting command: %w", err)
122122
}
123123

124-
var stderr bytes.Buffer
125-
io.Copy(&stderr, stderrPipe)
124+
errSection, scanErr := extractRelevantLogs(stderrPipe)
125+
if scanErr != nil {
126+
return scanErr
127+
}
126128

127129
if err := cmd.Wait(); err != nil {
128-
var errMsg string
129-
if stderr.Len() > 0 {
130-
errMsg = extractErrorMessage(stderr.String())
130+
if errSection.Len() == 0 {
131+
return fmt.Errorf("build failed with error(s):\n%s\n%w", errSection.String(), err)
131132
}
132-
return fmt.Errorf("error executing command: %s %w", errMsg, err)
133+
return fmt.Errorf("build failed:\n%s\n%w", errSection.String(), err)
133134
}
134135

135136
return nil
136137
}
137138

138-
func extractErrorMessage(stderr string) string {
139-
scanner := bufio.NewScanner(strings.NewReader(stderr))
140-
var errors []string
139+
// this needs for parsing buildx logs due to the fact that buildx writes all to stderr
140+
// it will look for the first error section of the logs that contains the error
141+
// or if not found just lines starts with "error:" or "ERROR:"
142+
func extractRelevantLogs(stderr io.ReadCloser) (bytes.Buffer, error) {
143+
scanner := bufio.NewScanner(stderr)
144+
145+
var errSection bytes.Buffer
146+
var foundSection bool
147+
reSectionStart := regexp.MustCompile(`^------$`)
148+
reError := regexp.MustCompile(`(?i)^error:`)
141149

142150
for scanner.Scan() {
143151
line := scanner.Text()
144-
if strings.HasPrefix(line, "ERROR:") || strings.HasPrefix(line, "error:") {
145-
errors = append(errors, line)
152+
153+
if reSectionStart.MatchString(line) {
154+
if errSection.Len() > 0 {
155+
break
156+
}
157+
foundSection = true
146158
}
159+
160+
if foundSection {
161+
errSection.WriteString(line + "\n")
162+
} else if reError.MatchString(line) {
163+
errSection.WriteString(line + "\n")
164+
}
165+
}
166+
167+
if err := scanner.Err(); err != nil {
168+
return errSection, fmt.Errorf("error reading stderr: %w", err)
147169
}
148-
return strings.Join(errors, " ")
170+
171+
return errSection, nil
149172
}
150173

151174
func setCliArgs(serviceDockerfilePathInContext string, secrets []secrets.Secret) ([]string, error) {

server/pkg/docker/dockerfile.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ func generateDockerfile(fromImage string, runCommands []string, opts DockerfileO
5050
data = append(data, []byte(line+"\n")...)
5151
}
5252

53-
addLineFunc(fmt.Sprintf("FROM %s", fromImage))
53+
// we use stages to reduce the size of output data to stdout
54+
addLineFunc(fmt.Sprintf("FROM %s as builder", fromImage))
5455

5556
for labelName, labelVal := range opts.Labels {
5657
addLineFunc(fmt.Sprintf("LABEL %s=%q", labelName, labelVal))
@@ -76,5 +77,10 @@ func generateDockerfile(fromImage string, runCommands []string, opts DockerfileO
7677
}
7778
}
7879

80+
// since we need only the artifacts from the build stage
81+
// we use scratch as the final image containing ONLY artifacts
82+
addLineFunc("FROM scratch")
83+
addLineFunc(fmt.Sprintf("COPY --from=builder /%s /%s/", ContainerArtifactsDir, ContainerArtifactsDir))
84+
7985
return data
8086
}

0 commit comments

Comments
 (0)