Conditional execution of steps

Skip specific pipeline steps according to one or more conditions

For each step in a codefresh.yml file, you can define a set of conditions which need to be satisfied in order to execute the step. For details on the codefresh.yml file, see Pipeline definitions YAML.)

There are currently two main methods to define conditions:

  • Branch conditions
  • Expression conditions

Branch Conditions

Usually, you’ll want to define a branch condition, be it of the type ignore for blacklisting a set of branches or of the type only for allowlisting a set of branches. Each branch specification can either be an exact branch name, e.g. master, or a regular expression, e.g. /hotfix$/. Case insensitive regexps (/^FB-/i) are also supported.

Here are some examples:

Only execute for the master branch

only-master-branch.yml

build-step:
  description: Building the image.
  type: build
  dockerfile: Dockerfile
  image-name: someRepo/someUser
  when:
    branch:
      only:
        - master

Only execute for feature branches

Only execute for branches whose name begins with FB- prefix, (feature branches):

only-feature-branches.yml

build-step:
  description: Building the image.
  type: build
  dockerfile: Dockerfile
  image-name: someRepo/someUser
  when:
    branch:
      only:
        - /^FB-.*/i

Ignore specific branches

Ignore the development branch and master branch:

ignore-master-and-develop-branch.yml

build-step:
  description: Building the image.
  type: build
  dockerfile: Dockerfile
  image-name: someRepo/someUser
  when:
    branch:
      ignore:
        - master
        - develop

TIP
We use JavaScript regular expressions for the syntax in branch conditions.

Conditional expressions

Alternatively, you can use more advanced condition expressions.

This follows the standard condition expression syntax. In this case, you can choose to execute if all expression conditions evaluate to true, or to execute if any expression conditions evaluate to true.

NOTE
Use “” around variables with text to avoid errors in processing the conditions. Example: “$”

Here are some examples.

AND conditional expression

Execute if the string [skip ci] is not part of the main repository commit message AND if the branch is master

all-conditions.yml

build-step:
  description: Building the image.
  type: build
  dockerfile: Dockerfile
  image-name: someRepo/someUser
  when:
    condition:
      all:
        noSkipCiInCommitMessage: 'includes(lower("${{CF_COMMIT_MESSAGE}}"), "skip ci") == false'
        masterBranch: '"${{CF_BRANCH}}" == "master"'

OR conditional expression

Execute if the string [skip ci] is not part of the main repository commit message, OR if the branch is not a feature branch (i.e. name starts with FB-)

any-condition.yml

build-step:
  description: Building the image.
  type: build
  dockerfile: Dockerfile
  image-name: someRepo/someUser
  when:
    condition:
      any:
        noSkipCiInCommitMessage: 'includes(lower("${{CF_COMMIT_MESSAGE}}"), "skip ci") == false'
        notFeatureBranch: 'match("${{CF_BRANCH}}", "^FB-", true) == false'

ALL conditions to be met

Each step in codefresh.yml file can contain conditions expressions that must be satisfied for the step to execute.

This is a small example of where a condition expression can be used: YAML

step-name:
  description: Step description
  image: image/id
  commands:
    - bash-command1
    - bash-command2
  when:
    condition:
      all:
        executeForMasterBranch: "'${{CF_BRANCH}}' == 'master'"

Conditional expression syntax

A conditional expression is a basic expression that is evaluated to true/false (to decide whether to execute or not to execute), and can have the following syntax:

Types

Type True/False Examples True/False
String True: “hello”
False: “”
  • String with content = true
  • Empty string = false
  • String with content = true
String comparison is lexicographic.
Number True: 5
True: 3.4
True: 1.79E+308
  • Any number other than 0 = true.
  • 0 = false
Boolean True: true
False: false
  • True = true
  • False = false
Null False: null Always false

Variables

You can use the user-defined variables, including the variables exposed by each individual pipeline step. See Variables in pipelines.

Unary Operators

Operator Operation
- Negation of numbers
! Logical NOT

Binary Operators

Operator Operation
Add, String Concatenation +
Subtract -
Multiply *
Divide /
Modulus %
Logical AND &&
Logical OR ||

Comparisons

Operator Operation
== Equal to
!= Not equal to
> Greater than
>= Greater than or equal
< Less than
<= Less than or equal

Functions

Function Name Parameters Return value Example
String 0: number or string String of input value. String(40) == '40'
Number 0: number or string Number of input value. Number('50') == 50
Number('hello') is invalid
Boolean 0: number or string Boolean of input value. Boolean('123') == true
Boolean('') == false
Boolean(583) == true
Boolean(0) == false
round 0: number Rounded number. round(1.3) == 1
round(1.95) == 2
floor 0: number Number rounded to floor. floor(1.3) == 1
floor(1.95) == 1
upper 0: string String in upper case. upper('hello') == 'HELLO'
lower 0: string String in lower case. lower('BYE BYE') == 'bye bye'
trim 0: string Trimmed string. trim(" abc ") == "abc"
trimLeft 0: string Left-trimmed string. trimLeft(" abc ") == "abc "
trimRight 0: string Right-trimmed string. trimRight(" abc ") == " abc"
replace 0: string - main string
1: string - substring to find
2: string - substring to replace
Replace all instances of the sub-string (1) in the main string (0) with the sub-string (2). replace('hello there', 'e', 'a') == 'hallo thara'
substring 0: string - main string
1: string - index to start
2: string - index to end
Returns a sub-string of a string. substring("hello world", 6, 11) == "world"
length string Length of a string. length("gump") == 4
includes 0: string - main string
1: string - string to search for
Whether a search string is located within the main string. includes("codefresh", "odef") == true
indexOf 0: string - main string
1: string - string to search for
Index of a search string if it is found inside the main string indexOf("codefresh", "odef") == 1
match 0: string - main string
1: string - regular expression string, JS style (Note: in JS strings, the backslash \ is an escape character so in order to use a literal backslash, you need to escape it. For example: "^\\d+$" instead of "^\d+$")
2: boolean - ignore case
Search for a regular expression inside a string, ignoring or not ignoring case match("hello there you", "..ll.", false) == true
match("hello there you", "..LL.", false) == false
match("hello there you", "hell$", true) == false
match("hello there you", "^hell", true) == true
match("hello there you", "bye", false) == false
Variable string Search for the value of a variable Variable('some-clone')
Member 0: string - variable name
1: string - member name
Search for the value of a variable member Member('some-clone', 'working-directory')

Execute steps according to the presence of a variable

If a variable does not exist in a Codefresh pipeline, then it will simply stay as a string inside the definition. When the ${{MY_VAR}} variable is not available, the engine will literally print ${{MY_VAR}}, because that variable doesn’t exist.

You can use this mechanism to decide which steps will be executed if a variable exists or not.

codefresh.yml

version: "1.0"
steps:
  step1:
    title: "Running if variable exists"
    type: "freestyle" 
    image: "alpine:3.9" 
    commands:
      - echo "Step 1 is running"
    when:
      condition:
        all:
          whenVarExists: 'includes("${{MY_VAR}}", "{{MY_VAR}}") == false'
  step2:
    title: "Running if variable does not exist"
    type: "freestyle" 
    image: "alpine:3.9" 
    commands:
      - echo "Step 2 is running"
    when:
      condition:
        all:
          whenVarIsMissing: 'includes("${{MY_VAR}}", "{{MY_VAR}}") == true'

Try running the pipeline above and see how it behaves when a variable called MY_VAR exists (or doesn’t exist).

NOTE
If you use this pattern frequently it means that you are trying to create a complex pipeline that is very smart. We suggest you create instead multiple simple pipelines for the same project.

Single step dependencies

When parallel execution is enabled, use the when: condition to set up step dependencies through the keywords, steps: and on:. For more information, see parallel pipeline execution.

Codefresh YAML for pipeline definitions
Variables in pipelines
Pull Requests and Branches
Hooks in pipelines