Add support for path-prefix condition (#174)

Example:
```yaml
when:
  path: '*.md'
```

should match only builds in which the commit added/removed or modified files with the *.md extension

Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
Alex Eftimie 2021-06-28 23:50:35 +02:00 committed by GitHub
parent 978d666eac
commit 2ff91e6a05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 373 additions and 51 deletions

View file

@ -54,12 +54,13 @@ type (
// Commit defines runtime metadata for a commit.
Commit struct {
Sha string `json:"sha,omitempty"`
Ref string `json:"ref,omitempty"`
Refspec string `json:"refspec,omitempty"`
Branch string `json:"branch,omitempty"`
Message string `json:"message,omitempty"`
Author Author `json:"author,omitempty"`
Sha string `json:"sha,omitempty"`
Ref string `json:"ref,omitempty"`
Refspec string `json:"refspec,omitempty"`
Branch string `json:"branch,omitempty"`
Message string `json:"message,omitempty"`
Author Author `json:"author,omitempty"`
ChangedFiles []string `json:"changed_files,omitempty"`
}
// Author defines runtime metadata for a commit author.

View file

@ -3,6 +3,7 @@ package yaml
import (
"fmt"
"path/filepath"
"strings"
libcompose "github.com/docker/libcompose/yaml"
"github.com/woodpecker-ci/woodpecker/cncd/pipeline/pipeline/frontend"
@ -23,6 +24,7 @@ type (
Status Constraint
Matrix ConstraintMap
Local types.BoolTrue
Path ConstraintPath
}
// Constraint defines a runtime constraint.
@ -36,6 +38,13 @@ type (
Include map[string]string
Exclude map[string]string
}
// ConstraintPath defines a runtime constrain for paths
ConstraintPath struct {
Include []string
Exclude []string
IgnoreMessage string `yaml:"ignore_message,omitempty"`
}
)
// Match returns true if all constraints match the given input. If a single
@ -48,7 +57,8 @@ func (c *Constraints) Match(metadata frontend.Metadata) bool {
c.Repo.Match(metadata.Repo.Name) &&
c.Ref.Match(metadata.Curr.Commit.Ref) &&
c.Instance.Match(metadata.Sys.Host) &&
c.Matrix.Match(metadata.Job.Matrix)
c.Matrix.Match(metadata.Job.Matrix) &&
c.Path.Match(metadata.Curr.Commit.ChangedFiles, metadata.Curr.Commit.Message)
}
// Match returns true if the string matches the include patterns and does not
@ -163,3 +173,76 @@ func (c *ConstraintMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
}
return nil
}
// UnmarshalYAML unmarshals the constraint.
func (c *ConstraintPath) UnmarshalYAML(value *yaml.Node) error {
var out1 = struct {
Include libcompose.Stringorslice `yaml:"include,omitempty"`
Exclude libcompose.Stringorslice `yaml:"exclude,omitempty"`
IgnoreMessage string `yaml:"ignore_message,omitempty"`
}{}
var out2 libcompose.Stringorslice
err1 := value.Decode(&out1)
err2 := value.Decode(&out2)
c.Exclude = out1.Exclude
c.IgnoreMessage = out1.IgnoreMessage
c.Include = append(
out1.Include,
out2...,
)
if err1 != nil && err2 != nil {
y, _ := yaml.Marshal(value)
return fmt.Errorf("Could not parse condition: %s", y)
}
return nil
}
// Match returns true if file paths in string slice matches the include and not exclude patterns
// or if commit message contains ignore message.
func (c *ConstraintPath) Match(v []string, message string) bool {
// ignore file pattern matches if the commit message contains a pattern
if len(c.IgnoreMessage) > 0 && strings.Contains(strings.ToLower(message), strings.ToLower(c.IgnoreMessage)) {
return true
}
// always match if there are no commit files (empty commit)
if len(v) == 0 {
return true
}
if len(c.Exclude) > 0 && c.Excludes(v) {
return false
}
if len(c.Include) > 0 && !c.Includes(v) {
return false
}
return true
}
// Includes returns true if the string matches any of the include patterns.
func (c *ConstraintPath) Includes(v []string) bool {
for _, pattern := range c.Include {
for _, file := range v {
if ok, _ := filepath.Match(pattern, file); ok {
return true
}
}
}
return false
}
// Excludes returns true if the string matches any of the exclude patterns.
func (c *ConstraintPath) Excludes(v []string) bool {
for _, pattern := range c.Exclude {
for _, file := range v {
if ok, _ := filepath.Match(pattern, file); ok {
return true
}
}
}
return false
}

View file

@ -150,6 +150,94 @@ func TestConstraint(t *testing.T) {
}
}
func TestConstraintList(t *testing.T) {
testdata := []struct {
conf string
with []string
message string
want bool
}{
{
conf: "",
with: []string{"CHANGELOG.md", "README.md"},
want: true,
},
{
conf: "CHANGELOG.md",
with: []string{"CHANGELOG.md", "README.md"},
want: true,
},
{
conf: "'*.md'",
with: []string{"CHANGELOG.md", "README.md"},
want: true,
},
{
conf: "['*.md']",
with: []string{"CHANGELOG.md", "README.md"},
want: true,
},
{
conf: "{ include: [ README.md ] }",
with: []string{"CHANGELOG.md"},
want: false,
},
{
conf: "{ exclude: [ README.md ] }",
with: []string{"design.md"},
want: true,
},
// include and exclude blocks
{
conf: "{ include: [ '*.md', '*.ini' ], exclude: [ CHANGELOG.md ] }",
with: []string{"README.md"},
want: true,
},
{
conf: "{ include: [ '*.md' ], exclude: [ CHANGELOG.md ] }",
with: []string{"CHANGELOG.md"},
want: false,
},
{
conf: "{ include: [ '*.md' ], exclude: [ CHANGELOG.md ] }",
with: []string{"README.md", "CHANGELOG.md"},
want: false,
},
// commit message ignore matches
{
conf: "{ include: [ README.md ], ignore_message: '[ALL]' }",
with: []string{"CHANGELOG.md"},
message: "Build them [ALL]",
want: true,
},
{
conf: "{ exclude: [ '*.php' ], ignore_message: '[ALL]' }",
with: []string{"myfile.php"},
message: "Build them [ALL]",
want: true,
},
{
conf: "{ ignore_message: '[ALL]' }",
with: []string{},
message: "Build them [ALL]",
want: true,
},
// empty commit
{
conf: "{ include: [ README.md ] }",
with: []string{},
want: true,
},
}
for _, test := range testdata {
c := parseConstraintPath(test.conf)
got, want := c.Match(test.with, test.message), test.want
if got != want {
t.Errorf("Expect %q matches %q is %v", test.with, test.conf, want)
}
}
}
func TestConstraintMap(t *testing.T) {
testdata := []struct {
conf string
@ -371,3 +459,9 @@ func parseConstraintMap(s string) *ConstraintMap {
yaml.Unmarshal([]byte(s), c)
return c
}
func parseConstraintPath(s string) *ConstraintPath {
c := &ConstraintPath{}
yaml.Unmarshal([]byte(s), c)
return c
}

View file

@ -384,6 +384,29 @@ when:
instance: stage.drone.company.com
```
Execute a step only on commit with certain files added/removed/modified:
**NOTE: Feature is only available for Github repositories.**
```diff
when:
path: "src/*"
```
Execute a step only on commit excluding certain files added/removed/modified:
**NOTE: Feature is only available for Github repositories.**
```diff
when:
path:
exclude: [ '*.md', '*.ini' ]
ignore_message: "[ALL]"
```
> Note for `path` conditions: passing `[ALL]` inside the commit message will ignore all path conditions.
#### Failure Execution
Woodpecker uses the container exit code to determine the success or failure status of a build. Non-zero exit codes fail the build and cause the pipeline to immediately exit.

4
go.mod
View file

@ -7,6 +7,8 @@ require (
docker.io/go-docker v1.0.0
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 // indirect
github.com/bmatcuk/doublestar v1.3.4 // indirect
github.com/bradrydzewski/togo v0.0.0-20180401185031-50a0e4726e74 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/dgrijalva/jwt-go v0.0.0-20150904212456-c1da56349675
github.com/dimfeld/httptreemux v5.0.1+incompatible
@ -55,6 +57,8 @@ require (
github.com/stretchr/testify v1.5.1
github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5
github.com/urfave/cli v1.22.4
github.com/vektra/mockery v1.1.2 // indirect
github.com/woodpecker-ci/togo v0.0.0-20180401185031-50a0e4726e74 // indirect
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d

17
go.sum
View file

@ -17,6 +17,10 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/bradrydzewski/togo v0.0.0-20180401185031-50a0e4726e74 h1:fE72rAOk9gpizJL3mNv+Ez+3yt/GCoZWtkKEPLTZvvM=
github.com/bradrydzewski/togo v0.0.0-20180401185031-50a0e4726e74/go.mod h1:+zgWTTgi3saXD5N9SSA+LYteMbFoIJKJ9WEPXoV0jQA=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@ -227,15 +231,23 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vektra/mockery v1.1.2 h1:uc0Yn67rJpjt8U/mAZimdCKn9AeA97BOkjpmtBSlfP4=
github.com/vektra/mockery v1.1.2/go.mod h1:VcfZjKaFOPO+MpN4ZvwPjs4c48lkq1o3Ym8yHZJu0jU=
github.com/woodpecker-ci/togo v0.0.0-20180401185031-50a0e4726e74 h1:q/tWgA3hMWrAQqsS4yfhc0+w4RevBGr9ghem/bFFDRY=
github.com/woodpecker-ci/togo v0.0.0-20180401185031-50a0e4726e74/go.mod h1:lykh/ei/caPO6sv4NN+pqnDTo8kEKhZcnhafN8GhGNs=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -246,6 +258,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -283,7 +296,11 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e h1:ssd5ulOvVWlh4kDSUF2SqzmMeWfjmwDXM+uGw/aQjRE=
golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=

View file

@ -16,38 +16,39 @@ package model
// swagger:model build
type Build struct {
ID int64 `json:"id" meddler:"build_id,pk"`
RepoID int64 `json:"-" meddler:"build_repo_id"`
ConfigID int64 `json:"-" meddler:"build_config_id"`
Number int `json:"number" meddler:"build_number"`
Parent int `json:"parent" meddler:"build_parent"`
Event string `json:"event" meddler:"build_event"`
Status string `json:"status" meddler:"build_status"`
Error string `json:"error" meddler:"build_error"`
Enqueued int64 `json:"enqueued_at" meddler:"build_enqueued"`
Created int64 `json:"created_at" meddler:"build_created"`
Started int64 `json:"started_at" meddler:"build_started"`
Finished int64 `json:"finished_at" meddler:"build_finished"`
Deploy string `json:"deploy_to" meddler:"build_deploy"`
Commit string `json:"commit" meddler:"build_commit"`
Branch string `json:"branch" meddler:"build_branch"`
Ref string `json:"ref" meddler:"build_ref"`
Refspec string `json:"refspec" meddler:"build_refspec"`
Remote string `json:"remote" meddler:"build_remote"`
Title string `json:"title" meddler:"build_title"`
Message string `json:"message" meddler:"build_message"`
Timestamp int64 `json:"timestamp" meddler:"build_timestamp"`
Sender string `json:"sender" meddler:"build_sender"`
Author string `json:"author" meddler:"build_author"`
Avatar string `json:"author_avatar" meddler:"build_avatar"`
Email string `json:"author_email" meddler:"build_email"`
Link string `json:"link_url" meddler:"build_link"`
Signed bool `json:"signed" meddler:"build_signed"` // deprecate
Verified bool `json:"verified" meddler:"build_verified"` // deprecate
Reviewer string `json:"reviewed_by" meddler:"build_reviewer"`
Reviewed int64 `json:"reviewed_at" meddler:"build_reviewed"`
Procs []*Proc `json:"procs,omitempty" meddler:"-"`
Files []*File `json:"files,omitempty" meddler:"-"`
ID int64 `json:"id" meddler:"build_id,pk"`
RepoID int64 `json:"-" meddler:"build_repo_id"`
ConfigID int64 `json:"-" meddler:"build_config_id"`
Number int `json:"number" meddler:"build_number"`
Parent int `json:"parent" meddler:"build_parent"`
Event string `json:"event" meddler:"build_event"`
Status string `json:"status" meddler:"build_status"`
Error string `json:"error" meddler:"build_error"`
Enqueued int64 `json:"enqueued_at" meddler:"build_enqueued"`
Created int64 `json:"created_at" meddler:"build_created"`
Started int64 `json:"started_at" meddler:"build_started"`
Finished int64 `json:"finished_at" meddler:"build_finished"`
Deploy string `json:"deploy_to" meddler:"build_deploy"`
Commit string `json:"commit" meddler:"build_commit"`
Branch string `json:"branch" meddler:"build_branch"`
Ref string `json:"ref" meddler:"build_ref"`
Refspec string `json:"refspec" meddler:"build_refspec"`
Remote string `json:"remote" meddler:"build_remote"`
Title string `json:"title" meddler:"build_title"`
Message string `json:"message" meddler:"build_message"`
Timestamp int64 `json:"timestamp" meddler:"build_timestamp"`
Sender string `json:"sender" meddler:"build_sender"`
Author string `json:"author" meddler:"build_author"`
Avatar string `json:"author_avatar" meddler:"build_avatar"`
Email string `json:"author_email" meddler:"build_email"`
Link string `json:"link_url" meddler:"build_link"`
Signed bool `json:"signed" meddler:"build_signed"` // deprecate
Verified bool `json:"verified" meddler:"build_verified"` // deprecate
Reviewer string `json:"reviewed_by" meddler:"build_reviewer"`
Reviewed int64 `json:"reviewed_at" meddler:"build_reviewed"`
Procs []*Proc `json:"procs,omitempty" meddler:"-"`
Files []*File `json:"files,omitempty" meddler:"-"`
ChangedFiles []string `json:"changed_files,omitempty" meddler:"changed_files,json"`
}
// Trim trims string values that would otherwise exceed

View file

@ -195,18 +195,20 @@ func convertRepoHook(from *webhook) *model.Repo {
// convertPushHook is a helper function used to extract the Build details
// from a push webhook and convert to the common Drone Build structure.
func convertPushHook(from *webhook) *model.Build {
files := getChangedFilesFromWebhook(from)
build := &model.Build{
Event: model.EventPush,
Commit: from.Head.ID,
Ref: from.Ref,
Link: from.Head.URL,
Branch: strings.Replace(from.Ref, "refs/heads/", "", -1),
Message: from.Head.Message,
Email: from.Head.Author.Email,
Avatar: from.Sender.Avatar,
Author: from.Sender.Login,
Remote: from.Repo.CloneURL,
Sender: from.Sender.Login,
Event: model.EventPush,
Commit: from.Head.ID,
Ref: from.Ref,
Link: from.Head.URL,
Branch: strings.Replace(from.Ref, "refs/heads/", "", -1),
Message: from.Head.Message,
Email: from.Head.Author.Email,
Avatar: from.Sender.Avatar,
Author: from.Sender.Login,
Remote: from.Repo.CloneURL,
Sender: from.Sender.Login,
ChangedFiles: files,
}
if len(build.Author) == 0 {
build.Author = from.Head.Author.Username
@ -282,3 +284,14 @@ func convertPullHook(from *webhook, merge bool) *model.Build {
}
return build
}
func getChangedFilesFromWebhook(from *webhook) []string {
var files []string
files = append(files, from.Head.Added...)
files = append(files, from.Head.Removed...)
files = append(files, from.Head.Modified...)
if len(files) == 0 {
files = make([]string, 0)
}
return files
}

View file

@ -35,7 +35,10 @@ const HookPush = `
"name": "baxterthehacker",
"email": "baxterthehacker@users.noreply.github.com",
"username": "baxterthehacker"
}
},
"added": ["CHANGELOG.md"],
"removed": [],
"modified": ["app/controller/application.rb"]
},
"repository": {
"id": 35129377,

View file

@ -60,6 +60,8 @@ func Test_parser(t *testing.T) {
g.Assert(r != nil).IsTrue()
g.Assert(b != nil).IsTrue()
g.Assert(b.Event).Equal(model.EventPush)
expectedFiles := []string{"CHANGELOG.md", "app/controller/application.rb"}
g.Assert(b.ChangedFiles).Equal(expectedFiles)
})
})

View file

@ -37,6 +37,10 @@ type webhook struct {
Email string `json:"email"`
Username string `json:"username"`
} `json:"committer"`
Added []string `json:"added"`
Removed []string `json:"removed"`
Modified []string `json:"modified"`
} `json:"head_commit"`
Sender struct {

View file

@ -319,6 +319,7 @@ func metadataFromStruct(repo *model.Repo, build, last *model.Build, proc *model.
Email: build.Email,
Avatar: build.Avatar,
},
ChangedFiles: build.ChangedFiles,
},
},
Prev: frontend.Build{
@ -341,6 +342,7 @@ func metadataFromStruct(repo *model.Repo, build, last *model.Build, proc *model.
Email: last.Email,
Avatar: last.Avatar,
},
ChangedFiles: last.ChangedFiles,
},
},
Job: frontend.Job{

View file

@ -192,6 +192,14 @@ var migrations = []struct {
name: "update-table-set-repo-fallback-again",
stmt: updateTableSetRepoFallbackAgain,
},
{
name: "add-builds-changed_files-column",
stmt: addBuildsChangedfilesColumn,
},
{
name: "update-builds-set-changed_files",
stmt: updateBuildsSetChangedfiles,
},
}
// Migrate performs the database migration. If the migration fails
@ -725,3 +733,15 @@ UPDATE repos SET repo_fallback='false'
var updateTableSetRepoFallbackAgain = `
UPDATE repos SET repo_fallback='false'
`
//
// 025_add_builds_changed_files_column.sql
//
var addBuildsChangedfilesColumn = `
ALTER TABLE builds ADD COLUMN changed_files TEXT
`
var updateBuildsSetChangedfiles = `
UPDATE builds SET changed_files='[]'
`

View file

@ -0,0 +1,5 @@
-- name: add-builds-changed_files-column
ALTER TABLE builds ADD COLUMN changed_files TEXT
-- name: update-builds-set-changed_files
UPDATE builds SET changed_files='[]'

View file

@ -192,6 +192,14 @@ var migrations = []struct {
name: "update-table-set-repo-fallback-again",
stmt: updateTableSetRepoFallbackAgain,
},
{
name: "add-builds-changed_files-column",
stmt: addBuildsChangedfilesColumn,
},
{
name: "update-builds-set-changed_files",
stmt: updateBuildsSetChangedfiles,
},
}
// Migrate performs the database migration. If the migration fails
@ -727,3 +735,15 @@ UPDATE repos SET repo_fallback='false'
var updateTableSetRepoFallbackAgain = `
UPDATE repos SET repo_fallback='false'
`
//
// 025_add_builds_changed_files_column.sql
//
var addBuildsChangedfilesColumn = `
ALTER TABLE builds ADD COLUMN changed_files TEXT;
`
var updateBuildsSetChangedfiles = `
UPDATE builds SET changed_files='[]'
`

View file

@ -0,0 +1,5 @@
-- name: add-builds-changed_files-column
ALTER TABLE builds ADD COLUMN changed_files TEXT;
-- name: update-builds-set-changed_files
UPDATE builds SET changed_files='[]'

View file

@ -196,6 +196,14 @@ var migrations = []struct {
name: "update-table-set-repo-fallback-again",
stmt: updateTableSetRepoFallbackAgain,
},
{
name: "add-builds-changed_files-column",
stmt: addBuildsChangedfilesColumn,
},
{
name: "update-builds-set-changed_files",
stmt: updateBuildsSetChangedfiles,
},
}
// Migrate performs the database migration. If the migration fails
@ -726,3 +734,15 @@ UPDATE repos SET repo_fallback='false'
var updateTableSetRepoFallbackAgain = `
UPDATE repos SET repo_fallback='false'
`
//
// 025_add_builds_changed_files_column.sql
//
var addBuildsChangedfilesColumn = `
ALTER TABLE builds ADD COLUMN changed_files TEXT
`
var updateBuildsSetChangedfiles = `
UPDATE builds SET changed_files='[]'
`

View file

@ -0,0 +1,5 @@
-- name: add-builds-changed_files-column
ALTER TABLE builds ADD COLUMN changed_files TEXT
-- name: update-builds-set-changed_files
UPDATE builds SET changed_files='[]'