Skip to content
This repository has been archived by the owner on Feb 14, 2024. It is now read-only.

Commit

Permalink
Merge pull request #41 from buildkite/group
Browse files Browse the repository at this point in the history
Add support for group steps
  • Loading branch information
jradtilbrook authored Apr 20, 2022
2 parents cb91f1a + 906dfba commit ff56568
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
17 changes: 14 additions & 3 deletions cmd/buildkite-signed-pipeline/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,28 @@ func (s SharedSecretSigner) Sign(pipeline interface{}) (interface{}, error) {

copy := reflect.MakeMap(original.Type())

// Copy values to new map
// TODO handle pipelines of single commands (e.g. `command: foo`)
// Iterate over the top level map (where keys are things like, steps, agents, env)
for _, mk := range original.MapKeys() {
keyName := mk.String()
item := original.MapIndex(mk)

// references many steps
// We only care about "steps" at the top level, so dive into this field
if strings.EqualFold(keyName, "steps") {
unwrapped := item.Elem()
if unwrapped.Kind() == reflect.Slice {
// newSteps will replace the existing steps. they will be built up with the signature added
var newSteps []interface{}
for i := 0; i < unwrapped.Len(); i += 1 {
stepItem := unwrapped.Index(i)
// If the current stepItem is a complex type (list or map)
if stepItem.Elem().Kind() != reflect.String {
signedStep, err := s.signStep(stepItem)
if err != nil {
return nil, err
}
newSteps = append(newSteps, signedStep)
} else {
} else { // The current stepItem is a plain string (like just `wait` or `block`) so added it without modification
newSteps = append(newSteps, stepItem.Interface())
}
}
Expand Down Expand Up @@ -123,6 +125,15 @@ func (s SharedSecretSigner) signStep(step reflect.Value) (interface{}, error) {
}
}

// if the step is a `group` we need to recurse to calculate the signature of nested command steps
if _, hasGroup := copy["group"]; hasGroup {
pipeline := make(map[string]interface{})
pipeline["steps"] = copy["steps"]
signedGroup, err := s.Sign(pipeline)
copy["steps"] = signedGroup.(map[string]interface{})["steps"]
return copy, err
}

// extract the plugin declaration for signing
extractedPlugins := ""
var err error
Expand Down
19 changes: 19 additions & 0 deletions cmd/buildkite-signed-pipeline/signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,25 @@ func TestSigningCommandWithPlugins(t *testing.T) {
assert.Equal(t, "llamas", sig)
}

func TestSigningCommandWithGroup(t *testing.T) {
jsonPipeline := `{"steps":[{"group":"Tests","steps":[{"command":"echo pass"}]}]}`

var parsed interface{}
if err := json.Unmarshal([]byte(jsonPipeline), &parsed); err != nil {
t.Fatal(err)
}

signer := NewSharedSecretSigner("secret-llamas")

signed, err := signer.Sign(parsed)
if err != nil {
t.Fatal(err)
}

j, err := json.Marshal(signed)
assert.Equal(t, `{"steps":[{"group":"Tests","steps":[{"command":"echo pass","env":{"STEP_SIGNATURE":"sha256:2c3cb7057477c9630e26532ab6b1707fffc4df3efeb6488bcd9ff2784e1de6fa"}}]}]}`, string(j))
}

func mapInto(dest interface{}, source interface{}) error {
jsonBytes, err := json.Marshal(source)
if err != nil {
Expand Down

0 comments on commit ff56568

Please sign in to comment.