I am trying to use the github.com/goccy/go-yaml
Go YAML library to write BitBucket Pipeline files. The complicating fact is that I'm trying to use YAML's merge and anchor features to reuse common steps.
A condensed version of the output I'm looking for:
image: ubuntu:latest
definitions:
steps:
- step: &run-task
name: Run a task
oidc: true
runs-on:
- self.hosted
script:
- sbt test
pipelines:
tags:
'*.*.*':
- step:
<<: *run-task
name: Release
script:
- sbt publish
Here is the current struct/logic:
package main
import (
"fmt"
"github.com/goccy/go-yaml"
)
type Pipeline struct {
Image string `yaml:"image"`
Definitions Definitions `yaml:"definitions"`
Pipelines Pipelines `yaml:"pipelines"`
}
type Pipelines struct {
Tags *Tag `yaml:"tags"`
}
type Definitions struct {
Steps []*StepTemplate `yaml:"steps"`
}
type StepTemplate struct {
*StepTemplate `yaml:"step,anchor=run-task"`
Name string `yaml:"name,omitempty"`
Oidc bool `yaml:"oidc,omitempty"`
RunsOn []string `yaml:"runs-on,omitempty"`
Script []string `yaml:"script,omitempty"`
}
type StepReal struct {
*StepReal `yaml:"step,alias=run-task"`
Name string `yaml:"name,omitempty"`
Oidc bool `yaml:"oidc,omitempty"`
RunsOn []string `yaml:"runs-on,omitempty"`
Script []string `yaml:"script,omitempty"`
}
type Tag map[string][]*StepReal
func main() {
defaultStep := &StepTemplate{
Name: "Run step",
Oidc: true,
RunsOn: []string{"self.hosted", "default"},
Script: []string{"sbt test"},
}
releaseStep := StepReal{
//Step: defaultStep,
Name: "Release",
Script: []string{"sbt publish"},
}
tagSteps := &Tag{
"*.*.*": []*StepReal{&releaseStep},
}
pipe := Pipeline{
Image: "ubuntu:latest",
Definitions: Definitions{
Steps: []*StepTemplate{defaultStep},
},
Pipelines: Pipelines{
Tags: tagSteps,
},
}
bytes, _ := yaml.MarshalWithOptions(pipe, yaml.IndentSequence(true))
fmt.Println(string(bytes))
}
I think I'm pretty close but I cannot figure out a couple of things:
null
in the &run-task
anchor<<: *run-task
merge in the pipeline.tags
blockIt took me some time to figure out but maybe is this what you're looking for:
package main
import (
"fmt"
"github.com/goccy/go-yaml"
)
type Pipeline struct {
Image string `yaml:"image"`
Definitions Definitions `yaml:"definitions"`
Pipelines Pipelines `yaml:"pipelines"`
}
type Pipelines struct {
Tags *Tag `yaml:"tags"`
}
type Definitions struct {
Steps []*StepTemplate `yaml:"steps"`
}
type Step struct {
*Step `yaml:",omitempty,inline,alias"`
Name string `yaml:"name,omitempty"`
Oidc bool `yaml:"oidc,omitempty"`
RunsOn []string `yaml:"runs-on,omitempty"`
Script []string `yaml:"script,omitempty"`
}
type StepTemplate struct {
*Step `yaml:"step,anchor=run-task"`
}
type StepReal struct {
*Step
}
type Tag map[string][]*StepReal
func main() {
defaultStep := &StepTemplate{
&Step{
Name: "Run a task",
Oidc: true,
RunsOn: []string{"self.hosted"},
Script: []string{"sbt test"},
},
}
releaseStep := StepReal{
&Step{
Step: defaultStep.Step,
Name: "Release",
Script: []string{"sbt publish"},
},
}
tagSteps := &Tag{
"*.*.*": []*StepReal{&releaseStep},
}
pipe := Pipeline{
Image: "ubuntu:latest",
Definitions: Definitions{
Steps: []*StepTemplate{defaultStep},
},
Pipelines: Pipelines{
Tags: tagSteps,
},
}
bytes, err := yaml.MarshalWithOptions(pipe, yaml.IndentSequence(true))
if err != nil {
panic(err)
}
fmt.Println(string(bytes))
}