File size: 5,038 Bytes
d61821a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | diff --git a/common/build.go b/common/build.go
index ef5dda01..73e7972e 100644
--- a/common/build.go
+++ b/common/build.go
@@ -656,11 +656,8 @@ func (b *Build) executeStage(ctx context.Context, buildStage BuildStage, executo
// rather than the returned error because gRPC wraps deadline
// exceeded as a status error that does not unwrap to
// context.DeadlineExceeded.
- if err != nil && errors.Is(ctx.Err(), context.DeadlineExceeded) {
- b.logger.Warningln(
- string(buildStage) + " could not run to completion because the timeout was exceeded. " +
- "For more control over job and script timeouts see: " +
- "https://docs.gitlab.com/ci/runners/configure_runners/#set-script-and-after_script-timeouts")
+ if err != nil {
+ b.warnTimeoutExceeded(ctx, string(buildStage))
}
return err
}
@@ -676,14 +673,7 @@ func (b *Build) executeStage(ctx context.Context, buildStage BuildStage, executo
b.setCurrentStage(buildStage)
b.Log().WithField("build_stage", buildStage).Debug("Executing build stage")
- defer func() {
- if errors.Is(ctx.Err(), context.DeadlineExceeded) {
- b.logger.Warningln(
- string(buildStage) + " could not run to completion because the timeout was exceeded. " +
- "For more control over job and script timeouts see: " +
- "https://docs.gitlab.com/ci/runners/configure_runners/#set-script-and-after_script-timeouts")
- }
- }()
+ defer b.warnTimeoutExceeded(ctx, string(buildStage))
shell := executor.Shell()
if shell == nil {
@@ -828,6 +818,12 @@ func (b *Build) executeScript(ctx context.Context, trace JobTrace, executor Exec
//nolint:errcheck
err = b.executeStepStage(ctx, executor.(steps.Connector), "concrete", concreteSteps, trace.SetCancelFunc)
+ // Whole-job dispatch: stage breakdown isn't visible to the user, so
+ // attribute the timeout to "Job" rather than a build stage.
+ if err != nil {
+ b.warnTimeoutExceeded(ctx, "Job")
+ }
+
b.executeUploadReferees(ctx, startTime, time.Now())
return err
@@ -1092,6 +1088,16 @@ func (b *Build) attemptExecuteStage(
return err
}
+func (b *Build) warnTimeoutExceeded(ctx context.Context, subject string) {
+ if !errors.Is(ctx.Err(), context.DeadlineExceeded) {
+ return
+ }
+ b.logger.Warningln(
+ subject + " could not run to completion because the timeout was exceeded. " +
+ "For more control over job and script timeouts see: " +
+ "https://docs.gitlab.com/ci/runners/configure_runners/#set-script-and-after_script-timeouts")
+}
+
func (b *Build) GetBuildTimeout() time.Duration {
buildTimeout := b.RunnerInfo.Timeout
if buildTimeout <= 0 {
diff --git a/functions/concrete/builder/builder.go b/functions/concrete/builder/builder.go
index 310ae0fd..30fba029 100644
--- a/functions/concrete/builder/builder.go
+++ b/functions/concrete/builder/builder.go
@@ -353,7 +353,6 @@ func (b *builder) buildSteps() []stages.Step {
})
if step.Name == spec.StepNameAfterScript {
- s.AllowFailure = true
s.OnSuccess = true
s.OnFailure = true
afterScript = append(afterScript, s)
diff --git a/functions/concrete/run/runner.go b/functions/concrete/run/runner.go
index d17b3d62..cbfc5c64 100644
--- a/functions/concrete/run/runner.go
+++ b/functions/concrete/run/runner.go
@@ -224,17 +224,21 @@ func (r *Runner) runScriptSteps(jobCtx context.Context, steps []stages.Step) err
r.setCancel(cancel)
var firstErr error
+ timeoutStage := "step_script"
for _, step := range steps {
r.loadGitlabEnv()
- if err := r.section(scriptCtx, "step_"+step.Step, step.Run); err != nil {
+ sectionName := "step_" + step.Step
+ if err := r.section(scriptCtx, sectionName, step.Run); err != nil {
if firstErr == nil {
firstErr = err
}
+ timeoutStage = sectionName
break
}
}
+ r.warnStageTimeout(jobCtx, scriptCtx, timeoutStage)
return r.classifyScriptContextError(jobCtx, scriptCtx, firstErr)
}
@@ -277,6 +281,7 @@ func (r *Runner) runAfterScriptSteps(jobCtx context.Context, steps []stages.Step
return nil
})
+ r.warnStageTimeout(jobCtx, afterCtx, "after_script")
return err
}
@@ -386,6 +391,21 @@ func (r *Runner) logWarningf(format string, args ...interface{}) {
fmt.Fprintf(r.env.Stderr, " %s\033[0m\n", msg)
}
+// warnStageTimeout fires only on a stage-only deadline; the job-level
+// case is owned by the outer runner.
+func (r *Runner) warnStageTimeout(jobCtx, stageCtx context.Context, stageName string) {
+ if !errors.Is(stageCtx.Err(), context.DeadlineExceeded) {
+ return
+ }
+ if errors.Is(jobCtx.Err(), context.DeadlineExceeded) {
+ return
+ }
+ r.logWarningf("%s could not run to completion because the timeout was exceeded. "+
+ "For more control over job and script timeouts see: "+
+ "https://docs.gitlab.com/ci/runners/configure_runners/#set-script-and-after_script-timeouts",
+ stageName)
+}
+
// setupGitlabEnv creates the GITLAB_ENV file so user scripts can append
// KEY=VALUE lines to define dynamic variables for subsequent steps.
func (r *Runner) setupGitlabEnv() error {
|