Add env for workflow and step name (#1693)

closes #1681
This commit is contained in:
Anbraten 2023-04-08 13:15:28 +02:00 committed by GitHub
parent 6af9371011
commit 36b5ae3459
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 80 additions and 50 deletions

View file

@ -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"),

View file

@ -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"},

View file

@ -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 `<owner>/<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 |

View file

@ -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

View file

@ -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

View file

@ -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) &&

View file

@ -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,

View file

@ -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")
}
}

View file

@ -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))
}
}
}