mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-26 02:10:31 +00:00
Add agent tagging / filtering for pipelines (#902)
Officially support labels for pipelines and agents to improve pipeline picking. * add pipeline labels * update, improve docs and add migration * update proto file --- closes #304 & #860
This commit is contained in:
parent
56a55842f6
commit
e79ad00826
44 changed files with 385 additions and 1218 deletions
|
@ -19,6 +19,7 @@ import (
|
|||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -283,7 +284,7 @@ func (r *Runner) Run(ctx context.Context) error {
|
|||
state.Pipeline.Step.Environment = map[string]string{}
|
||||
}
|
||||
|
||||
// TODO: find better way to update this state
|
||||
// TODO: find better way to update this state and move it to pipeline to have the same env in cli-exec
|
||||
state.Pipeline.Step.Environment["CI_MACHINE"] = r.hostname
|
||||
state.Pipeline.Step.Environment["CI_BUILD_STATUS"] = "success"
|
||||
state.Pipeline.Step.Environment["CI_BUILD_STARTED"] = strconv.FormatInt(state.Pipeline.Time, 10)
|
||||
|
@ -293,6 +294,8 @@ func (r *Runner) Run(ctx context.Context) error {
|
|||
state.Pipeline.Step.Environment["CI_JOB_STARTED"] = strconv.FormatInt(state.Pipeline.Time, 10)
|
||||
state.Pipeline.Step.Environment["CI_JOB_FINISHED"] = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
|
||||
state.Pipeline.Step.Environment["CI_SYSTEM_ARCH"] = runtime.GOOS + "/" + runtime.GOARCH
|
||||
|
||||
if state.Pipeline.Error != nil {
|
||||
state.Pipeline.Step.Environment["CI_BUILD_STATUS"] = "failure"
|
||||
state.Pipeline.Step.Environment["CI_JOB_STATUS"] = "failure"
|
||||
|
|
|
@ -206,6 +206,11 @@ func execWithAxis(c *cli.Context, file, repoPath string, axis matrix.Axis) error
|
|||
|
||||
// return the metadata from the cli context.
|
||||
func metadataFromContext(c *cli.Context, axis matrix.Axis) frontend.Metadata {
|
||||
platform := c.String("system-platform")
|
||||
if platform == "" {
|
||||
platform = runtime.GOOS + "/" + runtime.GOARCH
|
||||
}
|
||||
|
||||
return frontend.Metadata{
|
||||
Repo: frontend.Repo{
|
||||
Name: c.String("repo-name"),
|
||||
|
@ -262,9 +267,9 @@ func metadataFromContext(c *cli.Context, axis matrix.Axis) frontend.Metadata {
|
|||
Matrix: axis,
|
||||
},
|
||||
Sys: frontend.System{
|
||||
Name: c.String("system-name"),
|
||||
Link: c.String("system-link"),
|
||||
Arch: c.String("system-arch"),
|
||||
Name: c.String("system-name"),
|
||||
Link: c.String("system-link"),
|
||||
Platform: platform,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,9 +101,8 @@ var flags = []cli.Flag{
|
|||
// metadata parameters
|
||||
//
|
||||
&cli.StringFlag{
|
||||
EnvVars: []string{"CI_SYSTEM_ARCH"},
|
||||
Name: "system-arch",
|
||||
Value: "linux/amd64",
|
||||
EnvVars: []string{"CI_SYSTEM_PLATFORM"},
|
||||
Name: "system-platform",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
EnvVars: []string{"CI_SYSTEM_NAME"},
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
|
@ -39,18 +40,26 @@ import (
|
|||
)
|
||||
|
||||
func loop(c *cli.Context) error {
|
||||
filter := rpc.Filter{
|
||||
Labels: map[string]string{
|
||||
"platform": runtime.GOOS + "/" + runtime.GOARCH,
|
||||
},
|
||||
Expr: c.String("filter"),
|
||||
}
|
||||
|
||||
hostname := c.String("hostname")
|
||||
if len(hostname) == 0 {
|
||||
hostname, _ = os.Hostname()
|
||||
}
|
||||
|
||||
labels := map[string]string{
|
||||
"hostname": hostname,
|
||||
"platform": runtime.GOOS + "/" + runtime.GOARCH,
|
||||
"repo": "*", // allow all repos by default
|
||||
}
|
||||
|
||||
for _, v := range c.StringSlice("filter-labels") {
|
||||
parts := strings.SplitN(v, "=", 2)
|
||||
labels[parts[0]] = parts[1]
|
||||
}
|
||||
|
||||
filter := rpc.Filter{
|
||||
Labels: labels,
|
||||
}
|
||||
|
||||
if c.Bool("pretty") {
|
||||
log.Logger = log.Output(
|
||||
zerolog.ConsoleWriter{
|
||||
|
|
|
@ -72,10 +72,10 @@ var flags = []cli.Flag{
|
|||
Name: "hostname",
|
||||
Usage: "agent hostname",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
EnvVars: []string{"WOODPECKER_FILTER"},
|
||||
&cli.StringSliceFlag{
|
||||
EnvVars: []string{"WOODPECKER_FILTER_LABELS"},
|
||||
Name: "filter",
|
||||
Usage: "filter expression to restrict builds by label",
|
||||
Usage: "List of labels to filter tasks on. An agent must be assigned every tag listed in a task to be selected.",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
EnvVars: []string{"WOODPECKER_MAX_PROCS"},
|
||||
|
|
|
@ -96,26 +96,6 @@ pipeline:
|
|||
+ exclude: [ develop, feature/* ]
|
||||
```
|
||||
|
||||
### `platform`
|
||||
|
||||
To configure your pipeline to only be executed on an agent with a specific platform, you can use the `platform` key.
|
||||
Have a look at the official [go docs](https://go.dev/doc/install/source) for the available platforms. The syntax of the platform is `GOOS/GOARCH` like `linux/arm64` or `linux/amd64`.
|
||||
|
||||
Example:
|
||||
|
||||
Assuming we have two agents, one `arm` and one `amd64`. Previously this pipeline would have executed on **either agent**, as Woodpecker is not fussy about where it runs the pipelines. By setting the following option it will only be executed on an agent with the platform `linux/arm64`.
|
||||
|
||||
```diff
|
||||
+platform: linux/arm64
|
||||
|
||||
pipeline:
|
||||
build:
|
||||
image: golang
|
||||
commands:
|
||||
- go build
|
||||
- go test
|
||||
```
|
||||
|
||||
### Skip Commits
|
||||
|
||||
Woodpecker gives the ability to skip individual commits by adding `[CI SKIP]` to the commit message. Note this is case-insensitive.
|
||||
|
@ -401,6 +381,10 @@ pipeline:
|
|||
|
||||
#### `platform`
|
||||
|
||||
:::note
|
||||
This condition should be used in conjunction with a [matrix](/docs/usage/matrix-pipelines#example-matrix-pipeline-using-multiple-platforms) pipeline as a regular pipeline will only executed by a single agent which only has one arch.
|
||||
:::
|
||||
|
||||
Execute a step for a specific platform:
|
||||
|
||||
```diff
|
||||
|
@ -448,8 +432,8 @@ when:
|
|||
#### `path`
|
||||
|
||||
:::info
|
||||
Path conditions are applied only to **push** and **pull_request** events.
|
||||
It is currently **only available** for GitHub, GitLab.
|
||||
Path conditions are applied only to **push** and **pull_request** events.
|
||||
It is currently **only available** for GitHub, GitLab.
|
||||
Gitea only support **push** at the moment ([go-gitea/gitea#18228](https://github.com/go-gitea/gitea/pull/18228)).
|
||||
:::
|
||||
|
||||
|
@ -586,7 +570,52 @@ git clone https://github.com/octocat/hello-world \
|
|||
|
||||
Woodpecker has integrated support for matrix builds. Woodpecker executes a separate build task for each combination in the matrix, allowing you to build and test a single commit against multiple configurations.
|
||||
|
||||
For more details check the [matrix build docs](/docs/usage/matrix-builds/).
|
||||
For more details check the [matrix build docs](/docs/usage/matrix-pipelines/).
|
||||
|
||||
## `platform`
|
||||
|
||||
To configure your pipeline to only be executed on an agent with a specific platform, you can use the `platform` key.
|
||||
Have a look at the official [go docs](https://go.dev/doc/install/source) for the available platforms. The syntax of the platform is `GOOS/GOARCH` like `linux/arm64` or `linux/amd64`.
|
||||
|
||||
Example:
|
||||
|
||||
Assuming we have two agents, one `arm` and one `amd64`. Previously this pipeline would have executed on **either agent**, as Woodpecker is not fussy about where it runs the pipelines. By setting the following option it will only be executed on an agent with the platform `linux/arm64`.
|
||||
|
||||
```diff
|
||||
+platform: linux/arm64
|
||||
|
||||
pipeline:
|
||||
build:
|
||||
image: golang
|
||||
commands:
|
||||
- go build
|
||||
- go test
|
||||
```
|
||||
|
||||
## `labels`
|
||||
|
||||
You can set labels for your pipeline to select an agent to execute the pipeline on. An agent will pick up and run a pipeline when **every** label assigned to a pipeline matches the agents labels.
|
||||
|
||||
To set additional agent labels check the [agent configuration options](/docs/administration/agent-config#woodpecker_filter_labels). Agents will have at least three default labels: `platform=agent-os/agent-arch`, `hostname=my-agent` and `repo=*`. Agents can use a `*` as a wildcard for a label. For example `repo=*` will match every repo.
|
||||
|
||||
Pipeline labels with an empty value will be ignored.
|
||||
By default each pipeline has at least the `repo=your-user/your-repo-name` label. If you have set the [platform attribute](#platform) for your pipeline it will have a label like `platform=your-os/your-arch` as well.
|
||||
|
||||
You can add additional labels as a key value map:
|
||||
|
||||
```diff
|
||||
+labels:
|
||||
+ location: europe # only agents with `location=europe` or `location=*` will be used
|
||||
+ weather: sun
|
||||
+ hostname: "" # this label will be ignored as it is empty
|
||||
|
||||
pipeline:
|
||||
build:
|
||||
image: golang
|
||||
commands:
|
||||
- go build
|
||||
- go test
|
||||
```
|
||||
|
||||
## `clone`
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Matrix builds
|
||||
# Matrix pipelines
|
||||
|
||||
Woodpecker has integrated support for matrix builds. Woodpecker executes a separate build task for each combination in the matrix, allowing you to build and test a single commit against multiple configurations.
|
||||
Woodpecker has integrated support for matrix pipeline. Woodpecker executes a separate pipeline for each combination in the matrix, allowing you to build and test a single commit against multiple configurations.
|
||||
|
||||
Example matrix definition:
|
||||
|
||||
|
@ -33,6 +33,15 @@ matrix:
|
|||
Matrix variables are interpolated in the yaml using the `${VARIABLE}` syntax, before the yaml is parsed. This is an example yaml file before interpolating matrix parameters:
|
||||
|
||||
```yaml
|
||||
matrix:
|
||||
GO_VERSION:
|
||||
- 1.4
|
||||
- 1.3
|
||||
DATABASE:
|
||||
- mysql:5.5
|
||||
- mysql:6.5
|
||||
- mariadb:10.1
|
||||
|
||||
pipeline:
|
||||
build:
|
||||
image: golang:${GO_VERSION}
|
||||
|
@ -44,15 +53,6 @@ pipeline:
|
|||
services:
|
||||
database:
|
||||
image: ${DATABASE}
|
||||
|
||||
matrix:
|
||||
GO_VERSION:
|
||||
- 1.4
|
||||
- 1.3
|
||||
DATABASE:
|
||||
- mysql:5.5
|
||||
- mysql:6.5
|
||||
- mariadb:10.1
|
||||
```
|
||||
|
||||
Example YAML file after injecting the matrix parameters:
|
||||
|
@ -78,36 +78,61 @@ services:
|
|||
|
||||
## Examples
|
||||
|
||||
Example matrix build based on Docker image tag:
|
||||
### Example matrix pipeline based on Docker image tag
|
||||
|
||||
```yaml
|
||||
matrix:
|
||||
TAG:
|
||||
- 1.7
|
||||
- 1.8
|
||||
- latest
|
||||
|
||||
pipeline:
|
||||
build:
|
||||
image: golang:${TAG}
|
||||
commands:
|
||||
- go build
|
||||
- go test
|
||||
|
||||
matrix:
|
||||
TAG:
|
||||
- 1.7
|
||||
- 1.8
|
||||
- latest
|
||||
```
|
||||
|
||||
Example matrix build based on Docker image:
|
||||
### Example matrix pipeline based on container image
|
||||
|
||||
```yaml
|
||||
matrix:
|
||||
IMAGE:
|
||||
- golang:1.7
|
||||
- golang:1.8
|
||||
- golang:latest
|
||||
|
||||
pipeline:
|
||||
build:
|
||||
image: ${IMAGE}
|
||||
commands:
|
||||
- go build
|
||||
- go test
|
||||
|
||||
matrix:
|
||||
IMAGE:
|
||||
- golang:1.7
|
||||
- golang:1.8
|
||||
- golang:latest
|
||||
```
|
||||
|
||||
### Example matrix pipeline using multiple platforms
|
||||
|
||||
```yaml
|
||||
matrix:
|
||||
platform:
|
||||
- linux/amd64
|
||||
- linux/arm64
|
||||
|
||||
platform: ${platform}
|
||||
|
||||
pipeline:
|
||||
test:
|
||||
image: alpine
|
||||
commands:
|
||||
- echo "I am running on ${platform}"
|
||||
|
||||
test-arm-only:
|
||||
image: alpine
|
||||
commands:
|
||||
- echo "I am running on ${platform}"
|
||||
- echo "Arm is cool!"
|
||||
when:
|
||||
platform: linux/arm*
|
||||
```
|
|
@ -12,7 +12,6 @@ services:
|
|||
environment:
|
||||
+ - WOODPECKER_SERVER=localhost:9000
|
||||
+ - WOODPECKER_AGENT_SECRET="your-shared-secret-goes-here"
|
||||
|
||||
```
|
||||
|
||||
The following are automatically set and can be overridden:
|
||||
|
@ -37,45 +36,6 @@ services:
|
|||
+ - WOODPECKER_MAX_PROCS=4
|
||||
```
|
||||
|
||||
## Filtering agents
|
||||
|
||||
When building your pipelines as long as you have set the platform or filter, builds can be made to only run code on certain agents.
|
||||
|
||||
```
|
||||
- WOODPECKER_HOSTNAME=mycompany-ci-01.example.com
|
||||
- WOODPECKER_FILTER=
|
||||
```
|
||||
|
||||
### Filter on Platform
|
||||
|
||||
Only want certain pipelines or steps to run on certain agents with specific platforms? Such as arm vs amd64?
|
||||
|
||||
```yaml
|
||||
# .woodpecker.yml
|
||||
pipeline:
|
||||
build:
|
||||
image: golang
|
||||
commands:
|
||||
- go build
|
||||
- go test
|
||||
when:
|
||||
platform: linux/amd64
|
||||
|
||||
|
||||
testing:
|
||||
image: golang
|
||||
commands:
|
||||
- go build
|
||||
- go test
|
||||
when:
|
||||
platform: linux/arm*
|
||||
|
||||
|
||||
```
|
||||
|
||||
See [Conditionals Pipeline](/docs/usage/pipeline-syntax#step-when---conditional-execution) syntax for more
|
||||
|
||||
|
||||
## All agent configuration options
|
||||
|
||||
Here is the full list of configuration options and their default variables.
|
||||
|
@ -125,6 +85,11 @@ Configures the agent hostname.
|
|||
|
||||
Configures the number of parallel builds.
|
||||
|
||||
### `WOODPECKER_FILTER_LABELS`
|
||||
> Default: empty
|
||||
|
||||
Configures labels to filter pipeline pick up. Use a list of key-value pairs like `key=value,second-key=*`. `*` can be used as a wildcard. By default agents provide three additional labels `platform=os/arch`, `hostname=my-agent` and `repo=*` which can be overwritten if needed. To learn how labels work check out the [pipeline syntax page](/docs/usage/pipeline-syntax#labels).
|
||||
|
||||
### `WOODPECKER_HEALTHCHECK`
|
||||
> Default: `true`
|
||||
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
Some versions need some changes to the server configuration or the pipeline configuration files.
|
||||
|
||||
## 1.0.0
|
||||
|
||||
- Refactored support of old agent filter labels and expression. Learn how to use the new [filter](/docs/usage/pipeline-syntax#labels).
|
||||
- Renamed step environment variable `CI_SYSTEM_ARCH` to `CI_SYSTEM_PLATFORM`. Same applies for the cli exec variable.
|
||||
|
||||
## 0.15.0
|
||||
|
||||
- Default value for custom pipeline path is now empty / un-set which results in following resolution:
|
||||
|
|
1
go.mod
1
go.mod
|
@ -44,7 +44,6 @@ require (
|
|||
github.com/tevino/abool v1.2.0
|
||||
github.com/ugorji/go v1.2.7 // indirect
|
||||
github.com/urfave/cli/v2 v2.5.1
|
||||
github.com/woodpecker-ci/expr v0.0.0-20210628233344-164b8b3d0915
|
||||
github.com/xanzy/go-gitlab v0.64.0
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
|
|
2
go.sum
2
go.sum
|
@ -1413,8 +1413,6 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17
|
|||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
||||
github.com/woodpecker-ci/expr v0.0.0-20210628233344-164b8b3d0915 h1:9zBOoKSR9CBeYoKQv6LFIuImg8lorCjh8XzK72bJMRg=
|
||||
github.com/woodpecker-ci/expr v0.0.0-20210628233344-164b8b3d0915/go.mod h1:PbzlZ93HrA1cf16OUP1vckAPq57gtF+ccnwZeDkmC9s=
|
||||
github.com/xanzy/go-gitlab v0.64.0 h1:rMgQdW9S1w3qvNAH2LYpFd2xh7KNLk+JWJd7sorNuTc=
|
||||
github.com/xanzy/go-gitlab v0.64.0/go.mod h1:F0QEXwmqiBUxCgJm8fE9S+1veX4XC9Z4cfaAbqwk4YM=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
|
|
|
@ -87,11 +87,11 @@ type (
|
|||
|
||||
// System defines runtime metadata for a ci/cd system.
|
||||
System struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
Link string `json:"link,omitempty"`
|
||||
Arch string `json:"arch,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
Link string `json:"link,omitempty"`
|
||||
Platform string `json:"arch,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -179,11 +179,13 @@ func (m *Metadata) Environ() map[string]string {
|
|||
"CI_PREV_BUILD_STARTED": strconv.FormatInt(m.Prev.Started, 10),
|
||||
"CI_PREV_BUILD_FINISHED": strconv.FormatInt(m.Prev.Finished, 10),
|
||||
|
||||
"CI_SYSTEM_NAME": m.Sys.Name,
|
||||
"CI_SYSTEM_LINK": m.Sys.Link,
|
||||
"CI_SYSTEM_HOST": m.Sys.Host,
|
||||
"CI_SYSTEM_ARCH": m.Sys.Arch,
|
||||
"CI_SYSTEM_VERSION": version.Version,
|
||||
"CI_SYSTEM_NAME": m.Sys.Name,
|
||||
"CI_SYSTEM_LINK": m.Sys.Link,
|
||||
"CI_SYSTEM_HOST": m.Sys.Host,
|
||||
"CI_SYSTEM_PLATFORM": m.Sys.Platform, // will be set by pipeline platform option or by agent
|
||||
"CI_SYSTEM_VERSION": version.Version,
|
||||
|
||||
"CI_SYSTEM_ARCH": m.Sys.Platform, // TODO: remove after next version
|
||||
}
|
||||
if m.Curr.Event == EventTag {
|
||||
params["CI_COMMIT_TAG"] = strings.TrimPrefix(m.Curr.Commit.Ref, "refs/tags/")
|
||||
|
@ -198,5 +200,5 @@ func (m *Metadata) Environ() map[string]string {
|
|||
var pullRegexp = regexp.MustCompile(`\d+`)
|
||||
|
||||
func (m *Metadata) SetPlatform(platform string) {
|
||||
m.Sys.Arch = platform
|
||||
m.Sys.Platform = platform
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {
|
|||
})
|
||||
|
||||
// create a default network
|
||||
if strings.HasPrefix(c.metadata.Sys.Arch, windowsPrefix) {
|
||||
if strings.HasPrefix(c.metadata.Sys.Platform, windowsPrefix) {
|
||||
config.Networks = append(config.Networks, &backend.Network{
|
||||
Name: fmt.Sprintf("%s_default", c.prefix),
|
||||
Driver: networkDriverNAT,
|
||||
|
|
|
@ -78,7 +78,7 @@ func (c *Compiler) createProcess(name string, container *yaml.Container, section
|
|||
}
|
||||
|
||||
if len(container.Commands) != 0 {
|
||||
if c.metadata.Sys.Arch == "windows/amd64" {
|
||||
if c.metadata.Sys.Platform == "windows/amd64" {
|
||||
entrypoint = []string{"powershell", "-noprofile", "-noninteractive", "-command"}
|
||||
command = []string{"[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex"}
|
||||
environment["CI_SCRIPT"] = generateScriptWindows(container.Commands)
|
||||
|
|
|
@ -50,7 +50,7 @@ type (
|
|||
// Match returns true if all constraints match the given input. If a single
|
||||
// constraint fails a false value is returned.
|
||||
func (c *Constraints) Match(metadata frontend.Metadata) bool {
|
||||
match := c.Platform.Match(metadata.Sys.Arch) &&
|
||||
match := c.Platform.Match(metadata.Sys.Platform) &&
|
||||
c.Environment.Match(metadata.Curr.Target) &&
|
||||
c.Event.Match(metadata.Curr.Event) &&
|
||||
c.Repo.Match(metadata.Repo.Name) &&
|
||||
|
|
|
@ -440,12 +440,12 @@ func TestConstraints(t *testing.T) {
|
|||
// platform constraint
|
||||
{
|
||||
conf: "{ platform: linux/amd64 }",
|
||||
with: frontend.Metadata{Sys: frontend.System{Arch: "linux/amd64"}},
|
||||
with: frontend.Metadata{Sys: frontend.System{Platform: "linux/amd64"}},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "{ repo: linux/amd64 }",
|
||||
with: frontend.Metadata{Sys: frontend.System{Arch: "windows/amd64"}},
|
||||
with: frontend.Metadata{Sys: frontend.System{Platform: "windows/amd64"}},
|
||||
want: false,
|
||||
},
|
||||
// instance constraint
|
||||
|
|
|
@ -40,7 +40,6 @@ func (c *client) Next(ctx context.Context, f Filter) (*Pipeline, error) {
|
|||
var err error
|
||||
req := new(proto.NextRequest)
|
||||
req.Filter = new(proto.Filter)
|
||||
req.Filter.Expr = f.Expr
|
||||
req.Filter.Labels = f.Labels
|
||||
for {
|
||||
res, err = c.client.Next(ctx, req)
|
||||
|
|
|
@ -10,7 +10,6 @@ type (
|
|||
// Filter defines filters for fetching items from the queue.
|
||||
Filter struct {
|
||||
Labels map[string]string `json:"labels"`
|
||||
Expr string `json:"expr"`
|
||||
}
|
||||
|
||||
// State defines the pipeline state.
|
||||
|
|
|
@ -17,6 +17,7 @@ package proto
|
|||
//go:generate protoc --go_out=paths=source_relative:. woodpecker.proto
|
||||
//go:generate protoc --go-grpc_out=paths=source_relative:. woodpecker.proto
|
||||
|
||||
// get needed binary's:
|
||||
// go install google.golang.org/protobuf/cmd/protoc-gen-go
|
||||
// go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
|
||||
// install protoc: https://grpc.io/docs/protoc-installation/
|
||||
// and get needed binary's:
|
||||
// go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||
// go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.18.1
|
||||
// protoc-gen-go v1.28.0
|
||||
// protoc v3.12.4
|
||||
// source: woodpecker.proto
|
||||
|
||||
package proto
|
||||
|
@ -328,7 +328,6 @@ type Filter struct {
|
|||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Labels map[string]string `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
Expr string `protobuf:"bytes,2,opt,name=expr,proto3" json:"expr,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Filter) Reset() {
|
||||
|
@ -370,13 +369,6 @@ func (x *Filter) GetLabels() map[string]string {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (x *Filter) GetExpr() string {
|
||||
if x != nil {
|
||||
return x.Expr
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Pipeline struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
@ -1069,98 +1061,96 @@ var file_woodpecker_proto_rawDesc = []byte{
|
|||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x10, 0x0a,
|
||||
0x03, 0x70, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x70, 0x6f, 0x73, 0x12,
|
||||
0x10, 0x0a, 0x03, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x75,
|
||||
0x74, 0x22, 0x8a, 0x01, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x06,
|
||||
0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x4c, 0x61, 0x62, 0x65,
|
||||
0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12,
|
||||
0x12, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x65,
|
||||
0x78, 0x70, 0x72, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74,
|
||||
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4e,
|
||||
0x0a, 0x08, 0x50, 0x69, 0x70, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69,
|
||||
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d,
|
||||
0x65, 0x6f, 0x75, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x2e,
|
||||
0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x93,
|
||||
0x01, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48,
|
||||
0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3a, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76,
|
||||
0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b,
|
||||
0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e,
|
||||
0x47, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49,
|
||||
0x4e, 0x47, 0x10, 0x02, 0x22, 0x34, 0x0a, 0x0b, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x74,
|
||||
0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x38, 0x0a, 0x09, 0x4e, 0x65,
|
||||
0x78, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x2b, 0x0a, 0x08, 0x70, 0x69, 0x70, 0x65, 0x6c,
|
||||
0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x2e, 0x50, 0x69, 0x70, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x52, 0x08, 0x70, 0x69, 0x70, 0x65,
|
||||
0x6c, 0x69, 0x6e, 0x65, 0x22, 0x41, 0x0a, 0x0b, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65,
|
||||
0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x1d, 0x0a, 0x0b, 0x57, 0x61, 0x69, 0x74, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x41, 0x0a, 0x0b, 0x44, 0x6f, 0x6e, 0x65, 0x52, 0x65,
|
||||
0x74, 0x22, 0x76, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x06, 0x6c,
|
||||
0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c,
|
||||
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39,
|
||||
0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
|
||||
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4e, 0x0a, 0x08, 0x50, 0x69, 0x70,
|
||||
0x65, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x2e, 0x0a, 0x12, 0x48, 0x65, 0x61,
|
||||
0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x13, 0x48, 0x65,
|
||||
0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x40, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0e, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68,
|
||||
0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61,
|
||||
0x74, 0x75, 0x73, 0x22, 0x3a, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74,
|
||||
0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10,
|
||||
0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0f,
|
||||
0x0a, 0x0b, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x22,
|
||||
0x34, 0x0a, 0x0b, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25,
|
||||
0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66,
|
||||
0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x38, 0x0a, 0x09, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x65, 0x70,
|
||||
0x6c, 0x79, 0x12, 0x2b, 0x0a, 0x08, 0x70, 0x69, 0x70, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x69, 0x70,
|
||||
0x65, 0x6c, 0x69, 0x6e, 0x65, 0x52, 0x08, 0x70, 0x69, 0x70, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x22,
|
||||
0x41, 0x0a, 0x0b, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e,
|
||||
0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22,
|
||||
0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61,
|
||||
0x74, 0x65, 0x22, 0x1d, 0x0a, 0x0b, 0x57, 0x61, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
|
||||
0x64, 0x22, 0x41, 0x0a, 0x0b, 0x44, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
|
||||
0x12, 0x22, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73,
|
||||
0x74, 0x61, 0x74, 0x65, 0x22, 0x1f, 0x0a, 0x0d, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61,
|
||||
0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x1f, 0x0a, 0x0d, 0x45, 0x78, 0x74,
|
||||
0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x40, 0x0a, 0x0d, 0x55, 0x70,
|
||||
0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x04, 0x66,
|
||||
0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x43, 0x0a, 0x0d,
|
||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a,
|
||||
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a,
|
||||
0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74,
|
||||
0x65, 0x22, 0x3d, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12,
|
||||
0x1f, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x69, 0x6e, 0x65, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65,
|
||||
0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0xfa, 0x02, 0x0a, 0x0a, 0x57, 0x6f,
|
||||
0x6f, 0x64, 0x70, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x04, 0x4e, 0x65, 0x78, 0x74,
|
||||
0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4e, 0x65, 0x78,
|
||||
0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x2a, 0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74,
|
||||
0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70,
|
||||
0x74, 0x79, 0x22, 0x00, 0x12, 0x2a, 0x0a, 0x04, 0x57, 0x61, 0x69, 0x74, 0x12, 0x12, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x57, 0x61, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00,
|
||||
0x12, 0x2a, 0x0a, 0x04, 0x44, 0x6f, 0x6e, 0x65, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x2e, 0x44, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x06,
|
||||
0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45,
|
||||
0x78, 0x74, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x06,
|
||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55,
|
||||
0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x06,
|
||||
0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55,
|
||||
0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x28, 0x0a, 0x03,
|
||||
0x4c, 0x6f, 0x67, 0x12, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x6f, 0x67, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45,
|
||||
0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x32, 0x48, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68,
|
||||
0x12, 0x3e, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61,
|
||||
0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77,
|
||||
0x6f, 0x6f, 0x64, 0x70, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x2d, 0x63, 0x69, 0x2f, 0x77, 0x6f, 0x6f,
|
||||
0x64, 0x70, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x2f, 0x70, 0x69, 0x70, 0x65, 0x6c, 0x69, 0x6e, 0x65,
|
||||
0x2f, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x40, 0x0a, 0x0d, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c,
|
||||
0x65, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x43, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
|
||||
0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x3d, 0x0a, 0x0a,
|
||||
0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x04, 0x6c, 0x69,
|
||||
0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x2e, 0x4c, 0x69, 0x6e, 0x65, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x07, 0x0a, 0x05, 0x45,
|
||||
0x6d, 0x70, 0x74, 0x79, 0x32, 0xfa, 0x02, 0x0a, 0x0a, 0x57, 0x6f, 0x6f, 0x64, 0x70, 0x65, 0x63,
|
||||
0x6b, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x04, 0x4e, 0x65, 0x78, 0x74, 0x12, 0x12, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x65, 0x70, 0x6c,
|
||||
0x79, 0x22, 0x00, 0x12, 0x2a, 0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x12, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12,
|
||||
0x2a, 0x0a, 0x04, 0x57, 0x61, 0x69, 0x74, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
|
||||
0x57, 0x61, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2a, 0x0a, 0x04, 0x44,
|
||||
0x6f, 0x6e, 0x65, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x6f, 0x6e, 0x65,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
|
||||
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x06, 0x45, 0x78, 0x74, 0x65, 0x6e,
|
||||
0x64, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
|
||||
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
|
||||
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x06, 0x55, 0x70, 0x6c, 0x6f, 0x61,
|
||||
0x64, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
|
||||
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x28, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x11,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22,
|
||||
0x00, 0x32, 0x48, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x3e, 0x0a, 0x05, 0x43,
|
||||
0x68, 0x65, 0x63, 0x6b, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61,
|
||||
0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68,
|
||||
0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x38, 0x5a, 0x36, 0x67,
|
||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x6f, 0x6f, 0x64, 0x70, 0x65,
|
||||
0x63, 0x6b, 0x65, 0x72, 0x2d, 0x63, 0x69, 0x2f, 0x77, 0x6f, 0x6f, 0x64, 0x70, 0x65, 0x63, 0x6b,
|
||||
0x65, 0x72, 0x2f, 0x70, 0x69, 0x70, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x2f, 0x72, 0x70, 0x63, 0x2f,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -31,7 +31,6 @@ message Line {
|
|||
|
||||
message Filter {
|
||||
map<string, string> labels = 1;
|
||||
string expr = 2;
|
||||
}
|
||||
|
||||
message Pipeline {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.1.0
|
||||
// - protoc v3.18.1
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.12.4
|
||||
// source: woodpecker.proto
|
||||
|
||||
package proto
|
||||
|
|
10
pipeline/schema/.woodpecker/test-labels.yml
Normal file
10
pipeline/schema/.woodpecker/test-labels.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
labels:
|
||||
location: europe
|
||||
weather: sun
|
||||
hostname: ""
|
||||
|
||||
pipeline:
|
||||
build:
|
||||
image: golang:latest
|
||||
commands:
|
||||
- go test
|
7
pipeline/schema/.woodpecker/test-platform.yml
Normal file
7
pipeline/schema/.woodpecker/test-platform.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
platform: linux/amd64
|
||||
|
||||
pipeline:
|
||||
build:
|
||||
image: golang:latest
|
||||
commands:
|
||||
- go test
|
|
@ -17,6 +17,8 @@
|
|||
"services": { "$ref": "#/definitions/services" },
|
||||
"workspace": { "$ref": "#/definitions/workspace" },
|
||||
"matrix": { "$ref": "#/definitions/matrix" },
|
||||
"platform": { "$ref": "#/definitions/platform" },
|
||||
"labels": { "$ref": "#/definitions/labels" },
|
||||
"skip_clone": { "type": "boolean" },
|
||||
"depends_on": {
|
||||
"type": "array",
|
||||
|
@ -270,7 +272,7 @@
|
|||
"oneOf": [
|
||||
{ "type": "string" },
|
||||
{
|
||||
"type" :"array",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
|
@ -311,7 +313,7 @@
|
|||
"additionalProperties": true
|
||||
},
|
||||
"matrix": {
|
||||
"description": "TODO Read more: https://woodpecker-ci.org/docs/usage/matrix-builds",
|
||||
"description": "Execute pipeline for each matrix combination. Read more: https://woodpecker-ci.org/docs/usage/matrix-pipelines",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"include": {
|
||||
|
@ -329,6 +331,18 @@
|
|||
},
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"platform": {
|
||||
"description": "Configures the platform the pipeline will be executed on. Read more: https://woodpecker-ci.org/docs/usage/pipeline-syntax#platform",
|
||||
"type": "string",
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {
|
||||
"description": "Configures the labels used for the agent selection. Read more: https://woodpecker-ci.org/docs/usage/pipeline-syntax#clone",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": ["boolean", "string", "number"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,14 @@ func TestSchema(t *testing.T) {
|
|||
name: "Workspace",
|
||||
testFile: ".woodpecker/test-workspace.yml",
|
||||
},
|
||||
{
|
||||
name: "Platform",
|
||||
testFile: ".woodpecker/test-platform.yml",
|
||||
},
|
||||
{
|
||||
name: "Labels",
|
||||
testFile: ".woodpecker/test-labels.yml",
|
||||
},
|
||||
{
|
||||
name: "Broken Config",
|
||||
testFile: ".woodpecker/test-broken.yml",
|
||||
|
|
|
@ -15,36 +15,30 @@
|
|||
package grpc
|
||||
|
||||
import (
|
||||
"github.com/woodpecker-ci/expr"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/pipeline/rpc"
|
||||
"github.com/woodpecker-ci/woodpecker/server/queue"
|
||||
)
|
||||
|
||||
func createFilterFunc(filter rpc.Filter) (queue.Filter, error) {
|
||||
var st *expr.Selector
|
||||
var err error
|
||||
|
||||
if filter.Expr != "" {
|
||||
st, err = expr.ParseString(filter.Expr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func createFilterFunc(agentFilter rpc.Filter) (queue.FilterFn, error) {
|
||||
return func(task *queue.Task) bool {
|
||||
if st != nil {
|
||||
match, _ := st.Eval(expr.NewRow(task.Labels))
|
||||
return match
|
||||
}
|
||||
|
||||
for k, v := range filter.Labels {
|
||||
// if platform is not set ignore that filter
|
||||
if k == "platform" && task.Labels[k] == "" {
|
||||
for taskLabel, taskLabelValue := range task.Labels {
|
||||
// if a task label is empty it will be ignored
|
||||
if taskLabelValue == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if task.Labels[k] != v {
|
||||
agentLabelValue, ok := agentFilter.Labels[taskLabel]
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
// if agent label has a wildcard
|
||||
if agentLabelValue == "*" {
|
||||
continue
|
||||
}
|
||||
|
||||
if taskLabelValue != agentLabelValue {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,72 +26,70 @@ import (
|
|||
func TestCreateFilterFunc(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type filterTests struct {
|
||||
tsk queue.Task
|
||||
exp bool
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
struc rpc.Filter
|
||||
ft []filterTests
|
||||
}{{
|
||||
struc: rpc.Filter{},
|
||||
ft: []filterTests{{
|
||||
tsk: queue.Task{
|
||||
Labels: map[string]string{"platform": "", "repo": "test/woodpecker"},
|
||||
name string
|
||||
agentLabels map[string]string
|
||||
task queue.Task
|
||||
exp bool
|
||||
}{
|
||||
{
|
||||
name: "agent with missing labels",
|
||||
agentLabels: map[string]string{"repo": "test/woodpecker"},
|
||||
task: queue.Task{
|
||||
Labels: map[string]string{"platform": "linux/amd64", "repo": "test/woodpecker"},
|
||||
},
|
||||
exp: false,
|
||||
},
|
||||
{
|
||||
name: "agent with wrong labels",
|
||||
agentLabels: map[string]string{"platform": "linux/arm64"},
|
||||
task: queue.Task{
|
||||
Labels: map[string]string{"platform": "linux/amd64"},
|
||||
},
|
||||
exp: false,
|
||||
},
|
||||
{
|
||||
name: "agent with correct labels",
|
||||
agentLabels: map[string]string{"platform": "linux/amd64", "location": "europe"},
|
||||
task: queue.Task{
|
||||
Labels: map[string]string{"platform": "linux/amd64", "location": "europe"},
|
||||
},
|
||||
exp: true,
|
||||
}, {
|
||||
tsk: queue.Task{
|
||||
},
|
||||
{
|
||||
name: "agent with additional labels",
|
||||
agentLabels: map[string]string{"platform": "linux/amd64", "location": "europe"},
|
||||
task: queue.Task{
|
||||
Labels: map[string]string{"platform": "linux/amd64"},
|
||||
},
|
||||
exp: true,
|
||||
},
|
||||
{
|
||||
name: "agent with wildcard label",
|
||||
agentLabels: map[string]string{"platform": "linux/amd64", "location": "*"},
|
||||
task: queue.Task{
|
||||
Labels: map[string]string{"platform": "linux/amd64", "location": "america"},
|
||||
},
|
||||
exp: true,
|
||||
},
|
||||
{
|
||||
name: "agent with platform label and task without",
|
||||
agentLabels: map[string]string{"platform": "linux/amd64"},
|
||||
task: queue.Task{
|
||||
Labels: map[string]string{"platform": ""},
|
||||
},
|
||||
exp: true,
|
||||
}},
|
||||
}, {
|
||||
struc: rpc.Filter{
|
||||
Labels: map[string]string{"platform": "abc"},
|
||||
},
|
||||
ft: []filterTests{{
|
||||
tsk: queue.Task{
|
||||
Labels: map[string]string{"platform": "def"},
|
||||
},
|
||||
exp: false,
|
||||
}, {
|
||||
tsk: queue.Task{
|
||||
Labels: map[string]string{"platform": ""},
|
||||
},
|
||||
exp: true,
|
||||
}},
|
||||
}, {
|
||||
struc: rpc.Filter{
|
||||
Expr: "platform = 'abc' OR repo = 'test/woodpecker'",
|
||||
},
|
||||
ft: []filterTests{{
|
||||
tsk: queue.Task{
|
||||
Labels: map[string]string{"platform": "", "repo": "test/woodpecker"},
|
||||
},
|
||||
exp: true,
|
||||
}, {
|
||||
tsk: queue.Task{
|
||||
Labels: map[string]string{"platform": "abc", "repo": "else"},
|
||||
},
|
||||
exp: true,
|
||||
}, {
|
||||
tsk: queue.Task{
|
||||
Labels: map[string]string{"platform": "also", "repo": "else"},
|
||||
},
|
||||
exp: false,
|
||||
}},
|
||||
}}
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
fn, err := createFilterFunc(test.struc)
|
||||
if !assert.NoError(t, err) {
|
||||
t.Fail()
|
||||
}
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
fn, err := createFilterFunc(rpc.Filter{Labels: test.agentLabels})
|
||||
if !assert.NoError(t, err) {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
for _, ft := range test.ft {
|
||||
assert.EqualValues(t, ft.exp, fn(&ft.tsk))
|
||||
}
|
||||
assert.EqualValues(t, test.exp, fn(&test.task))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ type RPC struct {
|
|||
}
|
||||
|
||||
// Next implements the rpc.Next function
|
||||
func (s *RPC) Next(c context.Context, filter rpc.Filter) (*rpc.Pipeline, error) {
|
||||
func (s *RPC) Next(c context.Context, agentFilter rpc.Filter) (*rpc.Pipeline, error) {
|
||||
metadata, ok := grpcMetadata.FromIncomingContext(c)
|
||||
if ok {
|
||||
hostname, ok := metadata["hostname"]
|
||||
|
@ -61,7 +61,7 @@ func (s *RPC) Next(c context.Context, filter rpc.Filter) (*rpc.Pipeline, error)
|
|||
}
|
||||
}
|
||||
|
||||
fn, err := createFilterFunc(filter)
|
||||
fn, err := createFilterFunc(agentFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -63,7 +63,6 @@ func NewWoodpeckerServer(remote remote.Remote, queue queue.Queue, logger logging
|
|||
func (s *WoodpeckerServer) Next(c context.Context, req *proto.NextRequest) (*proto.NextReply, error) {
|
||||
filter := rpc.Filter{
|
||||
Labels: req.GetFilter().GetLabels(),
|
||||
Expr: req.GetFilter().GetExpr(),
|
||||
}
|
||||
|
||||
res := new(proto.NextReply)
|
||||
|
|
|
@ -26,7 +26,7 @@ type entry struct {
|
|||
}
|
||||
|
||||
type worker struct {
|
||||
filter Filter
|
||||
filter FilterFn
|
||||
channel chan *Task
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ func (q *fifo) PushAtOnce(c context.Context, tasks []*Task) error {
|
|||
}
|
||||
|
||||
// Poll retrieves and removes the head of this queue.
|
||||
func (q *fifo) Poll(c context.Context, f Filter) (*Task, error) {
|
||||
func (q *fifo) Poll(c context.Context, f FilterFn) (*Task, error) {
|
||||
q.Lock()
|
||||
w := &worker{
|
||||
channel: make(chan *Task, 1),
|
||||
|
|
|
@ -96,7 +96,7 @@ func (q *persistentQueue) PushAtOnce(c context.Context, tasks []*Task) error {
|
|||
}
|
||||
|
||||
// Poll retrieves and removes a task head of this queue.
|
||||
func (q *persistentQueue) Poll(c context.Context, f Filter) (*Task, error) {
|
||||
func (q *persistentQueue) Poll(c context.Context, f FilterFn) (*Task, error) {
|
||||
task, err := q.Queue.Poll(c, f)
|
||||
if task != nil {
|
||||
log.Debug().Msgf("pull queue item: %s: remove from backup", task.ID)
|
||||
|
|
|
@ -25,7 +25,7 @@ type Task struct {
|
|||
// Data is the actual data in the entry.
|
||||
Data []byte `json:"data"`
|
||||
|
||||
// Labels represents the key-value pairs the entry is lebeled with.
|
||||
// Labels represents the key-value pairs the entry is labeled with.
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
|
||||
// Task IDs this task depend
|
||||
|
@ -128,7 +128,7 @@ func (t *InfoT) String() string {
|
|||
|
||||
// Filter filters tasks in the queue. If the Filter returns false,
|
||||
// the Task is skipped and not returned to the subscriber.
|
||||
type Filter func(*Task) bool
|
||||
type FilterFn func(*Task) bool
|
||||
|
||||
// Queue defines a task queue for scheduling tasks among
|
||||
// a pool of workers.
|
||||
|
@ -140,7 +140,7 @@ type Queue interface {
|
|||
PushAtOnce(c context.Context, tasks []*Task) error
|
||||
|
||||
// Poll retrieves and removes a task head of this queue.
|
||||
Poll(c context.Context, f Filter) (*Task, error)
|
||||
Poll(c context.Context, f FilterFn) (*Task, error)
|
||||
|
||||
// Extend extends the deadline for a task.
|
||||
Extend(c context.Context, id string) error
|
||||
|
|
|
@ -110,8 +110,6 @@ func (b *ProcBuilder) Build() ([]*BuildItem, error) {
|
|||
proc.State = model.StatusSkipped
|
||||
}
|
||||
|
||||
metadata.SetPlatform(parsed.Platform)
|
||||
|
||||
ir := b.toInternalRepresentation(parsed, environ, metadata, proc.ID)
|
||||
|
||||
if len(ir.Stages) == 0 {
|
||||
|
@ -124,7 +122,7 @@ func (b *ProcBuilder) Build() ([]*BuildItem, error) {
|
|||
Labels: parsed.Labels,
|
||||
DependsOn: parsed.DependsOn,
|
||||
RunsOn: parsed.RunsOn,
|
||||
Platform: metadata.Sys.Arch,
|
||||
Platform: parsed.Platform,
|
||||
}
|
||||
if item.Labels == nil {
|
||||
item.Labels = map[string]string{}
|
||||
|
@ -365,10 +363,10 @@ func metadataFromStruct(repo *model.Repo, build, last *model.Build, proc *model.
|
|||
Matrix: proc.Environ,
|
||||
},
|
||||
Sys: frontend.System{
|
||||
Name: "woodpecker",
|
||||
Link: link,
|
||||
Host: host,
|
||||
Arch: "linux/amd64",
|
||||
Name: "woodpecker",
|
||||
Link: link,
|
||||
Host: host,
|
||||
Platform: "", // will be set by pipeline platform option or by agent
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
2
vendor/github.com/woodpecker-ci/expr/.gitignore
generated
vendored
2
vendor/github.com/woodpecker-ci/expr/.gitignore
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
*.out
|
||||
*.txt
|
5
vendor/github.com/woodpecker-ci/expr/README
generated
vendored
5
vendor/github.com/woodpecker-ci/expr/README
generated
vendored
|
@ -1,5 +0,0 @@
|
|||
Go package for parsing and evaluating SQL expressions.
|
||||
|
||||
Documentation:
|
||||
|
||||
https://pkg.go.dev/github.com/woodpecker-ci/expr
|
158
vendor/github.com/woodpecker-ci/expr/eval.go
generated
vendored
158
vendor/github.com/woodpecker-ci/expr/eval.go
generated
vendored
|
@ -1,158 +0,0 @@
|
|||
package expr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/woodpecker-ci/expr/parse"
|
||||
)
|
||||
|
||||
// state represents the state of an execution. It's not part of the
|
||||
// statement so that multiple executions of the same statement
|
||||
// can execute in parallel.
|
||||
type state struct {
|
||||
node parse.Node
|
||||
vars Row
|
||||
}
|
||||
|
||||
// at marks the state to be on node n, for error reporting.
|
||||
func (s *state) at(node parse.Node) {
|
||||
s.node = node
|
||||
}
|
||||
|
||||
// Walk functions step through the major pieces of the template structure,
|
||||
// generating output as they go.
|
||||
func (s *state) walk(node parse.BoolExpr) bool {
|
||||
s.at(node)
|
||||
|
||||
switch node := node.(type) {
|
||||
case *parse.ComparisonExpr:
|
||||
return s.eval(node)
|
||||
case *parse.AndExpr:
|
||||
return s.walk(node.Left) && s.walk(node.Right)
|
||||
case *parse.OrExpr:
|
||||
return s.walk(node.Left) || s.walk(node.Right)
|
||||
case *parse.NotExpr:
|
||||
return !s.walk(node.Expr)
|
||||
case *parse.ParenBoolExpr:
|
||||
return s.walk(node.Expr)
|
||||
default:
|
||||
panic("invalid node type")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *state) eval(node *parse.ComparisonExpr) bool {
|
||||
switch node.Operator {
|
||||
case parse.OperatorEq:
|
||||
return s.evalEq(node)
|
||||
case parse.OperatorGt:
|
||||
return s.evalGt(node)
|
||||
case parse.OperatorGte:
|
||||
return s.evalGte(node)
|
||||
case parse.OperatorLt:
|
||||
return s.evalLt(node)
|
||||
case parse.OperatorLte:
|
||||
return s.evalLte(node)
|
||||
case parse.OperatorNeq:
|
||||
return !s.evalEq(node)
|
||||
case parse.OperatorGlob:
|
||||
return s.evalGlob(node)
|
||||
case parse.OperatorNotGlob:
|
||||
return !s.evalGlob(node)
|
||||
case parse.OperatorRe:
|
||||
return s.evalRegexp(node)
|
||||
case parse.OperatorNotRe:
|
||||
return !s.evalRegexp(node)
|
||||
case parse.OperatorIn:
|
||||
return s.evalIn(node)
|
||||
case parse.OperatorNotIn:
|
||||
return !s.evalIn(node)
|
||||
default:
|
||||
panic("inalid operator type")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *state) evalEq(node *parse.ComparisonExpr) bool {
|
||||
return bytes.Equal(
|
||||
s.toValue(node.Left),
|
||||
s.toValue(node.Right),
|
||||
)
|
||||
}
|
||||
|
||||
func (s *state) evalGt(node *parse.ComparisonExpr) bool {
|
||||
return bytes.Compare(
|
||||
s.toValue(node.Left),
|
||||
s.toValue(node.Right),
|
||||
) == 1
|
||||
}
|
||||
|
||||
func (s *state) evalGte(node *parse.ComparisonExpr) bool {
|
||||
return bytes.Compare(
|
||||
s.toValue(node.Left),
|
||||
s.toValue(node.Right),
|
||||
) >= 0
|
||||
}
|
||||
|
||||
func (s *state) evalLt(node *parse.ComparisonExpr) bool {
|
||||
return bytes.Compare(
|
||||
s.toValue(node.Left),
|
||||
s.toValue(node.Right),
|
||||
) == -1
|
||||
}
|
||||
|
||||
func (s *state) evalLte(node *parse.ComparisonExpr) bool {
|
||||
return bytes.Compare(
|
||||
s.toValue(node.Left),
|
||||
s.toValue(node.Right),
|
||||
) <= 0
|
||||
}
|
||||
|
||||
func (s *state) evalGlob(node *parse.ComparisonExpr) bool {
|
||||
match, _ := filepath.Match(
|
||||
string(s.toValue(node.Right)),
|
||||
string(s.toValue(node.Left)),
|
||||
)
|
||||
return match
|
||||
}
|
||||
|
||||
func (s *state) evalRegexp(node *parse.ComparisonExpr) bool {
|
||||
match, _ := regexp.Match(
|
||||
string(s.toValue(node.Right)),
|
||||
s.toValue(node.Left),
|
||||
)
|
||||
return match
|
||||
}
|
||||
|
||||
func (s *state) evalIn(node *parse.ComparisonExpr) bool {
|
||||
left := s.toValue(node.Left)
|
||||
right, ok := node.Right.(*parse.ArrayLit)
|
||||
if !ok {
|
||||
panic("expected array literal")
|
||||
}
|
||||
|
||||
for _, expr := range right.Values {
|
||||
if bytes.Equal(left, s.toValue(expr)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *state) toValue(expr parse.ValExpr) []byte {
|
||||
switch node := expr.(type) {
|
||||
case *parse.Field:
|
||||
return s.vars.Field(node.Name)
|
||||
case *parse.BasicLit:
|
||||
return node.Value
|
||||
default:
|
||||
panic("invalid expression type")
|
||||
}
|
||||
}
|
||||
|
||||
// errRecover is the handler that turns panics into returns.
|
||||
func errRecover(err *error) {
|
||||
if e := recover(); e != nil {
|
||||
*err = e.(error)
|
||||
}
|
||||
}
|
5
vendor/github.com/woodpecker-ci/expr/go.mod
generated
vendored
5
vendor/github.com/woodpecker-ci/expr/go.mod
generated
vendored
|
@ -1,5 +0,0 @@
|
|||
module github.com/woodpecker-ci/expr
|
||||
|
||||
go 1.16
|
||||
|
||||
require github.com/kr/pretty v0.2.1
|
5
vendor/github.com/woodpecker-ci/expr/go.sum
generated
vendored
5
vendor/github.com/woodpecker-ci/expr/go.sum
generated
vendored
|
@ -1,5 +0,0 @@
|
|||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
268
vendor/github.com/woodpecker-ci/expr/parse/lex.go
generated
vendored
268
vendor/github.com/woodpecker-ci/expr/parse/lex.go
generated
vendored
|
@ -1,268 +0,0 @@
|
|||
package parse
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// token is a lexical token.
|
||||
type token uint
|
||||
|
||||
// list of lexical tokens.
|
||||
const (
|
||||
// special tokens
|
||||
tokenIllegal token = iota
|
||||
tokenEOF
|
||||
|
||||
// identifiers and basic type literals
|
||||
tokenIdent
|
||||
tokenText
|
||||
tokenReal
|
||||
tokenInteger
|
||||
|
||||
// operators and delimiters
|
||||
tokenEq // ==
|
||||
tokenLt // <
|
||||
tokenLte // <=
|
||||
tokenGt // >
|
||||
tokenGte // >=
|
||||
tokenNeq // !=
|
||||
tokenComma // ,
|
||||
tokenLparen // (
|
||||
tokenRparen // )
|
||||
|
||||
// keywords
|
||||
tokenNot
|
||||
tokenAnd
|
||||
tokenOr
|
||||
tokenIn
|
||||
tokenGlob
|
||||
tokenRegexp
|
||||
tokenBetween
|
||||
tokenTrue
|
||||
tokenFalse
|
||||
)
|
||||
|
||||
// lexer implements a lexical scanner that reads unicode characters
|
||||
// and tokens from a byte buffer.
|
||||
type lexer struct {
|
||||
buf []byte
|
||||
pos int
|
||||
start int
|
||||
width int
|
||||
}
|
||||
|
||||
// scan reads the next token or Unicode character from source and
|
||||
// returns it. It returns EOF at the end of the source.
|
||||
func (l *lexer) scan() token {
|
||||
l.start = l.pos
|
||||
l.skipWhitespace()
|
||||
|
||||
r := l.read()
|
||||
switch {
|
||||
case isIdent(r):
|
||||
l.unread()
|
||||
return l.scanIdent()
|
||||
case isQuote(r):
|
||||
l.unread()
|
||||
return l.scanQuote()
|
||||
case isNumeric(r):
|
||||
l.unread()
|
||||
return l.scanNumber()
|
||||
case isCompare(r):
|
||||
l.unread()
|
||||
return l.scanCompare()
|
||||
}
|
||||
|
||||
switch r {
|
||||
case eof:
|
||||
return tokenEOF
|
||||
case '(':
|
||||
return tokenLparen
|
||||
case ')':
|
||||
return tokenRparen
|
||||
case ',':
|
||||
return tokenComma
|
||||
}
|
||||
|
||||
return tokenIllegal
|
||||
}
|
||||
|
||||
// peek reads the next token or Unicode character from source and
|
||||
// returns it without advancing the scanner.
|
||||
func (l *lexer) peek() token {
|
||||
var (
|
||||
pos = l.pos
|
||||
start = l.start
|
||||
width = l.width
|
||||
)
|
||||
tok := l.scan()
|
||||
l.pos = pos
|
||||
l.start = start
|
||||
l.width = width
|
||||
return tok
|
||||
}
|
||||
|
||||
// bytes returns the bytes corresponding to the most recently scanned
|
||||
// token. Valid after calling Scan().
|
||||
func (l *lexer) bytes() []byte {
|
||||
return l.buf[l.start:l.pos]
|
||||
}
|
||||
|
||||
// string returns the string corresponding to the most recently scanned
|
||||
// token. Valid after calling Scan().
|
||||
func (l *lexer) string() string {
|
||||
return string(l.bytes())
|
||||
}
|
||||
|
||||
// init initializes a scanner with a new buffer.
|
||||
func (l *lexer) init(buf []byte) {
|
||||
l.buf = buf
|
||||
l.pos = 0
|
||||
l.start = 0
|
||||
l.width = 0
|
||||
}
|
||||
|
||||
func (l *lexer) scanIdent() token {
|
||||
for {
|
||||
if r := l.read(); r == eof {
|
||||
break
|
||||
} else if !isIdent(r) {
|
||||
l.unread()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
ident := l.bytes()
|
||||
switch string(ident) {
|
||||
case "NOT", "not":
|
||||
return tokenNot
|
||||
case "AND", "and":
|
||||
return tokenAnd
|
||||
case "OR", "or":
|
||||
return tokenOr
|
||||
case "IN", "in":
|
||||
return tokenIn
|
||||
case "GLOB", "glob":
|
||||
return tokenGlob
|
||||
case "REGEXP", "regexp":
|
||||
return tokenRegexp
|
||||
case "BETWEEN", "between":
|
||||
return tokenBetween
|
||||
case "TRUE", "true":
|
||||
return tokenTrue
|
||||
case "FALSE", "false":
|
||||
return tokenFalse
|
||||
}
|
||||
|
||||
return tokenIdent
|
||||
}
|
||||
|
||||
func (l *lexer) scanQuote() (tok token) {
|
||||
l.read() // consume first quote
|
||||
|
||||
for {
|
||||
if r := l.read(); r == eof {
|
||||
return tokenIllegal
|
||||
} else if isQuote(r) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return tokenText
|
||||
}
|
||||
|
||||
func (l *lexer) scanNumber() token {
|
||||
for {
|
||||
if r := l.read(); r == eof {
|
||||
break
|
||||
} else if !isNumeric(r) {
|
||||
l.unread()
|
||||
break
|
||||
}
|
||||
}
|
||||
return tokenInteger
|
||||
}
|
||||
|
||||
func (l *lexer) scanCompare() (tok token) {
|
||||
switch l.read() {
|
||||
case '=':
|
||||
tok = tokenEq
|
||||
case '!':
|
||||
tok = tokenNeq
|
||||
case '>':
|
||||
tok = tokenGt
|
||||
case '<':
|
||||
tok = tokenLt
|
||||
}
|
||||
|
||||
r := l.read()
|
||||
switch {
|
||||
case tok == tokenGt && r == '=':
|
||||
tok = tokenGte
|
||||
case tok == tokenLt && r == '=':
|
||||
tok = tokenLte
|
||||
case tok == tokenEq && r == '=':
|
||||
tok = tokenEq
|
||||
case tok == tokenNeq && r == '=':
|
||||
tok = tokenNeq
|
||||
case tok == tokenNeq && r != '=':
|
||||
tok = tokenIllegal
|
||||
default:
|
||||
l.unread()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (l *lexer) skipWhitespace() {
|
||||
for {
|
||||
if r := l.read(); r == eof {
|
||||
break
|
||||
} else if !isWhitespace(r) {
|
||||
l.unread()
|
||||
break
|
||||
}
|
||||
}
|
||||
l.ignore()
|
||||
}
|
||||
|
||||
func (l *lexer) read() rune {
|
||||
if l.pos >= len(l.buf) {
|
||||
l.width = 0
|
||||
return eof
|
||||
}
|
||||
r, w := utf8.DecodeRune(l.buf[l.pos:])
|
||||
l.width = w
|
||||
l.pos += l.width
|
||||
return r
|
||||
}
|
||||
|
||||
func (l *lexer) unread() {
|
||||
l.pos -= l.width
|
||||
}
|
||||
|
||||
func (l *lexer) ignore() {
|
||||
l.start = l.pos
|
||||
}
|
||||
|
||||
// eof rune sent when end of file is reached
|
||||
var eof = rune(0)
|
||||
|
||||
func isWhitespace(r rune) bool {
|
||||
return r == ' ' || r == '\t' || r == '\n'
|
||||
}
|
||||
|
||||
func isNumeric(r rune) bool {
|
||||
return unicode.IsDigit(r) || r == '.'
|
||||
}
|
||||
|
||||
func isQuote(r rune) bool {
|
||||
return r == '\''
|
||||
}
|
||||
|
||||
func isCompare(r rune) bool {
|
||||
return r == '=' || r == '!' || r == '>' || r == '<'
|
||||
}
|
||||
|
||||
func isIdent(r rune) bool {
|
||||
return unicode.IsLetter(r) || r == '_' || r == '-'
|
||||
}
|
119
vendor/github.com/woodpecker-ci/expr/parse/node.go
generated
vendored
119
vendor/github.com/woodpecker-ci/expr/parse/node.go
generated
vendored
|
@ -1,119 +0,0 @@
|
|||
package parse
|
||||
|
||||
// Node is an element in the parse tree.
|
||||
type Node interface {
|
||||
node()
|
||||
}
|
||||
|
||||
// ValExpr defines a value expression.
|
||||
type ValExpr interface {
|
||||
Node
|
||||
value()
|
||||
}
|
||||
|
||||
// BoolExpr defines a boolean expression.
|
||||
type BoolExpr interface {
|
||||
Node
|
||||
bool()
|
||||
}
|
||||
|
||||
// An expression is represented by a tree consisting of one
|
||||
// or more of the following concrete expression nodes.
|
||||
//
|
||||
type (
|
||||
// ComparisonExpr represents a two-value comparison expression.
|
||||
ComparisonExpr struct {
|
||||
Operator Operator
|
||||
Left, Right ValExpr
|
||||
}
|
||||
|
||||
// AndExpr represents an AND expression.
|
||||
AndExpr struct {
|
||||
Left, Right BoolExpr
|
||||
}
|
||||
|
||||
// OrExpr represents an OR expression.
|
||||
OrExpr struct {
|
||||
Left, Right BoolExpr
|
||||
}
|
||||
|
||||
// NotExpr represents a NOT expression.
|
||||
NotExpr struct {
|
||||
Expr BoolExpr
|
||||
}
|
||||
|
||||
// ParenBoolExpr represents a parenthesized boolean expression.
|
||||
ParenBoolExpr struct {
|
||||
Expr BoolExpr
|
||||
}
|
||||
|
||||
// BasicLit represents a basic literal.
|
||||
BasicLit struct {
|
||||
Kind Literal // INT, REAL, TEXT
|
||||
Value []byte
|
||||
}
|
||||
|
||||
// ArrayLit represents an array literal.
|
||||
ArrayLit struct {
|
||||
Values []ValExpr
|
||||
}
|
||||
|
||||
// Field represents a value lookup by name.
|
||||
Field struct {
|
||||
Name []byte
|
||||
}
|
||||
)
|
||||
|
||||
// Operator identifies the type of operator.
|
||||
type Operator int
|
||||
|
||||
// Comparison operators.
|
||||
const (
|
||||
OperatorEq Operator = iota
|
||||
OperatorLt
|
||||
OperatorLte
|
||||
OperatorGt
|
||||
OperatorGte
|
||||
OperatorNeq
|
||||
OperatorIn
|
||||
OperatorRe
|
||||
OperatorGlob
|
||||
OperatorNotIn
|
||||
OperatorNotRe
|
||||
OperatorNotGlob
|
||||
OperatorBetween
|
||||
OperatorNotBetween
|
||||
)
|
||||
|
||||
// Literal identifies the type of literal.
|
||||
type Literal int
|
||||
|
||||
// The list of possible literal kinds.
|
||||
const (
|
||||
LiteralBool Literal = iota
|
||||
LiteralInt
|
||||
LiteralReal
|
||||
LiteralText
|
||||
)
|
||||
|
||||
// node() defines the node in a parse tree
|
||||
func (x *ComparisonExpr) node() {}
|
||||
func (x *AndExpr) node() {}
|
||||
func (x *OrExpr) node() {}
|
||||
func (x *NotExpr) node() {}
|
||||
func (x *ParenBoolExpr) node() {}
|
||||
func (x *BasicLit) node() {}
|
||||
func (x *ArrayLit) node() {}
|
||||
func (x *Field) node() {}
|
||||
|
||||
// bool() defines the node as a boolean expression.
|
||||
func (x *ComparisonExpr) bool() {}
|
||||
func (x *AndExpr) bool() {}
|
||||
func (x *OrExpr) bool() {}
|
||||
func (x *NotExpr) bool() {}
|
||||
func (x *ParenBoolExpr) bool() {}
|
||||
|
||||
// value() defines the node as a value expression.
|
||||
func (x *BasicLit) value() {}
|
||||
func (x *ArrayLit) value() {}
|
||||
func (x *Field) value() {}
|
272
vendor/github.com/woodpecker-ci/expr/parse/parse.go
generated
vendored
272
vendor/github.com/woodpecker-ci/expr/parse/parse.go
generated
vendored
|
@ -1,272 +0,0 @@
|
|||
package parse
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Tree is the representation of a single parsed SQL statement.
|
||||
type Tree struct {
|
||||
Root BoolExpr
|
||||
|
||||
lex *lexer
|
||||
depth int
|
||||
}
|
||||
|
||||
// Parse parses the SQL statement and returns a Tree.
|
||||
func Parse(buf []byte) (*Tree, error) {
|
||||
t := new(Tree)
|
||||
t.lex = new(lexer)
|
||||
return t.Parse(buf)
|
||||
}
|
||||
|
||||
// Parse parses the SQL statement buffer to construct an ast
|
||||
// representation for execution.
|
||||
func (t *Tree) Parse(buf []byte) (tree *Tree, err error) {
|
||||
defer t.recover(&err)
|
||||
t.lex.init(buf)
|
||||
t.Root = t.parseExpr()
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// recover is the handler that turns panics into returns.
|
||||
func (t *Tree) recover(err *error) {
|
||||
if e := recover(); e != nil {
|
||||
*err = e.(error)
|
||||
}
|
||||
}
|
||||
|
||||
// errorf formats the error and terminates processing.
|
||||
func (t *Tree) errorf(format string, args ...interface{}) {
|
||||
t.Root = nil
|
||||
format = fmt.Sprintf("selector: parse error:%d: %s", t.lex.start, format)
|
||||
panic(fmt.Errorf(format, args...))
|
||||
}
|
||||
|
||||
func (t *Tree) parseExpr() BoolExpr {
|
||||
switch t.lex.peek() {
|
||||
case tokenLparen:
|
||||
t.lex.scan()
|
||||
return t.parseGroup()
|
||||
case tokenNot:
|
||||
t.lex.scan()
|
||||
return t.parseNot()
|
||||
}
|
||||
|
||||
left := t.parseVal()
|
||||
node := t.parseComparison(left)
|
||||
|
||||
switch t.lex.scan() {
|
||||
case tokenOr:
|
||||
return t.parseOr(node)
|
||||
case tokenAnd:
|
||||
return t.parseAnd(node)
|
||||
case tokenRparen:
|
||||
if t.depth == 0 {
|
||||
t.errorf("unexpected token")
|
||||
return nil
|
||||
}
|
||||
return node
|
||||
default:
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tree) parseGroup() BoolExpr {
|
||||
t.depth++
|
||||
node := t.parseExpr()
|
||||
t.depth--
|
||||
|
||||
switch t.lex.scan() {
|
||||
case tokenOr:
|
||||
return t.parseOr(node)
|
||||
case tokenAnd:
|
||||
return t.parseAnd(node)
|
||||
case tokenEOF:
|
||||
return node
|
||||
default:
|
||||
t.errorf("unexpected token")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tree) parseAnd(left BoolExpr) BoolExpr {
|
||||
node := new(AndExpr)
|
||||
node.Left = left
|
||||
node.Right = t.parseExpr()
|
||||
return node
|
||||
}
|
||||
|
||||
func (t *Tree) parseOr(left BoolExpr) BoolExpr {
|
||||
node := new(OrExpr)
|
||||
node.Left = left
|
||||
node.Right = t.parseExpr()
|
||||
return node
|
||||
}
|
||||
|
||||
func (t *Tree) parseNot() BoolExpr {
|
||||
node := new(NotExpr)
|
||||
node.Expr = t.parseExpr()
|
||||
return node
|
||||
}
|
||||
|
||||
func (t *Tree) parseComparison(left ValExpr) BoolExpr {
|
||||
var negate bool
|
||||
if t.lex.peek() == tokenNot {
|
||||
t.lex.scan()
|
||||
negate = true
|
||||
}
|
||||
|
||||
op := t.parseOperator()
|
||||
|
||||
if negate {
|
||||
switch op {
|
||||
case OperatorIn:
|
||||
op = OperatorNotIn
|
||||
case OperatorGlob:
|
||||
op = OperatorNotGlob
|
||||
case OperatorRe:
|
||||
op = OperatorNotRe
|
||||
case OperatorBetween:
|
||||
op = OperatorNotBetween
|
||||
}
|
||||
}
|
||||
|
||||
switch op {
|
||||
case OperatorBetween:
|
||||
return t.parseBetween(left)
|
||||
case OperatorNotBetween:
|
||||
return t.parseNotBetween(left)
|
||||
}
|
||||
|
||||
node := new(ComparisonExpr)
|
||||
node.Left = left
|
||||
node.Operator = op
|
||||
|
||||
switch node.Operator {
|
||||
case OperatorIn, OperatorNotIn:
|
||||
node.Right = t.parseList()
|
||||
case OperatorRe, OperatorNotRe:
|
||||
// TODO we should use a custom regexp node here that parses and
|
||||
// compiles the regexp, insteam of recompiling on every evaluation.
|
||||
node.Right = t.parseVal()
|
||||
default:
|
||||
node.Right = t.parseVal()
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
func (t *Tree) parseNotBetween(value ValExpr) BoolExpr {
|
||||
node := new(NotExpr)
|
||||
node.Expr = t.parseBetween(value)
|
||||
return node
|
||||
}
|
||||
|
||||
func (t *Tree) parseBetween(value ValExpr) BoolExpr {
|
||||
left := new(ComparisonExpr)
|
||||
left.Left = value
|
||||
left.Operator = OperatorGte
|
||||
left.Right = t.parseVal()
|
||||
|
||||
if t.lex.scan() != tokenAnd {
|
||||
t.errorf("unexpected token, expecting AND")
|
||||
return nil
|
||||
}
|
||||
|
||||
right := new(ComparisonExpr)
|
||||
right.Left = value
|
||||
right.Operator = OperatorLte
|
||||
right.Right = t.parseVal()
|
||||
|
||||
node := new(AndExpr)
|
||||
node.Left = left
|
||||
node.Right = right
|
||||
return node
|
||||
}
|
||||
|
||||
func (t *Tree) parseOperator() (op Operator) {
|
||||
switch t.lex.scan() {
|
||||
case tokenEq:
|
||||
return OperatorEq
|
||||
case tokenGt:
|
||||
return OperatorGt
|
||||
case tokenGte:
|
||||
return OperatorGte
|
||||
case tokenLt:
|
||||
return OperatorLt
|
||||
case tokenLte:
|
||||
return OperatorLte
|
||||
case tokenNeq:
|
||||
return OperatorNeq
|
||||
case tokenIn:
|
||||
return OperatorIn
|
||||
case tokenRegexp:
|
||||
return OperatorRe
|
||||
case tokenGlob:
|
||||
return OperatorGlob
|
||||
case tokenBetween:
|
||||
return OperatorBetween
|
||||
default:
|
||||
t.errorf("illegal operator")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tree) parseVal() ValExpr {
|
||||
switch t.lex.scan() {
|
||||
case tokenIdent:
|
||||
node := new(Field)
|
||||
node.Name = t.lex.bytes()
|
||||
return node
|
||||
case tokenText:
|
||||
return t.parseText()
|
||||
case tokenReal, tokenInteger, tokenTrue, tokenFalse:
|
||||
node := new(BasicLit)
|
||||
node.Value = t.lex.bytes()
|
||||
return node
|
||||
default:
|
||||
t.errorf("illegal value expression")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tree) parseList() ValExpr {
|
||||
if t.lex.scan() != tokenLparen {
|
||||
t.errorf("unexpected token, expecting (")
|
||||
return nil
|
||||
}
|
||||
node := new(ArrayLit)
|
||||
for {
|
||||
next := t.lex.peek()
|
||||
switch next {
|
||||
case tokenEOF:
|
||||
t.errorf("unexpected eof, expecting )")
|
||||
case tokenComma:
|
||||
t.lex.scan()
|
||||
case tokenRparen:
|
||||
t.lex.scan()
|
||||
return node
|
||||
default:
|
||||
child := t.parseVal()
|
||||
node.Values = append(node.Values, child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tree) parseText() ValExpr {
|
||||
node := new(BasicLit)
|
||||
node.Value = t.lex.bytes()
|
||||
|
||||
// this is where we strip the starting and ending quote
|
||||
// and unescape the string. On the surface this might look
|
||||
// like it is subject to index out of bounds errors but
|
||||
// it is safe because it is already verified by the lexer.
|
||||
node.Value = node.Value[1 : len(node.Value)-1]
|
||||
node.Value = bytes.Replace(node.Value, quoteEscaped, quoteUnescaped, -1)
|
||||
return node
|
||||
}
|
||||
|
||||
var (
|
||||
quoteEscaped = []byte("\\'")
|
||||
quoteUnescaped = []byte("'")
|
||||
)
|
50
vendor/github.com/woodpecker-ci/expr/selector.go
generated
vendored
50
vendor/github.com/woodpecker-ci/expr/selector.go
generated
vendored
|
@ -1,50 +0,0 @@
|
|||
package expr
|
||||
|
||||
import "github.com/woodpecker-ci/expr/parse"
|
||||
|
||||
// Selector reprents a parsed SQL selector statement.
|
||||
type Selector struct {
|
||||
*parse.Tree
|
||||
}
|
||||
|
||||
// Parse parses the SQL statement and returns a new Statement object.
|
||||
func Parse(b []byte) (selector *Selector, err error) {
|
||||
selector = new(Selector)
|
||||
selector.Tree, err = parse.Parse(b)
|
||||
return
|
||||
}
|
||||
|
||||
// ParseString parses the SQL statement and returns a new Statement object.
|
||||
func ParseString(s string) (selector *Selector, err error) {
|
||||
return Parse([]byte(s))
|
||||
}
|
||||
|
||||
// Eval evaluates the SQL statement using the provided data and returns true
|
||||
// if all conditions are satisfied. If a runtime error is experiences a false
|
||||
// value is returned along with an error message.
|
||||
func (s *Selector) Eval(row Row) (match bool, err error) {
|
||||
defer errRecover(&err)
|
||||
state := &state{vars: row}
|
||||
match = state.walk(s.Root)
|
||||
return
|
||||
}
|
||||
|
||||
// Row defines a row of columnar data.
|
||||
//
|
||||
// Note that the field name and field values are represented as []byte
|
||||
// since stomp header names and values are represented as []byte to avoid
|
||||
// extra allocations when converting from []byte to string.
|
||||
type Row interface {
|
||||
Field([]byte) []byte
|
||||
}
|
||||
|
||||
// NewRow return a Row bound to a map of key value strings.
|
||||
func NewRow(m map[string]string) Row {
|
||||
return mapRow(m)
|
||||
}
|
||||
|
||||
type mapRow map[string]string
|
||||
|
||||
func (m mapRow) Field(name []byte) []byte {
|
||||
return []byte(m[string(name)])
|
||||
}
|
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
|
@ -606,10 +606,6 @@ github.com/ultraware/whitespace
|
|||
github.com/urfave/cli/v2
|
||||
# github.com/uudashr/gocognit v1.0.5
|
||||
github.com/uudashr/gocognit
|
||||
# github.com/woodpecker-ci/expr v0.0.0-20210628233344-164b8b3d0915
|
||||
## explicit
|
||||
github.com/woodpecker-ci/expr
|
||||
github.com/woodpecker-ci/expr/parse
|
||||
# github.com/xanzy/go-gitlab v0.64.0
|
||||
## explicit
|
||||
github.com/xanzy/go-gitlab
|
||||
|
|
Loading…
Reference in a new issue