mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-30 12:20:33 +00:00
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:
parent
978d666eac
commit
2ff91e6a05
18 changed files with 373 additions and 51 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
4
go.mod
|
@ -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
17
go.sum
|
@ -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=
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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='[]'
|
||||
`
|
||||
|
|
|
@ -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='[]'
|
|
@ -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='[]'
|
||||
`
|
||||
|
|
|
@ -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='[]'
|
|
@ -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='[]'
|
||||
`
|
||||
|
|
|
@ -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='[]'
|
Loading…
Reference in a new issue