Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions pipeline/runtime/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ func (r *Runtime) Run(runnerCtx context.Context) error {
return pipeline_errors.ErrCancel
case err := <-r.execAll(runnerCtx, stage.Steps):
if err != nil {
r.err = err
r.setErr(err)
}
}
}

return r.err
return r.getErr()
}

// Updates the current status of a step.
Expand All @@ -105,7 +105,7 @@ func (r *Runtime) traceStep(processState *backend.State, err error, step *backen
state := new(state.State)
state.Pipeline.Started = r.started
state.Pipeline.Step = step
state.Pipeline.Error = r.err
state.Pipeline.Error = r.getErr()

// We have an error while starting the step
if processState == nil && err != nil {
Expand Down Expand Up @@ -141,14 +141,14 @@ func (r *Runtime) execAll(runnerCtx context.Context, steps []*backend.Step) <-ch
Str("step", step.Name).
Msg("prepare")

switch {
case r.err != nil && !step.OnFailure:
switch rErr := r.getErr(); {
case rErr != nil && !step.OnFailure:
logger.Debug().
Str("step", step.Name).
Err(r.err).
Err(rErr).
Msgf("skipped due to OnFailure=%t", step.OnFailure)
return nil
case r.err == nil && !step.OnSuccess:
case rErr == nil && !step.OnSuccess:
logger.Debug().
Str("step", step.Name).
Msgf("skipped due to OnSuccess=%t", step.OnSuccess)
Expand Down
14 changes: 8 additions & 6 deletions pipeline/runtime/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,43 +22,45 @@ import (
"go.woodpecker-ci.org/woodpecker/v3/pipeline/tracing"
)

// Option configures a runtime option.
// Option configures a Runtime.
type Option func(*Runtime)

// WithBackend returns an option configured with a runtime engine.
// WithBackend sets the backend engine used to run steps.
func WithBackend(backend backend.Backend) Option {
return func(r *Runtime) {
r.engine = backend
}
}

// WithLogger returns an option configured with a runtime logger.
// WithLogger sets the function used to stream step logs.
func WithLogger(logger logging.Logger) Option {
return func(r *Runtime) {
r.logger = logger
}
}

// WithTracer returns an option configured with a runtime tracer.
// WithTracer sets the tracer used to report step state changes.
func WithTracer(tracer tracing.Tracer) Option {
return func(r *Runtime) {
r.tracer = tracer
}
}

// WithContext returns an option configured with a context.
// WithContext sets the workflow execution context.
func WithContext(ctx context.Context) Option {
return func(r *Runtime) {
r.ctx = ctx
}
}

// WithDescription sets the descriptive key-value pairs attached to every log line.
func WithDescription(desc map[string]string) Option {
return func(r *Runtime) {
r.Description = desc
r.description = desc
}
}

// WithTaskUUID sets a specific task UUID instead of the auto-generated one.
func WithTaskUUID(uuid string) Option {
return func(r *Runtime) {
r.taskUUID = uuid
Expand Down
44 changes: 30 additions & 14 deletions pipeline/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package runtime

import (
"context"
"sync"

"github.com/oklog/ulid/v2"
"github.com/rs/zerolog"
Expand All @@ -27,44 +28,59 @@ import (
)

// Runtime represents a workflow state executed by a specific backend.
// Each workflow gets its own state configuration at runtime.
// Each workflow gets its own Runtime instance.
type Runtime struct {
err error
// err holds the first error that occurred in the workflow.
// Always use getErr/setErr to access it — it is read and written from concurrent goroutines.
errMu sync.RWMutex
err error

spec *backend.Config
engine backend.Backend
started int64

// The context a workflow is being executed with.
// All normal (non cleanup) operations must use this.
// Cleanup operations should use the runnerCtx passed to Run()
// ctx is the context for the current workflow execution.
// All normal (non-cleanup) step operations must use this context.
// Cleanup operations should use the runnerCtx passed to Run().
ctx context.Context

tracer tracing.Tracer
logger logging.Logger

taskUUID string

Description map[string]string // The runtime descriptors.
taskUUID string
description map[string]string
}

// New returns a new runtime using the specified runtime
// configuration and runtime engine.
// New returns a new Runtime for the given workflow spec and options.
func New(spec *backend.Config, opts ...Option) *Runtime {
r := new(Runtime)
r.Description = map[string]string{}
r.description = map[string]string{}
r.spec = spec
r.ctx = context.Background()
r.taskUUID = ulid.Make().String()
for _, opts := range opts {
opts(r)
for _, opt := range opts {
opt(r)
}
return r
}

// MakeLogger returns a logger enriched with all runtime description fields.
func (r *Runtime) MakeLogger() zerolog.Logger {
logCtx := log.With()
for key, val := range r.Description {
for key, val := range r.description {
logCtx = logCtx.Str(key, val)
}
return logCtx.Logger()
}

func (r *Runtime) getErr() error {
Comment thread
6543 marked this conversation as resolved.
Outdated
r.errMu.RLock()
defer r.errMu.RUnlock()
return r.err
}

func (r *Runtime) setErr(err error) {
r.errMu.Lock()
defer r.errMu.Unlock()
r.err = err
}
3 changes: 3 additions & 0 deletions pipeline/runtime/shutdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ var (
shutdownCtxLock sync.Mutex
)

// GetShutdownCtx returns a context that is valid for shutdownTimeout after the
// first call. It is used as a fallback cleanup context when the runner context
// is already cancelled.
Comment thread
6543 marked this conversation as resolved.
Outdated
func GetShutdownCtx() context.Context {
shutdownCtxLock.Lock()
defer shutdownCtxLock.Unlock()
Expand Down