github.com/jenkins-x/jx/v2@v2.1.155/pkg/tekton/syntax/syntax_helpers_test/test_helpers.go (about)

     1  package syntax_helpers_test
     2  
     3  import (
     4  	v1 "github.com/jenkins-x/jx-api/pkg/apis/jenkins.io/v1"
     5  	"github.com/jenkins-x/jx/v2/pkg/tekton/syntax"
     6  	"github.com/jenkins-x/jx/v2/pkg/util"
     7  	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1"
     8  	"github.com/tektoncd/pipeline/test/builder"
     9  	corev1 "k8s.io/api/core/v1"
    10  	"k8s.io/apimachinery/pkg/api/resource"
    11  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    12  )
    13  
    14  // PipelineStructureOp is an operation used in generating a PipelineStructure
    15  type PipelineStructureOp func(structure *v1.PipelineStructure)
    16  
    17  // PipelineStructureStageOp is an operation used in generating a PipelineStructureStage
    18  type PipelineStructureStageOp func(stage *v1.PipelineStructureStage)
    19  
    20  // PipelineStructure creates a PipelineStructure
    21  func PipelineStructure(name string, ops ...PipelineStructureOp) *v1.PipelineStructure {
    22  	s := &v1.PipelineStructure{
    23  		ObjectMeta: metav1.ObjectMeta{
    24  			Name: name,
    25  		},
    26  	}
    27  
    28  	for _, op := range ops {
    29  		op(s)
    30  	}
    31  
    32  	return s
    33  }
    34  
    35  // StructurePipelineRunRef adds a run reference to the structure
    36  func StructurePipelineRunRef(name string) PipelineStructureOp {
    37  	return func(structure *v1.PipelineStructure) {
    38  		structure.PipelineRunRef = &name
    39  	}
    40  }
    41  
    42  // StructureStage adds a stage to the structure
    43  func StructureStage(name string, ops ...PipelineStructureStageOp) PipelineStructureOp {
    44  	return func(structure *v1.PipelineStructure) {
    45  		stage := v1.PipelineStructureStage{Name: name}
    46  
    47  		for _, op := range ops {
    48  			op(&stage)
    49  		}
    50  
    51  		structure.Stages = append(structure.Stages, stage)
    52  	}
    53  }
    54  
    55  // StructureStageTaskRef adds a task ref to the stage
    56  func StructureStageTaskRef(name string) PipelineStructureStageOp {
    57  	return func(stage *v1.PipelineStructureStage) {
    58  		stage.TaskRef = &name
    59  	}
    60  }
    61  
    62  // StructureStageTaskRunRef adds a task run ref to the stage
    63  func StructureStageTaskRunRef(name string) PipelineStructureStageOp {
    64  	return func(stage *v1.PipelineStructureStage) {
    65  		stage.TaskRunRef = &name
    66  	}
    67  }
    68  
    69  // StructureStageDepth sets the depth on the stage
    70  func StructureStageDepth(depth int8) PipelineStructureStageOp {
    71  	return func(stage *v1.PipelineStructureStage) {
    72  		stage.Depth = depth
    73  	}
    74  }
    75  
    76  // StructureStageParent sets the parent stage for the stage
    77  func StructureStageParent(parent string) PipelineStructureStageOp {
    78  	return func(stage *v1.PipelineStructureStage) {
    79  		stage.Parent = &parent
    80  	}
    81  }
    82  
    83  // StructureStagePrevious sets the previous stage for the stage
    84  func StructureStagePrevious(previous string) PipelineStructureStageOp {
    85  	return func(stage *v1.PipelineStructureStage) {
    86  		stage.Previous = &previous
    87  	}
    88  }
    89  
    90  // StructureStageNext sets the next stage for the stage
    91  func StructureStageNext(Next string) PipelineStructureStageOp {
    92  	return func(stage *v1.PipelineStructureStage) {
    93  		stage.Next = &Next
    94  	}
    95  }
    96  
    97  // StructureStageStages sets the nested sequential stages for the stage
    98  func StructureStageStages(stages ...string) PipelineStructureStageOp {
    99  	return func(stage *v1.PipelineStructureStage) {
   100  		stage.Stages = append(stage.Stages, stages...)
   101  	}
   102  }
   103  
   104  // StructureStageParallel sets the nested parallel stages for the stage
   105  func StructureStageParallel(stages ...string) PipelineStructureStageOp {
   106  	return func(stage *v1.PipelineStructureStage) {
   107  		stage.Parallel = append(stage.Parallel, stages...)
   108  	}
   109  }
   110  
   111  // PipelineOp is an operation on a ParsedPipeline
   112  type PipelineOp func(*syntax.ParsedPipeline)
   113  
   114  // PipelineOptionsOp is an operation on RootOptions
   115  type PipelineOptionsOp func(*syntax.RootOptions)
   116  
   117  // PipelinePostOp is an operation on Post
   118  type PipelinePostOp func(*syntax.Post)
   119  
   120  // StageOp is an operation on a Stage
   121  type StageOp func(*syntax.Stage)
   122  
   123  // StageOptionsOp is an operation on StageOptions
   124  type StageOptionsOp func(*syntax.StageOptions)
   125  
   126  // StepOp is an operation on a step
   127  type StepOp func(*syntax.Step)
   128  
   129  // LoopOp is an operation on a Loop
   130  type LoopOp func(*syntax.Loop)
   131  
   132  // ParsedPipeline creates a ParsedPipeline from the provided operations
   133  func ParsedPipeline(ops ...PipelineOp) *syntax.ParsedPipeline {
   134  	s := &syntax.ParsedPipeline{}
   135  
   136  	for _, op := range ops {
   137  		op(s)
   138  	}
   139  
   140  	return s
   141  }
   142  
   143  // PipelineAgent sets the agent for the pipeline
   144  func PipelineAgent(image string) PipelineOp {
   145  	return func(parsed *syntax.ParsedPipeline) {
   146  		parsed.Agent = &syntax.Agent{
   147  			Image: image,
   148  		}
   149  	}
   150  }
   151  
   152  // PipelineOptions sets the RootOptions for the pipeline
   153  func PipelineOptions(ops ...PipelineOptionsOp) PipelineOp {
   154  	return func(parsed *syntax.ParsedPipeline) {
   155  		parsed.Options = &syntax.RootOptions{}
   156  
   157  		for _, op := range ops {
   158  			op(parsed.Options)
   159  		}
   160  	}
   161  }
   162  
   163  // PipelineSidecar adds a sidecar container to the RootOptions for the pipeline
   164  func PipelineSidecar(sidecar *corev1.Container) PipelineOptionsOp {
   165  	return func(options *syntax.RootOptions) {
   166  		if options.Sidecars == nil {
   167  			options.Sidecars = []*corev1.Container{}
   168  		}
   169  		options.Sidecars = append(options.Sidecars, sidecar)
   170  	}
   171  }
   172  
   173  // PipelineVolume adds a volume to the RootOptions for the pipeline
   174  func PipelineVolume(volume *corev1.Volume) PipelineOptionsOp {
   175  	return func(options *syntax.RootOptions) {
   176  		if options.Volumes == nil {
   177  			options.Volumes = []*corev1.Volume{}
   178  		}
   179  		options.Volumes = append(options.Volumes, volume)
   180  	}
   181  }
   182  
   183  // StageSidecar adds a sidecar to the StageOptions for the stage
   184  func StageSidecar(sidecar *corev1.Container) StageOptionsOp {
   185  	return func(options *syntax.StageOptions) {
   186  		if options.RootOptions == nil {
   187  			options.RootOptions = &syntax.RootOptions{}
   188  		}
   189  		if options.Sidecars == nil {
   190  			options.Sidecars = []*corev1.Container{}
   191  		}
   192  		options.Sidecars = append(options.Sidecars, sidecar)
   193  	}
   194  }
   195  
   196  // StageVolume adds a volume to the StageOptions for the stage
   197  func StageVolume(volume *corev1.Volume) StageOptionsOp {
   198  	return func(options *syntax.StageOptions) {
   199  		if options.RootOptions == nil {
   200  			options.RootOptions = &syntax.RootOptions{}
   201  		}
   202  		if options.Volumes == nil {
   203  			options.Volumes = []*corev1.Volume{}
   204  		}
   205  		options.Volumes = append(options.Volumes, volume)
   206  	}
   207  }
   208  
   209  // PipelineContainerOptions sets the containerOptions for the pipeline
   210  func PipelineContainerOptions(ops ...builder.ContainerOp) PipelineOptionsOp {
   211  	return func(options *syntax.RootOptions) {
   212  		options.ContainerOptions = &corev1.Container{}
   213  
   214  		for _, op := range ops {
   215  			op(options.ContainerOptions)
   216  		}
   217  	}
   218  }
   219  
   220  // PipelineTolerations sets the tolerations for the pipeline
   221  func PipelineTolerations(tolerations []corev1.Toleration) PipelineOptionsOp {
   222  	return func(options *syntax.RootOptions) {
   223  		options.Tolerations = append(options.Tolerations, tolerations...)
   224  	}
   225  }
   226  
   227  // PipelinePodLabels sets the optional pod labels for the pipeline
   228  func PipelinePodLabels(labels map[string]string) PipelineOptionsOp {
   229  	return func(options *syntax.RootOptions) {
   230  		options.PodLabels = util.MergeMaps(options.PodLabels, labels)
   231  	}
   232  }
   233  
   234  // StageContainerOptions sets the containerOptions for a stage
   235  func StageContainerOptions(ops ...builder.ContainerOp) StageOptionsOp {
   236  	return func(options *syntax.StageOptions) {
   237  		if options.RootOptions == nil {
   238  			options.RootOptions = &syntax.RootOptions{}
   239  		}
   240  		options.ContainerOptions = &corev1.Container{}
   241  
   242  		for _, op := range ops {
   243  			op(options.ContainerOptions)
   244  		}
   245  	}
   246  }
   247  
   248  // PipelineDir sets the default working directory for the pipeline
   249  func PipelineDir(dir string) PipelineOp {
   250  	return func(pipeline *syntax.ParsedPipeline) {
   251  		pipeline.WorkingDir = &dir
   252  	}
   253  }
   254  
   255  // StageDir sets the default working directory for the stage
   256  func StageDir(dir string) StageOp {
   257  	return func(stage *syntax.Stage) {
   258  		stage.WorkingDir = &dir
   259  	}
   260  }
   261  
   262  // ContainerResourceLimits sets the resource limits for container options
   263  func ContainerResourceLimits(cpus, memory string) builder.ContainerOp {
   264  	return func(container *corev1.Container) {
   265  		cpuQuantity, _ := resource.ParseQuantity(cpus)
   266  		memoryQuantity, _ := resource.ParseQuantity(memory)
   267  		container.Resources.Limits = corev1.ResourceList{
   268  			"cpu":    cpuQuantity,
   269  			"memory": memoryQuantity,
   270  		}
   271  	}
   272  }
   273  
   274  // ContainerResourceRequests sets the resource requests for container options
   275  func ContainerResourceRequests(cpus, memory string) builder.ContainerOp {
   276  	return func(container *corev1.Container) {
   277  		cpuQuantity, _ := resource.ParseQuantity(cpus)
   278  		memoryQuantity, _ := resource.ParseQuantity(memory)
   279  		container.Resources.Requests = corev1.ResourceList{
   280  			"cpu":    cpuQuantity,
   281  			"memory": memoryQuantity,
   282  		}
   283  	}
   284  }
   285  
   286  // ContainerSecurityContext sets the security context for container options
   287  func ContainerSecurityContext(privileged bool) builder.ContainerOp {
   288  	return func(container *corev1.Container) {
   289  		container.SecurityContext = &corev1.SecurityContext{
   290  			Privileged: &privileged,
   291  		}
   292  	}
   293  }
   294  
   295  // ContainerVolumeMount adds a VolumeMount to the container options
   296  func ContainerVolumeMount(name string, mountPath string) builder.ContainerOp {
   297  	return func(container *corev1.Container) {
   298  		container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
   299  			Name:      name,
   300  			MountPath: mountPath,
   301  		})
   302  	}
   303  }
   304  
   305  // StepVolumeMount adds a VolumeMount to the container options on a step
   306  func StepVolumeMount(name string, mountPath string) builder.StepOp {
   307  	return func(step *v1alpha1.Step) {
   308  		step.VolumeMounts = append(step.VolumeMounts, corev1.VolumeMount{
   309  			Name:      name,
   310  			MountPath: mountPath,
   311  		})
   312  	}
   313  }
   314  
   315  // StepResourceLimits sets the resource limits for container options on a step
   316  func StepResourceLimits(cpus, memory string) builder.StepOp {
   317  	return func(step *v1alpha1.Step) {
   318  		cpuQuantity, _ := resource.ParseQuantity(cpus)
   319  		memoryQuantity, _ := resource.ParseQuantity(memory)
   320  		step.Resources.Limits = corev1.ResourceList{
   321  			"cpu":    cpuQuantity,
   322  			"memory": memoryQuantity,
   323  		}
   324  	}
   325  }
   326  
   327  // StepResourceRequests sets the resource requests for container options on a step
   328  func StepResourceRequests(cpus, memory string) builder.StepOp {
   329  	return func(step *v1alpha1.Step) {
   330  		cpuQuantity, _ := resource.ParseQuantity(cpus)
   331  		memoryQuantity, _ := resource.ParseQuantity(memory)
   332  		step.Resources.Requests = corev1.ResourceList{
   333  			"cpu":    cpuQuantity,
   334  			"memory": memoryQuantity,
   335  		}
   336  	}
   337  }
   338  
   339  // StepSecurityContext sets the security context for container options on a step
   340  func StepSecurityContext(privileged bool) builder.StepOp {
   341  	return func(step *v1alpha1.Step) {
   342  		step.SecurityContext = &corev1.SecurityContext{
   343  			Privileged: &privileged,
   344  		}
   345  	}
   346  }
   347  
   348  // EnvVarFrom adds an environment variable using EnvVarSource to the container options
   349  func EnvVarFrom(name string, source *corev1.EnvVarSource) builder.ContainerOp {
   350  	return func(container *corev1.Container) {
   351  		container.Env = append(container.Env, corev1.EnvVar{
   352  			Name:      name,
   353  			ValueFrom: source,
   354  		})
   355  	}
   356  }
   357  
   358  // EnvVar adds an environment variable with a value to the container options
   359  func EnvVar(name string, value string) builder.ContainerOp {
   360  	return func(container *corev1.Container) {
   361  		container.Env = append(container.Env, corev1.EnvVar{
   362  			Name:  name,
   363  			Value: value,
   364  		})
   365  	}
   366  }
   367  
   368  // PipelineOptionsTimeout sets the timeout for the pipeline
   369  func PipelineOptionsTimeout(time int64, unit syntax.TimeoutUnit) PipelineOptionsOp {
   370  	return func(options *syntax.RootOptions) {
   371  		options.Timeout = &syntax.Timeout{
   372  			Time: time,
   373  			Unit: unit,
   374  		}
   375  	}
   376  }
   377  
   378  // PipelineOptionsRetry sets the retry count for the pipeline
   379  func PipelineOptionsRetry(count int8) PipelineOptionsOp {
   380  	return func(options *syntax.RootOptions) {
   381  		options.Retry = count
   382  	}
   383  }
   384  
   385  // PipelineOptionsDistributeParallelAcrossNodes sets the value for distributeParallelAcrossNodes
   386  func PipelineOptionsDistributeParallelAcrossNodes(b bool) PipelineOptionsOp {
   387  	return func(options *syntax.RootOptions) {
   388  		options.DistributeParallelAcrossNodes = b
   389  	}
   390  }
   391  
   392  // PipelineEnvVar add an environment variable, with specified name and value, to the pipeline.
   393  func PipelineEnvVar(name, value string) PipelineOp {
   394  	return func(parsed *syntax.ParsedPipeline) {
   395  		parsed.Env = append(parsed.GetEnv(), corev1.EnvVar{
   396  			Name:  name,
   397  			Value: value,
   398  		})
   399  	}
   400  }
   401  
   402  // PipelinePost adds a post condition to the pipeline
   403  func PipelinePost(condition syntax.PostCondition, ops ...PipelinePostOp) PipelineOp {
   404  	return func(parsed *syntax.ParsedPipeline) {
   405  		post := syntax.Post{
   406  			Condition: condition,
   407  		}
   408  
   409  		for _, op := range ops {
   410  			op(&post)
   411  		}
   412  
   413  		parsed.Post = append(parsed.Post, post)
   414  	}
   415  }
   416  
   417  // PipelineStage adds a stage to the pipeline
   418  func PipelineStage(name string, ops ...StageOp) PipelineOp {
   419  	return func(parsed *syntax.ParsedPipeline) {
   420  		s := syntax.Stage{
   421  			Name: name,
   422  		}
   423  
   424  		for _, op := range ops {
   425  			op(&s)
   426  		}
   427  		parsed.Stages = append(parsed.Stages, s)
   428  	}
   429  }
   430  
   431  // PostAction adds a post action to a post condition
   432  func PostAction(name string, options map[string]string) PipelinePostOp {
   433  	return func(post *syntax.Post) {
   434  		post.Actions = append(post.Actions, syntax.PostAction{
   435  			Name:    name,
   436  			Options: options,
   437  		})
   438  	}
   439  }
   440  
   441  // StageAgent sets the image/agent for a stage
   442  func StageAgent(image string) StageOp {
   443  	return func(stage *syntax.Stage) {
   444  		stage.Agent = &syntax.Agent{
   445  			Image: image,
   446  		}
   447  	}
   448  }
   449  
   450  // StageOptions sets the StageOptions for a stage
   451  func StageOptions(ops ...StageOptionsOp) StageOp {
   452  	return func(stage *syntax.Stage) {
   453  		stage.Options = &syntax.StageOptions{}
   454  
   455  		for _, op := range ops {
   456  			op(stage.Options)
   457  		}
   458  	}
   459  }
   460  
   461  // StageOptionsTimeout sets the timeout for a stage
   462  func StageOptionsTimeout(time int64, unit syntax.TimeoutUnit) StageOptionsOp {
   463  	return func(options *syntax.StageOptions) {
   464  		if options.RootOptions == nil {
   465  			options.RootOptions = &syntax.RootOptions{}
   466  		}
   467  		options.Timeout = &syntax.Timeout{
   468  			Time: time,
   469  			Unit: unit,
   470  		}
   471  	}
   472  }
   473  
   474  // StageOptionsRetry sets the retry count for a stage
   475  func StageOptionsRetry(count int8) StageOptionsOp {
   476  	return func(options *syntax.StageOptions) {
   477  		if options.RootOptions == nil {
   478  			options.RootOptions = &syntax.RootOptions{}
   479  		}
   480  		options.Retry = count
   481  	}
   482  }
   483  
   484  // StageOptionsWorkspace sets the workspace for a stage
   485  func StageOptionsWorkspace(ws string) StageOptionsOp {
   486  	return func(options *syntax.StageOptions) {
   487  		options.Workspace = &ws
   488  	}
   489  }
   490  
   491  // StageOptionsStash adds a stash to the stage
   492  func StageOptionsStash(name, files string) StageOptionsOp {
   493  	return func(options *syntax.StageOptions) {
   494  		options.Stash = &syntax.Stash{
   495  			Name:  name,
   496  			Files: files,
   497  		}
   498  	}
   499  }
   500  
   501  // StageOptionsUnstash adds an unstash to the stage
   502  func StageOptionsUnstash(name, dir string) StageOptionsOp {
   503  	return func(options *syntax.StageOptions) {
   504  		options.Unstash = &syntax.Unstash{
   505  			Name: name,
   506  		}
   507  		if dir != "" {
   508  			options.Unstash.Dir = dir
   509  		}
   510  	}
   511  }
   512  
   513  // StageEnvVar add an environment variable, with specified name and value, to the stage.
   514  func StageEnvVar(name, value string) StageOp {
   515  	return func(stage *syntax.Stage) {
   516  		stage.Env = append(stage.GetEnv(), corev1.EnvVar{
   517  			Name:  name,
   518  			Value: value,
   519  		})
   520  	}
   521  }
   522  
   523  // StagePost adds a post condition to the stage
   524  func StagePost(condition syntax.PostCondition, ops ...PipelinePostOp) StageOp {
   525  	return func(stage *syntax.Stage) {
   526  		post := syntax.Post{
   527  			Condition: condition,
   528  		}
   529  
   530  		for _, op := range ops {
   531  			op(&post)
   532  		}
   533  
   534  		stage.Post = append(stage.Post, post)
   535  	}
   536  }
   537  
   538  // StepAgent sets the agent for a step
   539  func StepAgent(image string) StepOp {
   540  	return func(step *syntax.Step) {
   541  		step.Agent = &syntax.Agent{
   542  			Image: image,
   543  		}
   544  	}
   545  }
   546  
   547  // StepImage sets the image for a step
   548  func StepImage(image string) StepOp {
   549  	return func(step *syntax.Step) {
   550  		step.Image = image
   551  	}
   552  }
   553  
   554  // StepCmd sets the command for a step
   555  func StepCmd(cmd string) StepOp {
   556  	return func(step *syntax.Step) {
   557  		step.Command = cmd
   558  	}
   559  }
   560  
   561  // StepName sets the name for a step
   562  func StepName(name string) StepOp {
   563  	return func(step *syntax.Step) {
   564  		step.Name = name
   565  	}
   566  }
   567  
   568  // StepArg sets the arguments for a step
   569  func StepArg(arg string) StepOp {
   570  	return func(step *syntax.Step) {
   571  		step.Arguments = append(step.Arguments, arg)
   572  	}
   573  }
   574  
   575  // StepStep sets the alias step for a step
   576  func StepStep(s string) StepOp {
   577  	return func(step *syntax.Step) {
   578  		step.Step = s
   579  	}
   580  }
   581  
   582  // StepOptions sets the alias step options for a step
   583  func StepOptions(options map[string]string) StepOp {
   584  	return func(step *syntax.Step) {
   585  		step.Options = options
   586  	}
   587  }
   588  
   589  // StepDir sets the working dir for a step
   590  func StepDir(dir string) StepOp {
   591  	return func(step *syntax.Step) {
   592  		step.Dir = dir
   593  	}
   594  }
   595  
   596  // StepLoop adds a loop to the step
   597  func StepLoop(variable string, values []string, ops ...LoopOp) StepOp {
   598  	return func(step *syntax.Step) {
   599  		loop := &syntax.Loop{
   600  			Variable: variable,
   601  			Values:   values,
   602  		}
   603  
   604  		for _, op := range ops {
   605  			op(loop)
   606  		}
   607  
   608  		step.Loop = loop
   609  	}
   610  }
   611  
   612  // StepEnvVar add an environment variable, with specified name and value, to the step.
   613  func StepEnvVar(name, value string) StepOp {
   614  	return func(step *syntax.Step) {
   615  		step.Env = append(step.Env, corev1.EnvVar{
   616  			Name:  name,
   617  			Value: value,
   618  		})
   619  	}
   620  }
   621  
   622  // LoopStep adds a step to the loop
   623  func LoopStep(ops ...StepOp) LoopOp {
   624  	return func(loop *syntax.Loop) {
   625  		step := syntax.Step{}
   626  
   627  		for _, op := range ops {
   628  			op(&step)
   629  		}
   630  
   631  		loop.Steps = append(loop.Steps, step)
   632  	}
   633  }
   634  
   635  // StageStep adds a step to the stage
   636  func StageStep(ops ...StepOp) StageOp {
   637  	return func(stage *syntax.Stage) {
   638  		step := syntax.Step{}
   639  
   640  		for _, op := range ops {
   641  			op(&step)
   642  		}
   643  
   644  		stage.Steps = append(stage.Steps, step)
   645  	}
   646  }
   647  
   648  // StageParallel adds a nested parallel stage to the stage
   649  func StageParallel(name string, ops ...StageOp) StageOp {
   650  	return func(stage *syntax.Stage) {
   651  		n := syntax.Stage{Name: name}
   652  
   653  		for _, op := range ops {
   654  			op(&n)
   655  		}
   656  
   657  		stage.Parallel = append(stage.Parallel, n)
   658  	}
   659  }
   660  
   661  // StageSequential adds a nested sequential stage to the stage
   662  func StageSequential(name string, ops ...StageOp) StageOp {
   663  	return func(stage *syntax.Stage) {
   664  		n := syntax.Stage{Name: name}
   665  
   666  		for _, op := range ops {
   667  			op(&n)
   668  		}
   669  
   670  		stage.Stages = append(stage.Stages, n)
   671  	}
   672  }
   673  
   674  // TaskStageLabel sets the stage label on the task
   675  func TaskStageLabel(value string) builder.TaskOp {
   676  	return func(t *v1alpha1.Task) {
   677  		if t.ObjectMeta.Labels == nil {
   678  			t.ObjectMeta.Labels = map[string]string{}
   679  		}
   680  		t.ObjectMeta.Labels[syntax.LabelStageName] = syntax.MangleToRfc1035Label(value, "")
   681  	}
   682  }
   683  
   684  // OutputsResource adds a resource, with specified name and type, to the Outputs.
   685  // Any number of TaskResource modifier can be passed to transform it.
   686  func OutputsResource(name string, resourceType v1alpha1.PipelineResourceType, ops ...builder.TaskResourceOp) builder.OutputsOp {
   687  	return func(i *v1alpha1.Outputs) {
   688  		r := &v1alpha1.TaskResource{
   689  			ResourceDeclaration: v1alpha1.ResourceDeclaration{
   690  				Name: name,
   691  				Type: resourceType,
   692  			}}
   693  		for _, op := range ops {
   694  			op(r)
   695  		}
   696  		i.Resources = append(i.Resources, *r)
   697  	}
   698  }