From 027939fa5750a181879b31af6ad52b875b6efb30 Mon Sep 17 00:00:00 2001 From: pat-s Date: Wed, 23 Oct 2024 09:50:35 +0200 Subject: [PATCH] add files --- agent/runner.go | 11 +++-- cli/exec/exec.go | 2 +- cmd/agent/core/agent.go | 13 ++--- cmd/agent/core/run.go | 5 +- cmd/agent/main.go | 5 +- pipeline/backend/docker/docker.go | 11 +++-- pipeline/backend/dummy/dummy.go | 11 +++-- pipeline/backend/dummy/dummy_test.go | 54 ++++++++++++--------- pipeline/backend/kubernetes/kubernetes.go | 25 +++++----- pipeline/backend/kubernetes/pod.go | 27 ++++++----- pipeline/backend/kubernetes/pod_test.go | 45 ++++++++--------- pipeline/backend/kubernetes/secrets.go | 17 ++++--- pipeline/backend/kubernetes/secrets_test.go | 9 +++- pipeline/backend/local/local.go | 11 +++-- pipeline/backend/types/backend.go | 11 +++-- pipeline/frontend/metadata/types.go | 17 ++++--- pipeline/pipeline.go | 23 ++++----- 17 files changed, 162 insertions(+), 135 deletions(-) diff --git a/agent/runner.go b/agent/runner.go index 27363aa6638..8403a8f120d 100644 --- a/agent/runner.go +++ b/agent/runner.go @@ -23,10 +23,11 @@ import ( "time" "github.com/rs/zerolog/log" - "google.golang.org/grpc/metadata" + grpc_metadata "google.golang.org/grpc/metadata" "go.woodpecker-ci.org/woodpecker/v2/pipeline" backend "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" "go.woodpecker-ci.org/woodpecker/v2/pipeline/rpc" "go.woodpecker-ci.org/woodpecker/v2/shared/constant" "go.woodpecker-ci.org/woodpecker/v2/shared/utils" @@ -50,11 +51,11 @@ func NewRunner(workEngine rpc.Peer, f rpc.Filter, h string, state *State, backen } } -func (r *Runner) Run(runnerCtx, shutdownCtx context.Context) error { //nolint:contextcheck +func (r *Runner) Run(runnerCtx, shutdownCtx context.Context, metadata *metadata.Metadata) error { //nolint:contextcheck log.Debug().Msg("request next execution") - meta, _ := metadata.FromOutgoingContext(runnerCtx) - ctxMeta := metadata.NewOutgoingContext(context.Background(), meta) + meta, _ := grpc_metadata.FromOutgoingContext(runnerCtx) + ctxMeta := grpc_metadata.NewOutgoingContext(context.Background(), meta) // get the next workflow from the queue workflow, err := r.client.Next(runnerCtx, r.filter) @@ -150,7 +151,7 @@ func (r *Runner) Run(runnerCtx, shutdownCtx context.Context) error { //nolint:co "repo": repoName, "pipeline_number": pipelineNumber, }), - ).Run(runnerCtx) + ).Run(runnerCtx, metadata) state.Finished = time.Now().Unix() diff --git a/cli/exec/exec.go b/cli/exec/exec.go index afededad9ad..8e8861db958 100644 --- a/cli/exec/exec.go +++ b/cli/exec/exec.go @@ -282,7 +282,7 @@ func execWithAxis(ctx context.Context, c *cli.Command, file, repoPath string, ax pipeline.WithDescription(map[string]string{ "CLI": "exec", }), - ).Run(ctx) + ).Run(ctx, metadata) } // convertPathForWindows converts a path to use slash separators diff --git a/cmd/agent/core/agent.go b/cmd/agent/core/agent.go index cba6249b10d..b9b375bcef2 100644 --- a/cmd/agent/core/agent.go +++ b/cmd/agent/core/agent.go @@ -35,13 +35,14 @@ import ( grpc_credentials "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/keepalive" - "google.golang.org/grpc/metadata" + grpc_metadata "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "go.woodpecker-ci.org/woodpecker/v2/agent" agent_rpc "go.woodpecker-ci.org/woodpecker/v2/agent/rpc" "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend" "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" "go.woodpecker-ci.org/woodpecker/v2/pipeline/rpc" "go.woodpecker-ci.org/woodpecker/v2/shared/logger" "go.woodpecker-ci.org/woodpecker/v2/shared/utils" @@ -63,7 +64,7 @@ var ( shutdownCtx = context.Background() ) -func run(ctx context.Context, c *cli.Command, backends []types.Backend) error { +func run(ctx context.Context, c *cli.Command, backends []types.Backend, metadata *metadata.Metadata) error { agentCtx, ctxCancel := context.WithCancelCause(ctx) stopAgentFunc = func(err error) { msg := "shutdown of whole agent" @@ -160,7 +161,7 @@ func run(ctx context.Context, c *cli.Command, backends []types.Backend) error { client := agent_rpc.NewGrpcClient(ctx, conn) agentConfigPersisted := atomic.Bool{} - grpcCtx := metadata.NewOutgoingContext(grpcClientCtx, metadata.Pairs("hostname", hostname)) + grpcCtx := grpc_metadata.NewOutgoingContext(grpcClientCtx, grpc_metadata.Pairs("hostname", hostname)) // check if grpc server version is compatible with agent grpcServerVersion, err := client.Version(grpcCtx) //nolint:contextcheck @@ -290,7 +291,7 @@ func run(ctx context.Context, c *cli.Command, backends []types.Backend) error { } log.Debug().Msg("polling new steps") - if err := runner.Run(agentCtx, shutdownCtx); err != nil { + if err := runner.Run(agentCtx, shutdownCtx, metadata); err != nil { log.Error().Err(err).Msg("runner done with error") return err } @@ -305,7 +306,7 @@ func run(ctx context.Context, c *cli.Command, backends []types.Backend) error { return serviceWaitingGroup.Wait() } -func runWithRetry(backendEngines []types.Backend) func(ctx context.Context, c *cli.Command) error { +func runWithRetry(backendEngines []types.Backend, metadata *metadata.Metadata) func(ctx context.Context, c *cli.Command) error { return func(ctx context.Context, c *cli.Command) error { if err := logger.SetupGlobalLogger(ctx, c, true); err != nil { return err @@ -317,7 +318,7 @@ func runWithRetry(backendEngines []types.Backend) func(ctx context.Context, c *c retryDelay := c.Duration("connect-retry-delay") var err error for i := 0; i < retryCount; i++ { - if err = run(ctx, c, backendEngines); status.Code(err) == codes.Unavailable { + if err = run(ctx, c, backendEngines, metadata); status.Code(err) == codes.Unavailable { log.Warn().Err(err).Msg(fmt.Sprintf("cannot connect to server, retrying in %v", retryDelay)) time.Sleep(retryDelay) } else { diff --git a/cmd/agent/core/run.go b/cmd/agent/core/run.go index 3b01c2dc78a..65cb210c728 100644 --- a/cmd/agent/core/run.go +++ b/cmd/agent/core/run.go @@ -24,17 +24,18 @@ import ( "github.com/urfave/cli/v3" backend "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" "go.woodpecker-ci.org/woodpecker/v2/shared/logger" "go.woodpecker-ci.org/woodpecker/v2/shared/utils" "go.woodpecker-ci.org/woodpecker/v2/version" ) -func RunAgent(ctx context.Context, backends []backend.Backend) { +func RunAgent(ctx context.Context, backends []backend.Backend, metadata *metadata.Metadata) { app := &cli.Command{} app.Name = "woodpecker-agent" app.Version = version.String() app.Usage = "woodpecker agent" - app.Action = runWithRetry(backends) + app.Action = runWithRetry(backends, metadata) app.Commands = []*cli.Command{ { Name: "ping", diff --git a/cmd/agent/main.go b/cmd/agent/main.go index 37316195e94..8ea1081fb82 100644 --- a/cmd/agent/main.go +++ b/cmd/agent/main.go @@ -24,6 +24,7 @@ import ( "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/kubernetes" "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/local" backendTypes "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" "go.woodpecker-ci.org/woodpecker/v2/shared/utils" ) @@ -33,9 +34,11 @@ var backends = []backendTypes.Backend{ local.New(), } +var metadataList = &metadata.Metadata{} + func main() { ctx := utils.WithContextSigtermCallback(context.Background(), func() { log.Info().Msg("termination signal is received, shutting down agent") }) - core.RunAgent(ctx, backends) + core.RunAgent(ctx, backends, metadataList) } diff --git a/pipeline/backend/docker/docker.go b/pipeline/backend/docker/docker.go index bc92b56a3a9..2c77e20ac24 100644 --- a/pipeline/backend/docker/docker.go +++ b/pipeline/backend/docker/docker.go @@ -36,6 +36,7 @@ import ( "github.com/urfave/cli/v3" backend "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" "go.woodpecker-ci.org/woodpecker/v2/shared/utils" ) @@ -169,7 +170,7 @@ func (e *docker) SetupWorkflow(ctx context.Context, conf *backend.Config, taskUU return nil } -func (e *docker) StartStep(ctx context.Context, step *backend.Step, taskUUID string) error { +func (e *docker) StartStep(ctx context.Context, step *backend.Step, taskUUID string, metadata *metadata.Metadata) error { log.Trace().Str("taskUUID", taskUUID).Msgf("start step %s", step.Name) config := e.toConfig(step) @@ -247,7 +248,7 @@ func (e *docker) StartStep(ctx context.Context, step *backend.Step, taskUUID str return e.client.ContainerStart(ctx, containerName, container.StartOptions{}) } -func (e *docker) WaitStep(ctx context.Context, step *backend.Step, taskUUID string) (*backend.State, error) { +func (e *docker) WaitStep(ctx context.Context, step *backend.Step, taskUUID string, metadata *metadata.Metadata) (*backend.State, error) { log.Trace().Str("taskUUID", taskUUID).Msgf("wait for step %s", step.Name) containerName := toContainerName(step) @@ -270,7 +271,7 @@ func (e *docker) WaitStep(ctx context.Context, step *backend.Step, taskUUID stri }, nil } -func (e *docker) TailStep(ctx context.Context, step *backend.Step, taskUUID string) (io.ReadCloser, error) { +func (e *docker) TailStep(ctx context.Context, step *backend.Step, taskUUID string, metadata *metadata.Metadata) (io.ReadCloser, error) { log.Trace().Str("taskUUID", taskUUID).Msgf("tail logs of step %s", step.Name) logs, err := e.client.ContainerLogs(ctx, toContainerName(step), container.LogsOptions{ @@ -294,7 +295,7 @@ func (e *docker) TailStep(ctx context.Context, step *backend.Step, taskUUID stri return rc, nil } -func (e *docker) DestroyStep(ctx context.Context, step *backend.Step, taskUUID string) error { +func (e *docker) DestroyStep(ctx context.Context, step *backend.Step, taskUUID string, metadata *metadata.Metadata) error { log.Trace().Str("taskUUID", taskUUID).Msgf("stop step %s", step.Name) containerName := toContainerName(step) @@ -310,7 +311,7 @@ func (e *docker) DestroyStep(ctx context.Context, step *backend.Step, taskUUID s return nil } -func (e *docker) DestroyWorkflow(ctx context.Context, conf *backend.Config, taskUUID string) error { +func (e *docker) DestroyWorkflow(ctx context.Context, conf *backend.Config, taskUUID string, metadata *metadata.Metadata) error { log.Trace().Str("taskUUID", taskUUID).Msgf("delete workflow environment") for _, stage := range conf.Stages { diff --git a/pipeline/backend/dummy/dummy.go b/pipeline/backend/dummy/dummy.go index cdf08c8aa62..d90bb359fcb 100644 --- a/pipeline/backend/dummy/dummy.go +++ b/pipeline/backend/dummy/dummy.go @@ -30,6 +30,7 @@ import ( "github.com/urfave/cli/v3" backend "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" ) type dummy struct { @@ -87,7 +88,7 @@ func (e *dummy) SetupWorkflow(_ context.Context, _ *backend.Config, taskUUID str return nil } -func (e *dummy) StartStep(_ context.Context, step *backend.Step, taskUUID string) error { +func (e *dummy) StartStep(_ context.Context, step *backend.Step, taskUUID string, metadata *metadata.Metadata) error { log.Trace().Str("taskUUID", taskUUID).Msgf("start step %s", step.Name) // internal state checks @@ -114,7 +115,7 @@ func (e *dummy) StartStep(_ context.Context, step *backend.Step, taskUUID string return nil } -func (e *dummy) WaitStep(ctx context.Context, step *backend.Step, taskUUID string) (*backend.State, error) { +func (e *dummy) WaitStep(ctx context.Context, step *backend.Step, taskUUID string, metadata *metadata.Metadata) (*backend.State, error) { log.Trace().Str("taskUUID", taskUUID).Msgf("wait for step %s", step.Name) _, exist := e.kv.Load("task_" + taskUUID) @@ -172,7 +173,7 @@ func (e *dummy) WaitStep(ctx context.Context, step *backend.Step, taskUUID strin }, nil } -func (e *dummy) TailStep(_ context.Context, step *backend.Step, taskUUID string) (io.ReadCloser, error) { +func (e *dummy) TailStep(_ context.Context, step *backend.Step, taskUUID string, metadata *metadata.Metadata) (io.ReadCloser, error) { log.Trace().Str("taskUUID", taskUUID).Msgf("tail logs of step %s", step.Name) _, exist := e.kv.Load("task_" + taskUUID) @@ -196,7 +197,7 @@ func (e *dummy) TailStep(_ context.Context, step *backend.Step, taskUUID string) return io.NopCloser(strings.NewReader(dummyExecStepOutput(step))), nil } -func (e *dummy) DestroyStep(_ context.Context, step *backend.Step, taskUUID string) error { +func (e *dummy) DestroyStep(_ context.Context, step *backend.Step, taskUUID string, metadata *metadata.Metadata) error { log.Trace().Str("taskUUID", taskUUID).Msgf("stop step %s", step.Name) _, exist := e.kv.Load("task_" + taskUUID) @@ -217,7 +218,7 @@ func (e *dummy) DestroyStep(_ context.Context, step *backend.Step, taskUUID stri return nil } -func (e *dummy) DestroyWorkflow(_ context.Context, _ *backend.Config, taskUUID string) error { +func (e *dummy) DestroyWorkflow(_ context.Context, _ *backend.Config, taskUUID string, metadata *metadata.Metadata) error { log.Trace().Str("taskUUID", taskUUID).Msgf("delete workflow environment") _, exist := e.kv.Load("task_" + taskUUID) diff --git a/pipeline/backend/dummy/dummy_test.go b/pipeline/backend/dummy/dummy_test.go index f0c3d85862c..64f40946c57 100644 --- a/pipeline/backend/dummy/dummy_test.go +++ b/pipeline/backend/dummy/dummy_test.go @@ -23,6 +23,7 @@ import ( "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/dummy" "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" ) func TestSmalPipelineDummyRun(t *testing.T) { @@ -39,17 +40,18 @@ func TestSmalPipelineDummyRun(t *testing.T) { t.Run("expect fail of step func with non setup workflow", func(t *testing.T) { step := &types.Step{Name: "step1", UUID: "SID_1"} nonExistWorkflowID := "WID_NONE" + metadata := &metadata.Metadata{} - err := dummyEngine.StartStep(ctx, step, nonExistWorkflowID) + err := dummyEngine.StartStep(ctx, step, nonExistWorkflowID, metadata) assert.Error(t, err) - _, err = dummyEngine.TailStep(ctx, step, nonExistWorkflowID) + _, err = dummyEngine.TailStep(ctx, step, nonExistWorkflowID, metadata) assert.Error(t, err) - _, err = dummyEngine.WaitStep(ctx, step, nonExistWorkflowID) + _, err = dummyEngine.WaitStep(ctx, step, nonExistWorkflowID, metadata) assert.Error(t, err) - err = dummyEngine.DestroyStep(ctx, step, nonExistWorkflowID) + err = dummyEngine.DestroyStep(ctx, step, nonExistWorkflowID, metadata) assert.Error(t, err) }) @@ -61,13 +63,14 @@ func TestSmalPipelineDummyRun(t *testing.T) { Environment: map[string]string{}, Commands: []string{"echo ja", "echo nein"}, } + metadata := &metadata.Metadata{} workflowUUID := "WID_1" assert.NoError(t, dummyEngine.SetupWorkflow(ctx, nil, workflowUUID)) - assert.NoError(t, dummyEngine.StartStep(ctx, step, workflowUUID)) + assert.NoError(t, dummyEngine.StartStep(ctx, step, workflowUUID, metadata)) - reader, err := dummyEngine.TailStep(ctx, step, workflowUUID) + reader, err := dummyEngine.TailStep(ctx, step, workflowUUID, metadata) assert.NoError(t, err) log, err := io.ReadAll(reader) assert.NoError(t, err) @@ -81,14 +84,14 @@ echo nein ------------------ `, string(log)) - state, err := dummyEngine.WaitStep(ctx, step, workflowUUID) + state, err := dummyEngine.WaitStep(ctx, step, workflowUUID, metadata) assert.NoError(t, err) assert.NoError(t, state.Error) assert.EqualValues(t, 0, state.ExitCode) - assert.NoError(t, dummyEngine.DestroyStep(ctx, step, workflowUUID)) + assert.NoError(t, dummyEngine.DestroyStep(ctx, step, workflowUUID, metadata)) - assert.NoError(t, dummyEngine.DestroyWorkflow(ctx, nil, workflowUUID)) + assert.NoError(t, dummyEngine.DestroyWorkflow(ctx, nil, workflowUUID, metadata)) }) t.Run("step exec error", func(t *testing.T) { @@ -98,23 +101,24 @@ echo nein Type: types.StepTypePlugin, Environment: map[string]string{dummy.EnvKeyStepType: "plugin", dummy.EnvKeyStepExitCode: "1"}, } + metadata := &metadata.Metadata{} workflowUUID := "WID_1" assert.NoError(t, dummyEngine.SetupWorkflow(ctx, nil, workflowUUID)) - assert.NoError(t, dummyEngine.StartStep(ctx, step, workflowUUID)) + assert.NoError(t, dummyEngine.StartStep(ctx, step, workflowUUID, metadata)) - _, err := dummyEngine.TailStep(ctx, step, workflowUUID) + _, err := dummyEngine.TailStep(ctx, step, workflowUUID, metadata) assert.NoError(t, err) - state, err := dummyEngine.WaitStep(ctx, step, workflowUUID) + state, err := dummyEngine.WaitStep(ctx, step, workflowUUID, metadata) assert.NoError(t, err) assert.NoError(t, state.Error) assert.EqualValues(t, 1, state.ExitCode) - assert.NoError(t, dummyEngine.DestroyStep(ctx, step, workflowUUID)) + assert.NoError(t, dummyEngine.DestroyStep(ctx, step, workflowUUID, metadata)) - assert.NoError(t, dummyEngine.DestroyWorkflow(ctx, nil, workflowUUID)) + assert.NoError(t, dummyEngine.DestroyWorkflow(ctx, nil, workflowUUID, metadata)) }) t.Run("step tail error", func(t *testing.T) { @@ -123,21 +127,22 @@ echo nein UUID: "SID_2", Environment: map[string]string{dummy.EnvKeyStepTailFail: "true"}, } + metadata := &metadata.Metadata{} workflowUUID := "WID_1" assert.NoError(t, dummyEngine.SetupWorkflow(ctx, nil, workflowUUID)) - assert.NoError(t, dummyEngine.StartStep(ctx, step, workflowUUID)) + assert.NoError(t, dummyEngine.StartStep(ctx, step, workflowUUID, metadata)) - _, err := dummyEngine.TailStep(ctx, step, workflowUUID) + _, err := dummyEngine.TailStep(ctx, step, workflowUUID, metadata) assert.Error(t, err) - _, err = dummyEngine.WaitStep(ctx, step, workflowUUID) + _, err = dummyEngine.WaitStep(ctx, step, workflowUUID, metadata) assert.NoError(t, err) - assert.NoError(t, dummyEngine.DestroyStep(ctx, step, workflowUUID)) + assert.NoError(t, dummyEngine.DestroyStep(ctx, step, workflowUUID, metadata)) - assert.NoError(t, dummyEngine.DestroyWorkflow(ctx, nil, workflowUUID)) + assert.NoError(t, dummyEngine.DestroyWorkflow(ctx, nil, workflowUUID, metadata)) }) t.Run("step start fail", func(t *testing.T) { @@ -147,22 +152,23 @@ echo nein Type: types.StepTypeService, Environment: map[string]string{dummy.EnvKeyStepType: "service", dummy.EnvKeyStepStartFail: "true"}, } + metadata := &metadata.Metadata{} workflowUUID := "WID_1" assert.NoError(t, dummyEngine.SetupWorkflow(ctx, nil, workflowUUID)) - assert.Error(t, dummyEngine.StartStep(ctx, step, workflowUUID)) + assert.Error(t, dummyEngine.StartStep(ctx, step, workflowUUID, metadata)) - _, err := dummyEngine.TailStep(ctx, step, workflowUUID) + _, err := dummyEngine.TailStep(ctx, step, workflowUUID, metadata) assert.Error(t, err) - state, err := dummyEngine.WaitStep(ctx, step, workflowUUID) + state, err := dummyEngine.WaitStep(ctx, step, workflowUUID, metadata) assert.Error(t, err) assert.Error(t, state.Error) assert.EqualValues(t, 0, state.ExitCode) - assert.Error(t, dummyEngine.DestroyStep(ctx, step, workflowUUID)) + assert.Error(t, dummyEngine.DestroyStep(ctx, step, workflowUUID, metadata)) - assert.NoError(t, dummyEngine.DestroyWorkflow(ctx, nil, workflowUUID)) + assert.NoError(t, dummyEngine.DestroyWorkflow(ctx, nil, workflowUUID, metadata)) }) } diff --git a/pipeline/backend/kubernetes/kubernetes.go b/pipeline/backend/kubernetes/kubernetes.go index 0e1a399f865..e9202212529 100644 --- a/pipeline/backend/kubernetes/kubernetes.go +++ b/pipeline/backend/kubernetes/kubernetes.go @@ -38,6 +38,7 @@ import ( "k8s.io/client-go/tools/cache" "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" ) const ( @@ -220,28 +221,28 @@ func (e *kube) SetupWorkflow(ctx context.Context, conf *types.Config, taskUUID s } // StartStep starts the pipeline step. -func (e *kube) StartStep(ctx context.Context, step *types.Step, taskUUID string) error { +func (e *kube) StartStep(ctx context.Context, step *types.Step, taskUUID string, metadata *metadata.Metadata) error { options, err := parseBackendOptions(step) if err != nil { log.Error().Err(err).Msg("could not parse backend options") } if needsRegistrySecret(step) { - err = startRegistrySecret(ctx, e, step) + err = startRegistrySecret(ctx, e, step, metadata) if err != nil { return err } } log.Trace().Str("taskUUID", taskUUID).Msgf("starting step: %s", step.Name) - _, err = startPod(ctx, e, step, options) + _, err = startPod(ctx, e, step, options, metadata) return err } // WaitStep waits for the pipeline step to complete and returns // the completion results. -func (e *kube) WaitStep(ctx context.Context, step *types.Step, taskUUID string) (*types.State, error) { - podName, err := stepToPodName(step) +func (e *kube) WaitStep(ctx context.Context, step *types.Step, taskUUID string, metadata *metadata.Metadata) (*types.State, error) { + podName, err := stepToPodName(step, metadata) if err != nil { return nil, err } @@ -316,8 +317,8 @@ func (e *kube) WaitStep(ctx context.Context, step *types.Step, taskUUID string) } // TailStep tails the pipeline step logs. -func (e *kube) TailStep(ctx context.Context, step *types.Step, taskUUID string) (io.ReadCloser, error) { - podName, err := stepToPodName(step) +func (e *kube) TailStep(ctx context.Context, step *types.Step, taskUUID string, metadata *metadata.Metadata) (io.ReadCloser, error) { + podName, err := stepToPodName(step, metadata) if err != nil { return nil, err } @@ -389,17 +390,17 @@ func (e *kube) TailStep(ctx context.Context, step *types.Step, taskUUID string) return rc, nil } -func (e *kube) DestroyStep(ctx context.Context, step *types.Step, taskUUID string) error { +func (e *kube) DestroyStep(ctx context.Context, step *types.Step, taskUUID string, metadata *metadata.Metadata) error { var errs []error log.Trace().Str("taskUUID", taskUUID).Msgf("Stopping step: %s", step.Name) if needsRegistrySecret(step) { - err := stopRegistrySecret(ctx, e, step, defaultDeleteOptions) + err := stopRegistrySecret(ctx, e, step, defaultDeleteOptions, metadata) if err != nil { errs = append(errs, err) } } - err := stopPod(ctx, e, step, defaultDeleteOptions) + err := stopPod(ctx, e, step, defaultDeleteOptions, metadata) if err != nil { errs = append(errs, err) } @@ -407,12 +408,12 @@ func (e *kube) DestroyStep(ctx context.Context, step *types.Step, taskUUID strin } // DestroyWorkflow destroys the pipeline environment. -func (e *kube) DestroyWorkflow(ctx context.Context, conf *types.Config, taskUUID string) error { +func (e *kube) DestroyWorkflow(ctx context.Context, conf *types.Config, taskUUID string, metadata *metadata.Metadata) error { log.Trace().Str("taskUUID", taskUUID).Msg("deleting Kubernetes primitives") for _, stage := range conf.Stages { for _, step := range stage.Steps { - err := stopPod(ctx, e, step, defaultDeleteOptions) + err := stopPod(ctx, e, step, defaultDeleteOptions, metadata) if err != nil { return err } diff --git a/pipeline/backend/kubernetes/pod.go b/pipeline/backend/kubernetes/pod.go index 50ae55dcd68..513632c81bf 100644 --- a/pipeline/backend/kubernetes/pod.go +++ b/pipeline/backend/kubernetes/pod.go @@ -28,6 +28,7 @@ import ( "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/common" "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" ) const ( @@ -35,7 +36,7 @@ const ( podPrefix = "wp-" ) -func mkPod(step *types.Step, config *config, podName, goos string, options BackendOptions) (*v1.Pod, error) { +func mkPod(step *types.Step, config *config, podName, goos string, options BackendOptions, metadata *metadata.Metadata) (*v1.Pod, error) { var err error nsp := newNativeSecretsProcessor(config, options.Secrets) @@ -49,7 +50,7 @@ func mkPod(step *types.Step, config *config, podName, goos string, options Backe return nil, err } - spec, err := podSpec(step, config, options, nsp) + spec, err := podSpec(step, config, options, nsp, metadata) if err != nil { return nil, err } @@ -68,15 +69,15 @@ func mkPod(step *types.Step, config *config, podName, goos string, options Backe return pod, nil } -func stepToPodName(step *types.Step) (name string, err error) { +func stepToPodName(step *types.Step, metadata *metadata.Metadata) (name string, err error) { if step.Type == types.StepTypeService { return serviceName(step) } - return podName(step) + return podName(step, metadata) } -func podName(step *types.Step) (string, error) { - return dnsName(podPrefix + step.UUID) +func podName(step *types.Step, metadata *metadata.Metadata) (string, error) { + return dnsName(strings.ReplaceAll(podPrefix+metadata.Repo.Owner+"-"+metadata.Repo.Name+"-"+metadata.Workflow.Name+"-"+step.Name+"-"+step.UUID[:5], "_", "-")) } func podMeta(step *types.Step, config *config, options BackendOptions, podName string) (meta_v1.ObjectMeta, error) { @@ -145,7 +146,7 @@ func podAnnotations(config *config, options BackendOptions) map[string]string { return annotations } -func podSpec(step *types.Step, config *config, options BackendOptions, nsp nativeSecretsProcessor) (v1.PodSpec, error) { +func podSpec(step *types.Step, config *config, options BackendOptions, nsp nativeSecretsProcessor, metadata *metadata.Metadata) (v1.PodSpec, error) { var err error spec := v1.PodSpec{ RestartPolicy: v1.RestartPolicyNever, @@ -165,7 +166,7 @@ func podSpec(step *types.Step, config *config, options BackendOptions, nsp nativ spec.ImagePullSecrets = secretsReferences(config.ImagePullSecretNames) if needsRegistrySecret(step) { log.Trace().Msgf("using an image pull secret from registries") - name, err := registrySecretName(step) + name, err := registrySecretName(step, metadata) if err != nil { return spec, err } @@ -502,13 +503,13 @@ func mapToEnvVars(m map[string]string) []v1.EnvVar { return ev } -func startPod(ctx context.Context, engine *kube, step *types.Step, options BackendOptions) (*v1.Pod, error) { - podName, err := stepToPodName(step) +func startPod(ctx context.Context, engine *kube, step *types.Step, options BackendOptions, metadata *metadata.Metadata) (*v1.Pod, error) { + podName, err := stepToPodName(step, metadata) if err != nil { return nil, err } engineConfig := engine.getConfig() - pod, err := mkPod(step, engineConfig, podName, engine.goos, options) + pod, err := mkPod(step, engineConfig, podName, engine.goos, options, metadata) if err != nil { return nil, err } @@ -517,8 +518,8 @@ func startPod(ctx context.Context, engine *kube, step *types.Step, options Backe return engine.client.CoreV1().Pods(engineConfig.Namespace).Create(ctx, pod, meta_v1.CreateOptions{}) } -func stopPod(ctx context.Context, engine *kube, step *types.Step, deleteOpts meta_v1.DeleteOptions) error { - podName, err := stepToPodName(step) +func stopPod(ctx context.Context, engine *kube, step *types.Step, deleteOpts meta_v1.DeleteOptions, metadata *metadata.Metadata) error { + podName, err := stepToPodName(step, metadata) if err != nil { return err } diff --git a/pipeline/backend/kubernetes/pod_test.go b/pipeline/backend/kubernetes/pod_test.go index 575b6047ad5..6afbc4f725b 100644 --- a/pipeline/backend/kubernetes/pod_test.go +++ b/pipeline/backend/kubernetes/pod_test.go @@ -23,34 +23,35 @@ import ( v1 "k8s.io/api/core/v1" "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" ) func TestPodName(t *testing.T) { - name, err := podName(&types.Step{UUID: "01he8bebctabr3kgk0qj36d2me-0"}) + name, err := podName(&types.Step{UUID: "01he8bebctabr3kgk0qj36d2me-0", Name: "stepName"}, &metadata.Metadata{Workflow: metadata.Workflow{Name: "my-workflow"}, Repo: metadata.Repo{Owner: "owner", Name: "repo_name"}}) assert.NoError(t, err) - assert.Equal(t, "wp-01he8bebctabr3kgk0qj36d2me-0", name) + assert.Equal(t, "wp-owner-repo-name-my-workflow-stepname-01he8", name) - _, err = podName(&types.Step{UUID: "01he8bebctabr3kgk0qj36d2me\\0a"}) + _, err = podName(&types.Step{UUID: "01he8bebctabr3kgk0qj36d2me\\0a", Name: ".."}, &metadata.Metadata{Workflow: metadata.Workflow{Name: "my-workflow"}, Repo: metadata.Repo{Owner: "owner", Name: "repo_name!"}}) assert.ErrorIs(t, err, ErrDNSPatternInvalid) - _, err = podName(&types.Step{UUID: "01he8bebctabr3kgk0qj36d2me-0-services-0..woodpecker-runtime.svc.cluster.local"}) + _, err = podName(&types.Step{UUID: "01he8bebctabr3kgk0qj36d2me-0-services-0..woodpecker-runtime.svc.cluster.local"}, &metadata.Metadata{Workflow: metadata.Workflow{Name: "my-workflow"}, Repo: metadata.Repo{Owner: "owner", Name: "repo_name.."}}) assert.ErrorIs(t, err, ErrDNSPatternInvalid) } func TestStepToPodName(t *testing.T) { - name, err := stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "clone", Type: types.StepTypeClone}) + name, err := stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "clone", Type: types.StepTypeClone}, &metadata.Metadata{Workflow: metadata.Workflow{Name: "my-workflow"}, Repo: metadata.Repo{Owner: "owner", Name: "repo_name"}}) assert.NoError(t, err) - assert.EqualValues(t, "wp-01he8bebctabr3kg", name) - name, err = stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "cache", Type: types.StepTypeCache}) + assert.EqualValues(t, "wp-owner-repo-name-my-workflow-clone-01he8", name) + name, err = stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "cache", Type: types.StepTypeCache}, &metadata.Metadata{Workflow: metadata.Workflow{Name: "my-workflow"}, Repo: metadata.Repo{Owner: "owner", Name: "repo_name"}}) assert.NoError(t, err) - assert.EqualValues(t, "wp-01he8bebctabr3kg", name) - name, err = stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "release", Type: types.StepTypePlugin}) + assert.EqualValues(t, "wp-owner-repo-name-my-workflow-cache-01he8", name) + name, err = stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "release", Type: types.StepTypePlugin}, &metadata.Metadata{Workflow: metadata.Workflow{Name: "my-workflow"}, Repo: metadata.Repo{Owner: "owner", Name: "repo_name"}}) assert.NoError(t, err) - assert.EqualValues(t, "wp-01he8bebctabr3kg", name) - name, err = stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "prepare-env", Type: types.StepTypeCommands}) + assert.EqualValues(t, "wp-owner-repo-name-my-workflow-release-01he8", name) + name, err = stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "prepare-env", Type: types.StepTypeCommands}, &metadata.Metadata{Workflow: metadata.Workflow{Name: "my-workflow"}, Repo: metadata.Repo{Owner: "owner", Name: "repo_name"}}) assert.NoError(t, err) - assert.EqualValues(t, "wp-01he8bebctabr3kg", name) - name, err = stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "postgres", Type: types.StepTypeService}) + assert.EqualValues(t, "wp-owner-repo-name-my-workflow-prepare-env-01he8", name) + name, err = stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "postgres", Type: types.StepTypeService}, &metadata.Metadata{Workflow: metadata.Workflow{Name: "workflow-postgres"}, Repo: metadata.Repo{Owner: "owner", Name: "repo_name"}}) assert.NoError(t, err) assert.EqualValues(t, "wp-svc-01he8bebctabr3kg-postgres", name) } @@ -138,7 +139,7 @@ func TestTinyPod(t *testing.T) { Environment: map[string]string{"CI": "woodpecker"}, }, &config{ Namespace: "woodpecker", - }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{}) + }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{}, &metadata.Metadata{Workflow: metadata.Workflow{Name: "my-workflow"}}) assert.NoError(t, err) podJSON, err := json.Marshal(pod) @@ -152,7 +153,7 @@ func TestFullPod(t *testing.T) { const expected = ` { "metadata": { - "name": "wp-01he8bebctabr3kgk0qj36d2me-0", + "name": "wp-owner-repo-name-my-workflow-go-test-01he8", "namespace": "woodpecker", "creationTimestamp": null, "labels": { @@ -176,7 +177,7 @@ func TestFullPod(t *testing.T) { ], "containers": [ { - "name": "wp-01he8bebctabr3kgk0qj36d2me-0", + "name": "wp-owner-repo-name-my-workflow-go-test-01he8", "image": "meltwater/drone-cache", "command": [ "/bin/sh", @@ -266,7 +267,7 @@ func TestFullPod(t *testing.T) { "name": "another-pull-secret" }, { - "name": "wp-01he8bebctabr3kgk0qj36d2me-0" + "name": "wp-owner-repo-name-my-workflow-go-test-01he8" } ], "tolerations": [ @@ -345,7 +346,7 @@ func TestFullPod(t *testing.T) { PodAnnotationsAllowFromStep: true, PodNodeSelector: map[string]string{"topology.kubernetes.io/region": "eu-central-1"}, SecurityContext: SecurityContextConfig{RunAsNonRoot: false}, - }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{ + }, "wp-owner-repo-name-my-workflow-go-test-01he8", "linux/amd64", BackendOptions{ Labels: map[string]string{"part-of": "woodpecker-ci"}, Annotations: map[string]string{"kubernetes.io/limit-ranger": "LimitRanger plugin set: cpu, memory request and limit for container"}, NodeSelector: map[string]string{"storage": "ssd"}, @@ -357,7 +358,7 @@ func TestFullPod(t *testing.T) { Limits: map[string]string{"memory": "256Mi", "cpu": "2"}, }, SecurityContext: &secCtx, - }) + }, &metadata.Metadata{Workflow: metadata.Workflow{Name: "my-workflow"}, Repo: metadata.Repo{Owner: "owner", Name: "repo_name"}}) assert.NoError(t, err) podJSON, err := json.Marshal(pod) @@ -378,7 +379,7 @@ func TestPodPrivilege(t *testing.T) { SecurityContext: SecurityContextConfig{RunAsNonRoot: globalRunAsRoot}, }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{ SecurityContext: &secCtx, - }) + }, &metadata.Metadata{Workflow: metadata.Workflow{Name: "my-workflow"}}) } // securty context is requesting user and group 101 (non-root) @@ -471,7 +472,7 @@ func TestScratchPod(t *testing.T) { Entrypoint: []string{"/usr/bin/curl", "-v", "google.com"}, }, &config{ Namespace: "woodpecker", - }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{}) + }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{}, &metadata.Metadata{Workflow: metadata.Workflow{Name: "my-workflow"}}) assert.NoError(t, err) podJSON, err := json.Marshal(pod) @@ -590,7 +591,7 @@ func TestSecrets(t *testing.T) { Target: SecretTarget{File: "~/.docker/config.json"}, }, }, - }) + }, &metadata.Metadata{Workflow: metadata.Workflow{Name: "my-workflow"}}) assert.NoError(t, err) podJSON, err := json.Marshal(pod) diff --git a/pipeline/backend/kubernetes/secrets.go b/pipeline/backend/kubernetes/secrets.go index 96ef8459317..dd8e0f940df 100644 --- a/pipeline/backend/kubernetes/secrets.go +++ b/pipeline/backend/kubernetes/secrets.go @@ -29,6 +29,7 @@ import ( meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/yaml/utils" ) @@ -204,8 +205,8 @@ func needsRegistrySecret(step *types.Step) bool { return step.AuthConfig.Username != "" && step.AuthConfig.Password != "" } -func mkRegistrySecret(step *types.Step, config *config) (*v1.Secret, error) { - name, err := registrySecretName(step) +func mkRegistrySecret(step *types.Step, config *config, metadata *metadata.Metadata) (*v1.Secret, error) { + name, err := registrySecretName(step, metadata) if err != nil { return nil, err } @@ -247,8 +248,8 @@ func mkRegistrySecret(step *types.Step, config *config) (*v1.Secret, error) { }, nil } -func registrySecretName(step *types.Step) (string, error) { - return podName(step) +func registrySecretName(step *types.Step, metadata *metadata.Metadata) (string, error) { + return podName(step, metadata) } func registrySecretLabels(step *types.Step) (map[string]string, error) { @@ -266,8 +267,8 @@ func registrySecretLabels(step *types.Step) (map[string]string, error) { return labels, nil } -func startRegistrySecret(ctx context.Context, engine *kube, step *types.Step) error { - secret, err := mkRegistrySecret(step, engine.config) +func startRegistrySecret(ctx context.Context, engine *kube, step *types.Step, metadata *metadata.Metadata) error { + secret, err := mkRegistrySecret(step, engine.config, metadata) if err != nil { return err } @@ -279,8 +280,8 @@ func startRegistrySecret(ctx context.Context, engine *kube, step *types.Step) er return nil } -func stopRegistrySecret(ctx context.Context, engine *kube, step *types.Step, deleteOpts meta_v1.DeleteOptions) error { - name, err := registrySecretName(step) +func stopRegistrySecret(ctx context.Context, engine *kube, step *types.Step, deleteOpts meta_v1.DeleteOptions, metadata *metadata.Metadata) error { + name, err := registrySecretName(step, metadata) if err != nil { return err } diff --git a/pipeline/backend/kubernetes/secrets_test.go b/pipeline/backend/kubernetes/secrets_test.go index 99d06723bf8..592c37f9e17 100644 --- a/pipeline/backend/kubernetes/secrets_test.go +++ b/pipeline/backend/kubernetes/secrets_test.go @@ -23,6 +23,7 @@ import ( v1 "k8s.io/api/core/v1" "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" ) func TestNativeSecretsEnabled(t *testing.T) { @@ -208,7 +209,7 @@ func TestUsernameAndPasswordNeedsSecret(t *testing.T) { func TestRegistrySecret(t *testing.T) { const expected = `{ "metadata": { - "name": "wp-01he8bebctabr3kgk0qj36d2me-0", + "name": "wp-owner-repo-name-my-workflow-go-test-01he8", "namespace": "woodpecker", "creationTimestamp": null, "labels": { @@ -231,7 +232,11 @@ func TestRegistrySecret(t *testing.T) { }, }, &config{ Namespace: "woodpecker", - }) + }, + &metadata.Metadata{ + Workflow: metadata.Workflow{Name: "my-workflow"}, + Repo: metadata.Repo{Owner: "owner", Name: "repo_name"}, + }) assert.NoError(t, err) secretJSON, err := json.Marshal(secret) diff --git a/pipeline/backend/local/local.go b/pipeline/backend/local/local.go index 5e11f68f0a6..f867732718c 100644 --- a/pipeline/backend/local/local.go +++ b/pipeline/backend/local/local.go @@ -32,6 +32,7 @@ import ( "golang.org/x/text/transform" "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" ) type workflowState struct { @@ -119,7 +120,7 @@ func (e *local) SetupWorkflow(_ context.Context, _ *types.Config, taskUUID strin } // StartStep the pipeline step. -func (e *local) StartStep(ctx context.Context, step *types.Step, taskUUID string) error { +func (e *local) StartStep(ctx context.Context, step *types.Step, taskUUID string, metadata *metadata.Metadata) error { log.Trace().Str("taskUUID", taskUUID).Msgf("start step %s", step.Name) state, err := e.getState(taskUUID) @@ -204,7 +205,7 @@ func (e *local) execPlugin(ctx context.Context, step *types.Step, state *workflo // WaitStep for the pipeline step to complete and returns // the completion results. -func (e *local) WaitStep(_ context.Context, step *types.Step, taskUUID string) (*types.State, error) { +func (e *local) WaitStep(_ context.Context, step *types.Step, taskUUID string, metadata *metadata.Metadata) (*types.State, error) { log.Trace().Str("taskUUID", taskUUID).Msgf("wait for step %s", step.Name) state, err := e.getState(taskUUID) @@ -234,18 +235,18 @@ func (e *local) WaitStep(_ context.Context, step *types.Step, taskUUID string) ( } // TailStep the pipeline step logs. -func (e *local) TailStep(_ context.Context, step *types.Step, taskUUID string) (io.ReadCloser, error) { +func (e *local) TailStep(_ context.Context, step *types.Step, taskUUID string, metadata *metadata.Metadata) (io.ReadCloser, error) { log.Trace().Str("taskUUID", taskUUID).Msgf("tail logs of step %s", step.Name) return e.output, nil } -func (e *local) DestroyStep(_ context.Context, _ *types.Step, _ string) error { +func (e *local) DestroyStep(_ context.Context, _ *types.Step, _ string, _ *metadata.Metadata) error { // WaitStep already waits for the command to finish, so there is nothing to do here. return nil } // DestroyWorkflow the pipeline environment. -func (e *local) DestroyWorkflow(_ context.Context, _ *types.Config, taskUUID string) error { +func (e *local) DestroyWorkflow(_ context.Context, _ *types.Config, taskUUID string, metadata *metadata.Metadata) error { log.Trace().Str("taskUUID", taskUUID).Msg("delete workflow environment") state, err := e.getState(taskUUID) diff --git a/pipeline/backend/types/backend.go b/pipeline/backend/types/backend.go index 4687018f86d..8c4628fd683 100644 --- a/pipeline/backend/types/backend.go +++ b/pipeline/backend/types/backend.go @@ -19,6 +19,7 @@ import ( "io" "github.com/urfave/cli/v3" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" ) // Backend defines a container orchestration backend and is used @@ -40,20 +41,20 @@ type Backend interface { SetupWorkflow(ctx context.Context, conf *Config, taskUUID string) error // StartStep starts the workflow step. - StartStep(ctx context.Context, step *Step, taskUUID string) error + StartStep(ctx context.Context, step *Step, taskUUID string, metadata *metadata.Metadata) error // WaitStep waits for the workflow step to complete and returns // the completion results. - WaitStep(ctx context.Context, step *Step, taskUUID string) (*State, error) + WaitStep(ctx context.Context, step *Step, taskUUID string, metadata *metadata.Metadata) (*State, error) // TailStep tails the workflow step logs. - TailStep(ctx context.Context, step *Step, taskUUID string) (io.ReadCloser, error) + TailStep(ctx context.Context, step *Step, taskUUID string, metadata *metadata.Metadata) (io.ReadCloser, error) // DestroyStep destroys the workflow step. - DestroyStep(ctx context.Context, step *Step, taskUUID string) error + DestroyStep(ctx context.Context, step *Step, taskUUID string, metadata *metadata.Metadata) error // DestroyWorkflow destroys the workflow environment. - DestroyWorkflow(ctx context.Context, conf *Config, taskUUID string) error + DestroyWorkflow(ctx context.Context, conf *Config, taskUUID string, metadata *metadata.Metadata) error } // BackendInfo represents the reported information of a loaded backend. diff --git a/pipeline/frontend/metadata/types.go b/pipeline/frontend/metadata/types.go index 9d3529fd93c..095992b181b 100644 --- a/pipeline/frontend/metadata/types.go +++ b/pipeline/frontend/metadata/types.go @@ -17,14 +17,15 @@ package metadata type ( // Metadata defines runtime m. Metadata struct { - ID string `json:"id,omitempty"` - Repo Repo `json:"repo,omitempty"` - Curr Pipeline `json:"curr,omitempty"` - Prev Pipeline `json:"prev,omitempty"` - Workflow Workflow `json:"workflow,omitempty"` - Step Step `json:"step,omitempty"` - Sys System `json:"sys,omitempty"` - Forge Forge `json:"forge,omitempty"` + ID string `json:"id,omitempty"` + Repo Repo `json:"repo,omitempty"` + Curr Pipeline `json:"curr,omitempty"` + Prev Pipeline `json:"prev,omitempty"` + Workflow Workflow `json:"workflow,omitempty"` + Step Step `json:"step,omitempty"` + Sys System `json:"sys,omitempty"` + Forge Forge `json:"forge,omitempty"` + FailureIgnore string `json:"failure_ignore,omitempty"` } // Repo defines runtime metadata for a repository. diff --git a/pipeline/pipeline.go b/pipeline/pipeline.go index 2b732b444fb..8c29afc549a 100644 --- a/pipeline/pipeline.go +++ b/pipeline/pipeline.go @@ -28,6 +28,7 @@ import ( backend "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" + meta "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" ) // TODO: move runtime into "runtime" subpackage @@ -89,7 +90,7 @@ func (r *Runtime) MakeLogger() zerolog.Logger { } // Run starts the execution of a workflow and waits for it to complete. -func (r *Runtime) Run(runnerCtx context.Context) error { +func (r *Runtime) Run(runnerCtx context.Context, metadata *metadata.Metadata) error { logger := r.MakeLogger() logger.Debug().Msgf("executing %d stages, in order of:", len(r.spec.Stages)) for stagePos, stage := range r.spec.Stages { @@ -109,7 +110,7 @@ func (r *Runtime) Run(runnerCtx context.Context) error { if ctx.Err() != nil { ctx = GetShutdownCtx() } - if err := r.engine.DestroyWorkflow(ctx, r.spec, r.taskUUID); err != nil { + if err := r.engine.DestroyWorkflow(ctx, r.spec, r.taskUUID, metadata); err != nil { logger.Error().Err(err).Msg("could not destroy engine") } }() @@ -123,7 +124,7 @@ func (r *Runtime) Run(runnerCtx context.Context) error { select { case <-r.ctx.Done(): return ErrCancel - case err := <-r.execAll(stage.Steps): + case err := <-r.execAll(stage.Steps, metadata): if err != nil { r.err = err } @@ -163,7 +164,7 @@ func (r *Runtime) traceStep(processState *backend.State, err error, step *backen } // Executes a set of parallel steps. -func (r *Runtime) execAll(steps []*backend.Step) <-chan error { +func (r *Runtime) execAll(steps []*backend.Step, metadata *metadata.Metadata) <-chan error { var g errgroup.Group done := make(chan error) logger := r.MakeLogger() @@ -200,13 +201,13 @@ func (r *Runtime) execAll(steps []*backend.Step) <-chan error { } // add compatibility for drone-ci plugins - metadata.SetDroneEnviron(step.Environment) + meta.SetDroneEnviron(step.Environment) logger.Debug(). Str("step", step.Name). Msg("executing") - processState, err := r.exec(step) + processState, err := r.exec(step, metadata) logger.Debug(). Str("step", step.Name). @@ -229,14 +230,14 @@ func (r *Runtime) execAll(steps []*backend.Step) <-chan error { } // Executes the step and returns the state and error. -func (r *Runtime) exec(step *backend.Step) (*backend.State, error) { - if err := r.engine.StartStep(r.ctx, step, r.taskUUID); err != nil { +func (r *Runtime) exec(step *backend.Step, metadata *metadata.Metadata) (*backend.State, error) { + if err := r.engine.StartStep(r.ctx, step, r.taskUUID, metadata); err != nil { return nil, err } var wg sync.WaitGroup if r.logger != nil { - rc, err := r.engine.TailStep(r.ctx, step, r.taskUUID) + rc, err := r.engine.TailStep(r.ctx, step, r.taskUUID, metadata) if err != nil { return nil, err } @@ -261,7 +262,7 @@ func (r *Runtime) exec(step *backend.Step) (*backend.State, error) { // We wait until all data was logged. (Needed for some backends like local as WaitStep kills the log stream) wg.Wait() - waitState, err := r.engine.WaitStep(r.ctx, step, r.taskUUID) + waitState, err := r.engine.WaitStep(r.ctx, step, r.taskUUID, metadata) if err != nil { if errors.Is(err, context.Canceled) { return waitState, ErrCancel @@ -269,7 +270,7 @@ func (r *Runtime) exec(step *backend.Step) (*backend.State, error) { return nil, err } - if err := r.engine.DestroyStep(r.ctx, step, r.taskUUID); err != nil { + if err := r.engine.DestroyStep(r.ctx, step, r.taskUUID, metadata); err != nil { return nil, err }