diff --git a/cli/exec/exec.go b/cli/exec/exec.go index 10b31d097..7a1b1f64c 100644 --- a/cli/exec/exec.go +++ b/cli/exec/exec.go @@ -112,7 +112,7 @@ func execWithAxis(c *cli.Context, file, repoPath string, axis matrix.Axis) error metadata := metadataFromContext(c, axis) environ := metadata.Environ() var secrets []compiler.Secret - for key, val := range metadata.Step.Matrix { + for key, val := range metadata.Workflow.Matrix { environ[key] = val secrets = append(secrets, compiler.Secret{ Name: key, @@ -218,7 +218,7 @@ func execWithAxis(c *cli.Context, file, repoPath string, axis matrix.Axis) error ctx, cancel := context.WithTimeout(context.Background(), c.Duration("timeout")) defer cancel() ctx = utils.WithContextSigtermCallback(ctx, func() { - println("ctrl+c received, terminating process") + fmt.Println("ctrl+c received, terminating process") }) return pipeline.New(compiled, @@ -290,10 +290,15 @@ func metadataFromContext(c *cli.Context, axis matrix.Axis) frontend.Metadata { }, }, }, - Step: frontend.Step{ - Number: c.Int("step-number"), + Workflow: frontend.Workflow{ + Name: c.String("workflow-name"), + Number: c.Int("workflow-number"), Matrix: axis, }, + Step: frontend.Step{ + Name: c.String("step-name"), + Number: c.Int("step-number"), + }, Sys: frontend.System{ Name: c.String("system-name"), Link: c.String("system-link"), diff --git a/cli/exec/flags.go b/cli/exec/flags.go index 3a8b42bbc..c884d6f5c 100644 --- a/cli/exec/flags.go +++ b/cli/exec/flags.go @@ -260,8 +260,16 @@ var flags = []cli.Flag{ Name: "prev-commit-author-email", }, &cli.IntFlag{ - EnvVars: []string{"CI_STEP_NUMBER", "CI_JOB_NUMBER"}, - Name: "step-number", + EnvVars: []string{"CI_WORKFLOW_NAME"}, + Name: "workflow-name", + }, + &cli.IntFlag{ + EnvVars: []string{"CI_WORKFLOW_NUMBER", "CI_JOB_NUMBER"}, + Name: "workflow-number", + }, + &cli.IntFlag{ + EnvVars: []string{"CI_STEP_NAME", "CI_JOB_NUMBER"}, + Name: "step-name", }, &cli.StringSliceFlag{ EnvVars: []string{"CI_ENV"}, diff --git a/docs/docs/20-usage/50-environment.md b/docs/docs/20-usage/50-environment.md index c4466350c..cb5771ab3 100644 --- a/docs/docs/20-usage/50-environment.md +++ b/docs/docs/20-usage/50-environment.md @@ -47,7 +47,7 @@ pipeline: This is the reference list of all environment variables available to your pipeline containers. These are injected into your pipeline step and plugins containers, at runtime. | NAME | Description | -|----------------------------------|----------------------------------------------------------------------------------------------| +| -------------------------------- | -------------------------------------------------------------------------------------------- | | `CI=woodpecker` | environment is woodpecker | | | **Repository** | | `CI_REPO` | repository full name `/` | @@ -84,8 +84,10 @@ This is the reference list of all environment variables available to your pipeli | `CI_PIPELINE_CREATED` | pipeline created UNIX timestamp | | `CI_PIPELINE_STARTED` | pipeline started UNIX timestamp | | `CI_PIPELINE_FINISHED` | pipeline finished UNIX timestamp | +| | **Current workflow** | +| `CI_WORKFLOW_NAME` | workflow name | | | **Current step** | -| `CI_STEP_NUMBER` | step number | +| `CI_STEP_NAME` | step name | | `CI_STEP_STATUS` | step status (success, failure) | | `CI_STEP_STARTED` | step started UNIX timestamp | | `CI_STEP_FINISHED` | step finished UNIX timestamp | diff --git a/pipeline/frontend/metadata.go b/pipeline/frontend/metadata.go index 6399570e0..0b22764e9 100644 --- a/pipeline/frontend/metadata.go +++ b/pipeline/frontend/metadata.go @@ -42,12 +42,13 @@ const ( 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"` - Step Step `json:"step,omitempty"` - Sys System `json:"sys,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"` } // Repo defines runtime metadata for a repository. @@ -96,12 +97,19 @@ type ( Avatar string `json:"avatar,omitempty"` } - // Step defines runtime metadata for a step. - Step struct { + // Workflow defines runtime metadata for a workflow. + Workflow struct { + Name string `json:"name,omitempty"` Number int `json:"number,omitempty"` Matrix map[string]string `json:"matrix,omitempty"` } + // Step defines runtime metadata for a step. + Step struct { + Name string `json:"name,omitempty"` + Number int `json:"number,omitempty"` + } + // Secret defines a runtime secret Secret struct { Name string `json:"name,omitempty"` @@ -180,6 +188,10 @@ func (m *Metadata) Environ() map[string]string { "CI_PIPELINE_STARTED": strconv.FormatInt(m.Curr.Started, 10), "CI_PIPELINE_FINISHED": strconv.FormatInt(m.Curr.Finished, 10), + "CI_WORKFLOW_NAME": m.Workflow.Name, + "CI_WORKFLOW_NUMBER": strconv.Itoa(m.Workflow.Number), + + "CI_STEP_NAME": m.Step.Name, "CI_STEP_NUMBER": strconv.Itoa(m.Step.Number), "CI_STEP_STATUS": "", // will be set by agent "CI_STEP_STARTED": "", // will be set by agent diff --git a/pipeline/frontend/yaml/compiler/convert.go b/pipeline/frontend/yaml/compiler/convert.go index 144fd827e..d5e4a2d00 100644 --- a/pipeline/frontend/yaml/compiler/convert.go +++ b/pipeline/frontend/yaml/compiler/convert.go @@ -62,6 +62,7 @@ func (c *Compiler) createProcess(name string, container *yaml.Container, section } environment["CI_WORKSPACE"] = path.Join(c.base, c.path) + environment["CI_STEP_NAME"] = name if section == "services" || container.Detached { detached = true diff --git a/pipeline/frontend/yaml/constraint/constraint.go b/pipeline/frontend/yaml/constraint/constraint.go index f92c6a8b4..41b189070 100644 --- a/pipeline/frontend/yaml/constraint/constraint.go +++ b/pipeline/frontend/yaml/constraint/constraint.go @@ -144,7 +144,7 @@ func (c *Constraint) Match(metadata frontend.Metadata, global bool) (bool, error c.SetDefaultEventFilter() // apply step only filters - match = c.Matrix.Match(metadata.Step.Matrix) + match = c.Matrix.Match(metadata.Workflow.Matrix) } match = match && c.Platform.Match(metadata.Sys.Platform) && diff --git a/pipeline/stepBuilder.go b/pipeline/stepBuilder.go index 6c7e13d37..08e45f799 100644 --- a/pipeline/stepBuilder.go +++ b/pipeline/stepBuilder.go @@ -50,7 +50,7 @@ type StepBuilder struct { } type Item struct { - Step *model.Step + Workflow *model.Step Platform string Labels map[string]string DependsOn []string @@ -76,7 +76,7 @@ func (b *StepBuilder) Build() ([]*Item, error) { } for _, axis := range axes { - step := &model.Step{ + workflow := &model.Step{ PipelineID: b.Curr.ID, PID: pidSequence, PGID: pidSequence, @@ -85,7 +85,7 @@ func (b *StepBuilder) Build() ([]*Item, error) { Name: SanitizePath(y.Name), } - metadata := metadataFromStruct(b.Repo, b.Curr, b.Last, step, b.Link) + metadata := metadataFromStruct(b.Repo, b.Curr, b.Last, workflow, b.Link) environ := b.environmentVariables(metadata, axis) // add global environment variables for substituting @@ -118,12 +118,12 @@ func (b *StepBuilder) Build() ([]*Item, error) { // checking if filtered. if match, err := parsed.When.Match(metadata, true); !match && err == nil { - log.Debug().Str("pipeline", step.Name).Msg( + log.Debug().Str("pipeline", workflow.Name).Msg( "Marked as skipped, dose not match metadata", ) - step.State = model.StatusSkipped + workflow.State = model.StatusSkipped } else if err != nil { - log.Debug().Str("pipeline", step.Name).Msg( + log.Debug().Str("pipeline", workflow.Name).Msg( "Pipeline config could not be parsed", ) return nil, err @@ -131,13 +131,13 @@ func (b *StepBuilder) Build() ([]*Item, error) { // TODO: deprecated branches filter => remove after some time if !parsed.Branches.Match(b.Curr.Branch) && (b.Curr.Event != model.EventDeploy && b.Curr.Event != model.EventTag) { - log.Debug().Str("pipeline", step.Name).Msg( + log.Debug().Str("pipeline", workflow.Name).Msg( "Marked as skipped, dose not match branch", ) - step.State = model.StatusSkipped + workflow.State = model.StatusSkipped } - ir, err := b.toInternalRepresentation(parsed, environ, metadata, step.ID) + ir, err := b.toInternalRepresentation(parsed, environ, metadata, workflow.ID) if err != nil { return nil, err } @@ -147,7 +147,7 @@ func (b *StepBuilder) Build() ([]*Item, error) { } item := &Item{ - Step: step, + Workflow: workflow, Config: ir, Labels: parsed.Labels, DependsOn: parsed.DependsOn, @@ -175,7 +175,7 @@ func (b *StepBuilder) Build() ([]*Item, error) { func stepListContainsItemsToRun(items []*Item) bool { for i := range items { - if items[i].Step.State == model.StatusPending { + if items[i].Workflow.State == model.StatusPending { return true } } @@ -196,7 +196,7 @@ func filterItemsWithMissingDependencies(items []*Item) []*Item { if len(itemsToRemove) > 0 { filtered := make([]*Item, 0) for _, item := range items { - if !containsItemWithName(item.Step.Name, itemsToRemove) { + if !containsItemWithName(item.Workflow.Name, itemsToRemove) { filtered = append(filtered, item) } } @@ -209,7 +209,7 @@ func filterItemsWithMissingDependencies(items []*Item) []*Item { func containsItemWithName(name string, items []*Item) bool { for _, item := range items { - if name == item.Step.Name { + if name == item.Workflow.Name { return true } } @@ -295,9 +295,9 @@ func (b *StepBuilder) toInternalRepresentation(parsed *yaml.Config, environ map[ func SetPipelineStepsOnPipeline(pipeline *model.Pipeline, pipelineItems []*Item) *model.Pipeline { var pidSequence int for _, item := range pipelineItems { - pipeline.Steps = append(pipeline.Steps, item.Step) - if pidSequence < item.Step.PID { - pidSequence = item.Step.PID + pipeline.Steps = append(pipeline.Steps, item.Workflow) + if pidSequence < item.Workflow.PID { + pidSequence = item.Workflow.PID } } @@ -313,11 +313,11 @@ func SetPipelineStepsOnPipeline(pipeline *model.Pipeline, pipelineItems []*Item) PipelineID: pipeline.ID, Name: step.Alias, PID: pidSequence, - PPID: item.Step.PID, + PPID: item.Workflow.PID, PGID: gid, State: model.StatusPending, } - if item.Step.State == model.StatusSkipped { + if item.Workflow.State == model.StatusSkipped { step.State = model.StatusSkipped } pipeline.Steps = append(pipeline.Steps, step) @@ -329,7 +329,7 @@ func SetPipelineStepsOnPipeline(pipeline *model.Pipeline, pipelineItems []*Item) } // return the metadata from the cli context. -func metadataFromStruct(repo *model.Repo, pipeline, last *model.Pipeline, step *model.Step, link string) frontend.Metadata { +func metadataFromStruct(repo *model.Repo, pipeline, last *model.Pipeline, workflow *model.Step, link string) frontend.Metadata { host := link uri, err := url.Parse(link) if err == nil { @@ -345,10 +345,12 @@ func metadataFromStruct(repo *model.Repo, pipeline, last *model.Pipeline, step * }, Curr: metadataPipelineFromModelPipeline(pipeline, true), Prev: metadataPipelineFromModelPipeline(last, false), - Step: frontend.Step{ - Number: step.PID, - Matrix: step.Environ, + Workflow: frontend.Workflow{ + Name: workflow.Name, + Number: workflow.PID, + Matrix: workflow.Environ, }, + Step: frontend.Step{}, Sys: frontend.System{ Name: "woodpecker", Link: link, diff --git a/pipeline/stepBuilder_test.go b/pipeline/stepBuilder_test.go index 4da2e4bef..db8075554 100644 --- a/pipeline/stepBuilder_test.go +++ b/pipeline/stepBuilder_test.go @@ -273,7 +273,7 @@ pipeline: if err != nil { t.Fatal(err) } - pipelineNames := []string{pipelineItems[0].Step.Name, pipelineItems[1].Step.Name} + pipelineNames := []string{pipelineItems[0].Workflow.Name, pipelineItems[1].Workflow.Name} if !containsItemWithName("lint", pipelineItems) || !containsItemWithName("test", pipelineItems) { t.Fatalf("Pipeline name should be 'lint' and 'test' but are '%v'", pipelineNames) } @@ -312,15 +312,15 @@ pipeline: if len(pipelineItems) != 2 { t.Fatal("Should have generated 2 pipeline") } - if pipelineItems[0].Step.State != model.StatusSkipped { + if pipelineItems[0].Workflow.State != model.StatusSkipped { t.Fatal("Should not run on dev branch") } - for _, child := range pipelineItems[0].Step.Children { + for _, child := range pipelineItems[0].Workflow.Children { if child.State != model.StatusSkipped { t.Fatal("Children should skipped status too") } } - if pipelineItems[1].Step.State != model.StatusPending { + if pipelineItems[1].Workflow.State != model.StatusPending { t.Fatal("Should run on dev branch") } } @@ -448,7 +448,7 @@ depends_on: [ zerostep ] if len(pipelineItems) != 1 { t.Fatal("Zerostep and the step that depends on it should not generate a pipeline item") } - if pipelineItems[0].Step.Name != "justastep" { + if pipelineItems[0].Workflow.Name != "justastep" { t.Fatal("justastep should have been generated") } } @@ -502,7 +502,7 @@ depends_on: [ shouldbefiltered ] if len(pipelineItems) != 1 { t.Fatal("Zerostep and the step that depends on it, and the one depending on it should not generate a pipeline item") } - if pipelineItems[0].Step.Name != "justastep" { + if pipelineItems[0].Workflow.Name != "justastep" { t.Fatal("justastep should have been generated") } } diff --git a/server/pipeline/queue.go b/server/pipeline/queue.go index 5fa359b55..19fe42d06 100644 --- a/server/pipeline/queue.go +++ b/server/pipeline/queue.go @@ -28,11 +28,11 @@ import ( func queuePipeline(repo *model.Repo, pipelineItems []*pipeline.Item) error { var tasks []*model.Task for _, item := range pipelineItems { - if item.Step.State == model.StatusSkipped { + if item.Workflow.State == model.StatusSkipped { continue } task := new(model.Task) - task.ID = fmt.Sprint(item.Step.ID) + task.ID = fmt.Sprint(item.Workflow.ID) task.Labels = map[string]string{} for k, v := range item.Labels { task.Labels[k] = v @@ -44,7 +44,7 @@ func queuePipeline(repo *model.Repo, pipelineItems []*pipeline.Item) error { task.DepStatus = make(map[string]model.StatusValue) task.Data, _ = json.Marshal(rpc.Pipeline{ - ID: fmt.Sprint(item.Step.ID), + ID: fmt.Sprint(item.Workflow.ID), Config: item.Config, Timeout: repo.Timeout, }) @@ -60,8 +60,8 @@ func queuePipeline(repo *model.Repo, pipelineItems []*pipeline.Item) error { func taskIds(dependsOn []string, pipelineItems []*pipeline.Item) (taskIds []string) { for _, dep := range dependsOn { for _, pipelineItem := range pipelineItems { - if pipelineItem.Step.Name == dep { - taskIds = append(taskIds, fmt.Sprint(pipelineItem.Step.ID)) + if pipelineItem.Workflow.Name == dep { + taskIds = append(taskIds, fmt.Sprint(pipelineItem.Workflow.ID)) } } }