Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/HEAD' into feat-skip-path
Browse files Browse the repository at this point in the history
  • Loading branch information
jamietanna committed Oct 8, 2024
2 parents 3e730b9 + d12c514 commit 3417451
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 33 deletions.
29 changes: 29 additions & 0 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,32 @@ steps:
config:
group: "this is a group"
command: "echo this-does-not-run"

- label: ":testtube: Testing default config"
plugins:
- artifacts#v1.9.2:
download:
- "monorepo-diff-buildkite-plugin"
- monorepo-diff#${BUILDKITE_COMMIT}:
diff: "cat ./e2e/commands-or-triggers"
watch:
- path: "not_a_path/"
config:
command: echo "This shouldn't run"
- default:
command: "echo hello-world"

- label: ":testtube: Testing default config with map"
plugins:
- artifacts#v1.9.2:
download:
- "monorepo-diff-buildkite-plugin"
- monorepo-diff#${BUILDKITE_COMMIT}:
diff: "cat ./e2e/commands-or-triggers"
watch:
- path: "not_a_path/"
config:
command: echo "This shouldn't run"
- default:
config:
command: "echo hello-world"
36 changes: 30 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Configuration supports 2 different step types.
steps:
- label: "Triggering pipelines"
plugins:
- monorepo-diff#v1.0.1:
- monorepo-diff#v1.1.0:
diff: "git diff --name-only HEAD~1"
watch:
- path: app/
Expand All @@ -76,7 +76,7 @@ steps:
steps:
- label: "Triggering pipelines with plugin"
plugins:
- monorepo-diff#v1.0.1:
- monorepo-diff#v1.1.0:
watch:
- path: test/.buildkite/
config: # Required [trigger step configuration]
Expand Down Expand Up @@ -143,7 +143,7 @@ git diff --name-only "$LATEST_TAG"
steps:
- label: "Triggering pipelines"
plugins:
- monorepo-diff#v1.0.1:
- monorepo-diff#v1.1.0:
diff: "git diff --name-only HEAD~1"
watch:
- path: "bar-service/"
Expand All @@ -160,6 +160,30 @@ This controls the pipeline interpolation on upload, and defaults to `true`.
If set to `false` it adds `--no-interpolation` to the `buildkite pipeline upload`,
to avoid trying to interpolate the commit message, which can cause failures.

#### `default` (optional)

A default `config` to run if no paths are matched, the `config` key is not reuired, so a `default` can be written with a `config` attribute or simple just a `command` or `trigger`.

**Example**

```yaml
steps:
- label: "Triggering pipelines"
plugins:
- monorepo-diff#v1.1.0:
diff: "git diff --name-only HEAD~1"
watch:
- path: "bar-service/"
config:
command: "echo deploy-bar"
- path: "foo-service/"
config:
trigger: "deploy-foo-service"
- default:
config: ## <-- Optional
command: echo "Hello, world!"
```

#### `env` (optional)

The object values provided in this configuration will be appended to `env` property of all steps or commands.
Expand All @@ -168,7 +192,7 @@ The object values provided in this configuration will be appended to `env` prope
steps:
- label: "Triggering pipelines"
plugins:
- monorepo-diff#v1.0.1:
- monorepo-diff#v1.1.0:
diff: "git diff --name-only HEAD~1"
watch:
- path: "foo-service/"
Expand All @@ -190,7 +214,7 @@ Add `log_level` property to set the log level. Supported log levels are `debug`
steps:
- label: "Triggering pipelines"
plugins:
- monorepo-diff#v1.0.1:
- monorepo-diff#v1.1.0:
diff: "git diff --name-only HEAD~1"
log_level: "debug" # defaults to "info"
watch:
Expand Down Expand Up @@ -221,7 +245,7 @@ By setting `wait` to `true`, the build will wait until the triggered pipeline bu
steps:
- label: "Triggering pipelines"
plugins:
- monorepo-diff#v1.0.1:
- monorepo-diff#v1.1.0:
diff: "git diff --name-only $(head -n 1 last_successful_build)"
interpolation: false
env:
Expand Down
3 changes: 2 additions & 1 deletion e2e/commands-or-triggers
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
user-service/infrastructure/cloudfront.yaml
user-service/serverless.yaml
world/bin/cli
global/route53.yaml
global/route53.yaml
unfound/file.ps1
2 changes: 0 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ func setupLogger(logLevel string) {
})

ll, err := log.ParseLevel(logLevel)

if err != nil {
ll = log.InfoLevel
}
Expand All @@ -29,7 +28,6 @@ func main() {
log.Debugf("received plugin: \n%v", plugins)

plugin, err := initializePlugin(plugins)

if err != nil {
log.Debug(err)
log.Fatal(err)
Expand Down
15 changes: 11 additions & 4 deletions pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"fmt"
"io/ioutil"
"os"
"reflect"
"strings"
Expand Down Expand Up @@ -94,7 +93,6 @@ func diff(command string) ([]string, error) {
env("SHELL", "bash"),
[]string{"-c", strings.Replace(command, "\n", " ", -1)},
)

if err != nil {
return nil, fmt.Errorf("diff command failed: %v", err)
}
Expand All @@ -104,8 +102,13 @@ func diff(command string) ([]string, error) {

func stepsToTrigger(files []string, watch []WatchConfig) ([]Step, error) {
steps := []Step{}
var defaultStep *Step

for _, w := range watch {
if w.Default != nil {
defaultStep = &w.Step
continue
}
for _, p := range w.Paths {
for _, f := range files {
match, err := matchPath(p, f)
Expand Down Expand Up @@ -135,6 +138,10 @@ func stepsToTrigger(files []string, watch []WatchConfig) ([]Step, error) {
}
}

if len(steps) == 0 && defaultStep != nil {
steps = append(steps, *defaultStep)
}

return dedupSteps(steps), nil
}

Expand Down Expand Up @@ -178,7 +185,7 @@ func dedupSteps(steps []Step) []Step {
}

func generatePipeline(steps []Step, plugin Plugin) (*os.File, bool, error) {
tmp, err := ioutil.TempFile(os.TempDir(), "bmrd-")
tmp, err := os.CreateTemp(os.TempDir(), "bmrd-")
if err != nil {
return nil, false, fmt.Errorf("could not create temporary pipeline file: %v", err)
}
Expand Down Expand Up @@ -220,7 +227,7 @@ func generatePipeline(steps []Step, plugin Plugin) (*os.File, bool, error) {
fmt.Printf("Generated Pipeline:\n%s\n", string(data))
}

if err = ioutil.WriteFile(tmp.Name(), data, 0644); err != nil {
if err = os.WriteFile(tmp.Name(), data, 0o644); err != nil {
return nil, false, fmt.Errorf("could not write step to temporary file: %v", err)
}

Expand Down
39 changes: 28 additions & 11 deletions pipeline_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"io/ioutil"
"os"
"testing"

Expand Down Expand Up @@ -121,7 +120,6 @@ func TestPipelinesToTriggerGetsListOfPipelines(t *testing.T) {
}

func TestPipelinesStepsToTrigger(t *testing.T) {

testCases := map[string]struct {
ChangedFiles []string
WatchConfigs []WatchConfig
Expand Down Expand Up @@ -316,6 +314,28 @@ func TestPipelinesStepsToTrigger(t *testing.T) {
}},
Expected: []Step{},
},
"default configuration": {
ChangedFiles: []string{
"unmatched/file.txt",
},
WatchConfigs: []WatchConfig{
{
Paths: []string{"app/"},
Step: Step{Trigger: "app-deploy"},
},
{
Paths: []string{"test/bin/"},
Step: Step{Command: "echo Make Changes to Bin"},
},
{
Default: struct{}{},
Step: Step{Command: "buildkite-agent pipeline upload other_tests.yml"},
},
},
Expected: []Step{
{Command: "buildkite-agent pipeline upload other_tests.yml"},
},
},
}

for name, tc := range testCases {
Expand Down Expand Up @@ -374,11 +394,10 @@ func TestGeneratePipeline(t *testing.T) {
require.NoError(t, err)
defer os.Remove(pipeline.Name())

got, err := ioutil.ReadFile(pipeline.Name())
got, err := os.ReadFile(pipeline.Name())
require.NoError(t, err)

want :=
`notify:
want := `notify:
- email: [email protected]
- email: [email protected]
- basecamp_campfire: https://basecamp
Expand Down Expand Up @@ -417,8 +436,7 @@ steps:
func TestGeneratePipelineWithNoStepsAndHooks(t *testing.T) {
steps := []Step{}

want :=
`steps:
want := `steps:
- wait: null
- command: echo "hello world"
- command: cat ./file.txt
Expand All @@ -436,7 +454,7 @@ func TestGeneratePipelineWithNoStepsAndHooks(t *testing.T) {
require.NoError(t, err)
defer os.Remove(pipeline.Name())

got, err := ioutil.ReadFile(pipeline.Name())
got, err := os.ReadFile(pipeline.Name())
require.NoError(t, err)

assert.Equal(t, want, string(got))
Expand All @@ -445,8 +463,7 @@ func TestGeneratePipelineWithNoStepsAndHooks(t *testing.T) {
func TestGeneratePipelineWithNoStepsAndNoHooks(t *testing.T) {
steps := []Step{}

want :=
`steps: []
want := `steps: []
`

plugin := Plugin{}
Expand All @@ -455,7 +472,7 @@ func TestGeneratePipelineWithNoStepsAndNoHooks(t *testing.T) {
require.NoError(t, err)
defer os.Remove(pipeline.Name())

got, err := ioutil.ReadFile(pipeline.Name())
got, err := os.ReadFile(pipeline.Name())
require.NoError(t, err)

assert.Equal(t, want, string(got))
Expand Down
27 changes: 20 additions & 7 deletions plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type WatchConfig struct {
Step Step `json:"config"`
RawSkipPath interface{} `json:"skip_path"`
SkipPaths []string
Default interface{} `json:"default"`
}

type Group struct {
Expand Down Expand Up @@ -126,12 +127,24 @@ func (plugin *Plugin) UnmarshalJSON(data []byte) error {
// Path and SkipPath can be string or an array of strings,
// handle both cases and create an array of paths on both.
for i, p := range plugin.Watch {
switch p.RawPath.(type) {
case string:
plugin.Watch[i].Paths = []string{plugin.Watch[i].RawPath.(string)}
case []interface{}:
for _, v := range plugin.Watch[i].RawPath.([]interface{}) {
plugin.Watch[i].Paths = append(plugin.Watch[i].Paths, v.(string))
if p.Default != nil {
plugin.Watch[i].Paths = []string{}
if config, ok := p.Default.(map[string]interface{}); ok && len(config) > 0 {
// Use the default config directly
b, _ := json.Marshal(config)
err := json.Unmarshal(b, &plugin.Watch[i].Step)
if err != nil {
return err
}
}
} else if p.RawPath != nil {
switch p.RawPath.(type) {
case string:
plugin.Watch[i].Paths = []string{plugin.Watch[i].RawPath.(string)}
case []interface{}:
for _, v := range plugin.Watch[i].RawPath.([]interface{}) {
plugin.Watch[i].Paths = append(plugin.Watch[i].Paths, v.(string))
}
}
}

Expand Down Expand Up @@ -321,7 +334,7 @@ func parseEnv(raw interface{}) (map[string]string, error) {
return nil, nil
}

if _, ok := raw.([]interface{}); ok != true {
if _, ok := raw.([]interface{}); !ok {
return nil, errors.New("failed to parse plugin configuration")
}

Expand Down
14 changes: 14 additions & 0 deletions plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ func TestPluginShouldUnmarshallCorrectly(t *testing.T) {
],
"soft_fail": true
}
},
{
"default": {
"command": "buildkite-agent pipeline upload other_tests.yml"
}
}
]
}
Expand Down Expand Up @@ -244,6 +249,15 @@ func TestPluginShouldUnmarshallCorrectly(t *testing.T) {
SoftFail: true,
},
},
{
Default: map[string]interface{}{
"command": "buildkite-agent pipeline upload other_tests.yml",
},
Paths: []string{},
Step: Step{
Command: "buildkite-agent pipeline upload other_tests.yml",
},
},
},
}

Expand Down
4 changes: 2 additions & 2 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ func isString(val interface{}) (string, bool) {
return "", false
}

switch val.(type) {
switch val := val.(type) {
case string:
return val.(string), true
return val, true
}

return "", false
Expand Down

0 comments on commit 3417451

Please sign in to comment.