Skip to content

Commit

Permalink
Add support for pipeline root.when conditions (#770)
Browse files Browse the repository at this point in the history
Co-authored-by: Zav Shotan <zshotan@bloomberg.net>
Co-authored-by: Anbraten <anton@ju60.de>
Co-authored-by: 6543 <6543@obermui.de>
  • Loading branch information
4 people authored Sep 26, 2022
1 parent 62d8276 commit ec9b0a6
Show file tree
Hide file tree
Showing 12 changed files with 440 additions and 110 deletions.
240 changes: 157 additions & 83 deletions docs/docs/20-usage/20-pipeline-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,88 +21,6 @@ pipeline:
In the above example we define two pipeline steps, `frontend` and `backend`. The names of these steps are completely arbitrary.

## Global Pipeline Conditionals

Woodpecker gives the ability to skip whole pipelines (not just steps) based on certain conditions.

### `branches`

Woodpecker can skip commits based on the target branch. If the branch matches the `branches:` block the pipeline is executed, otherwise it is skipped.

Example skipping a commit when the target branch is not master:

```diff
pipeline:
build:
image: golang
commands:
- go build
- go test
+branches: master
```

Example matching multiple target branches:

```diff
pipeline:
build:
image: golang
commands:
- go build
- go test
+branches: [ master, develop ]
```

Example uses glob matching:

```diff
pipeline:
build:
image: golang
commands:
- go build
- go test
+branches: [ master, feature/* ]
```

Example includes branches:

```diff
pipeline:
build:
image: golang
commands:
- go build
- go test
+branches:
+ include: [ master, feature/* ]
```

Example excludes branches:

```diff
pipeline:
build:
image: golang
commands:
- go build
- go test
+branches:
+ exclude: [ develop, feature/* ]
```

The branch matching is done using [doublestar](/~https://github.com/bmatcuk/doublestar/#usage), note that a pattern starting with `*` should be put between quotes and a literal `/` needs to be escaped. A few examples:

- `*\\/*` to match patterns with exactly 1 `/`
- `*\\/**` to match patters with at least 1 `/`
- `*` to match patterns without `/`
- `**` to match everything

### Skip Commits

Woodpecker gives the ability to skip individual commits by adding `[CI SKIP]` to the commit message. Note this is case-insensitive.
Expand Down Expand Up @@ -334,6 +252,13 @@ when:
- branch: prefix/*
```

The branch matching is done using [doublestar](/~https://github.com/bmatcuk/doublestar/#usage), note that a pattern starting with `*` should be put between quotes and a literal `/` needs to be escaped. A few examples:

- `*\\/*` to match patterns with exactly 1 `/`
- `*\\/**` to match patters with at least 1 `/`
- `*` to match patterns without `/`
- `**` to match everything

Execute a step using custom include and exclude logic:

```yaml
Expand Down Expand Up @@ -469,7 +394,7 @@ when:
:::info
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)).
Gitea only supports **push** at the moment ([go-gitea/gitea#18228](/~https://github.com/go-gitea/gitea/pull/18228)).
:::

Execute a step only on a pipeline with certain files being changed:
Expand Down Expand Up @@ -731,6 +656,155 @@ pipeline:
...
```

## `when` - Global pipeline conditions

Woodpecker gives the ability to skip whole pipelines (not just steps #when---conditional-execution-1) based on certain conditions by a `when` block. If all conditions in the `when` block evaluate to true the pipeline is executed, otherwise it is skipped, but treated as successful and other pipelines depending on it will still continue.

### `repo`

Example conditional execution by repository:

```diff
pipeline:
slack:
image: plugins/slack
settings:
channel: dev
+ when:
+ repo: test/test
```

### `branch`

:::note
Branch conditions are not applied to tags.
:::

Example conditional execution by branch:

```diff
pipeline:
slack:
image: plugins/slack
settings:
channel: dev
+ when:
+ branch: master
```

> The step now triggers on master, but also if the target branch of a pull request is `master`. Add an event condition to limit it further to pushes on master only.

Execute a step if the branch is `master` or `develop`:

```diff
when:
branch: [master, develop]
```

Execute a step if the branch starts with `prefix/*`:

```diff
when:
branch: prefix/*
```

Execute a step using custom include and exclude logic:

```diff
when:
branch:
include: [ master, release/* ]
exclude: [ release/1.0.0, release/1.1.* ]
```

### `event`

Execute a step if the build event is a `tag`:

```diff
when:
event: tag
```

Execute a step if the pipeline event is a `push` to a specified branch:

```diff
when:
event: push
+ branch: main
```

Execute a step for all non-pull request events:

```diff
when:
event: [push, tag, deployment]
```

Execute a step for all build events:

```diff
when:
event: [push, pull_request, tag, deployment]
```

### `tag`

This filter only applies to tag events.
Use glob expression to execute a step if the tag name starts with `v`:

```diff
when:
event: tag
tag: v*
```

### `environment`

Execute a step for deployment events matching the target deployment environment:

```diff
when:
environment: production
event: deployment
```

### `instance`

Execute a step only on a certain Woodpecker instance matching the specified hostname:

```diff
when:
instance: stage.woodpecker.company.com
```

### `path`

:::info
Path conditions are applied only to **push** and **pull_request** events.
It is currently **only available** for GitHub, GitLab.
Gitea only supports **push** at the moment ([go-gitea/gitea#18228](/~https://github.com/go-gitea/gitea/pull/18228)).
:::

Execute a step only on a pipeline with certain files being changed:

```diff
when:
path: "src/*"
```

You can use [glob patterns](/~https://github.com/bmatcuk/doublestar#patterns) to match the changed files and specify if the step should run if a file matching that pattern has been changed `include` or if some files have **not** been changed `exclude`.

```diff
when:
path:
include: [ '.woodpecker/*.yml', '*.ini' ]
exclude: [ '*.md', 'docs/**' ]
ignore_message: "[ALL]"
```

**Hint:** Passing a defined ignore-message like `[ALL]` inside the commit message will ignore all path conditions.

## `depends_on`

Woodpecker supports to define multiple pipelines for a repository. Those pipelines will run independent from each other. To depend them on each other you can use the [`depends_on`](https://woodpecker-ci.org/docs/usage/multi-pipeline#flow-control) keyword.
Expand Down
12 changes: 9 additions & 3 deletions pipeline/frontend/yaml/compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ func New(opts ...Option) *Compiler {
func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {
config := new(backend.Config)

if !conf.When.Match(c.metadata, true) {
// This pipeline does not match the configured filter so return an empty config and stop further compilation.
// An empty pipeline will just be skipped completely.
return config
}

// create a default volume
config.Volumes = append(config.Volumes, &backend.Volume{
Name: fmt.Sprintf("%s_default", c.prefix),
Expand Down Expand Up @@ -149,7 +155,7 @@ func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {
config.Stages = append(config.Stages, stage)
} else if !c.local && !conf.SkipClone {
for i, container := range conf.Clone.Containers {
if !container.When.Match(c.metadata) {
if !container.When.Match(c.metadata, false) {
continue
}
stage := new(backend.Stage)
Expand All @@ -176,7 +182,7 @@ func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {
stage.Alias = nameServices

for i, container := range conf.Services.Containers {
if !container.When.Match(c.metadata) {
if !container.When.Match(c.metadata, false) {
continue
}

Expand All @@ -196,7 +202,7 @@ func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {
continue
}

if !container.When.Match(c.metadata) {
if !container.When.Match(c.metadata, false) {
continue
}

Expand Down
4 changes: 3 additions & 1 deletion pipeline/frontend/yaml/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import (
type (
// Config defines a pipeline configuration.
Config struct {
When constraint.When `yaml:"when,omitempty"`
Cache types.Stringorslice
Platform string
Branches constraint.List
Workspace Workspace
Clone Containers
Pipeline Containers
Expand All @@ -23,6 +23,8 @@ type (
DependsOn []string `yaml:"depends_on,omitempty"`
RunsOn []string `yaml:"runs_on,omitempty"`
SkipClone bool `yaml:"skip_clone"`
// Deprecated use When.Branch
Branches constraint.List
}

// Workspace defines a pipeline workspace.
Expand Down
Loading

0 comments on commit ec9b0a6

Please sign in to comment.