Skip to content

Context variables

Context variables are the inputs for the automation conditions or checks.

Legend

The icons indicate the availability status of each action.

  • Supported on GitHub
  • Supported on GitLab
  • Supported on Bitbucket
  • Under development and not available yet.
  • Open beta - Under development and currently available for all

Overview

Context

gitStream includes a collection of variables called contexts.

Structures

The following structures are used in the context objects:

Example of a context object

Partial example of a context object for a PR that changed few lines in a README.md file:

{
  "branch": {
    "name": "new-feature-branch",
    "base": "main",
    "diff": {
      "size": 50,
      "files_metadata": [
        {
          "original_file": "README.md",
          "new_file": "README.md",
          "deletions": 0,
          "additions": 2
        }
      ]
    },
    "num_of_commits": 1
  },
  "source": {
    "diff": {
      "files": [
        {
          "original_file": "README.md",
          "new_file": "README.md",
          "diff": "@@ -10,3 +10,5 @@ This project \n+\n+## Intro",
          "original_content": "This project \n",
          "new_content": "This project \n\n## Intro"
        }
      ]
    }
  },
  "repo": {
    "contributors": {
      "popeye": "46",
      "olive": "6"
    },
    "owner": "acme"
  },
  "files": [
    "README.md"
  ]
}

Reference

actions

The actions context contains outputs from actions that have been executed in previous automations within the same CM file. This enables creating conditional workflows based on the results of earlier actions.

First Action with Outputs

Currently, only the code-review action supports outputs. This feature will be expanded to other actions in future releases.

Values Type Description
actions Map Contains outputs from all completed actions, organized by automation ID
actions.<automation_id> Map Outputs from a specific automation (identified by its key in the automations section)
actions.<automation_id>.outputs Map All outputs produced by the action(s) in the specified automation
actions.<automation_id>.outputs.<output_name> Various Specific output value (type depends on the action - see individual action documentation)

Syntax Notes:

  • Use dot notation for automation names with underscores: actions.ai_code_review.outputs.is_LGTM
  • Use bracket notation for automation names with hyphens: actions['ai-code-review'].outputs.is_LGTM

Example Usage:

automations:
  # First automation: Run AI code review
  ai_code_review:
    if:
      - {{ not pr.draft }}
    run:
      - action: code-review@v1

  # Second automation: Only runs if the AI review found no issues
  auto_approve_on_clean_review:
    if:
      - {{ actions.ai_code_review.outputs.is_LGTM }}
    run:
      - action: approve@v1

  # Third automation: Add different labels based on review result
  label_based_on_review:
    if:
      - true
    run:
      - action: add-label@v1
        args:
          label: "{{ 'ai-approved' if actions.ai_code_review.outputs.is_LGTM else 'needs-review' }}"

Available Action Outputs:

Action Output Type Description
code-review@v1 is_LGTM Bool true if no issues were found, false if issues were detected

branch

The branch context contains info regarding the branch changes compared to the base branch.

Note

compared to the source context does not include actual source code.

Values Type Description
branch Map Includes the info related to the current branch
branch.author String The branch author (the user that did first commit in the branch). The formatted like author in git-log, e.g. Popeye <popeye@acme.com>
branch.author_name String The branch author name
branch.author_email String The branch author email
branch.base String The main branch, main
branch.commits.messages [String] A list with all the commit messages in this branch
branch.diff.size Integer The sum of line changed: additions, edits and deletions
branch.diff.files_metadata FileMetadata List of changed files including their relative path
branch.name String The current branch, feature-123-branch
branch.num_of_commits Integer The number of commits in the branch

The branch context doesn't include any source code, but only related metadata.

Example for using branch.name and branch.author to automatically approve and merge version bumps.

automations:
  dependabot:
    if:
      - {{ branch.name | includes(term="dependabot") }}
      - {{ branch.author | includes(term="dependabot") }}
    run:
      - action: approve@v1
      - action: add-label@v1
        args:
          label: "approved-dependabot"
      - action: merge@v1
        args:
          wait_for_all_checks: true
          squash_on_merge: true

Tip

The files context doesn't include deleted file, to identify both modified and deleted files use the branch.diff.files_metadata, for example:

{{ branch.diff.files_metadata | match(attr='file', regex=r/\.md$/) | every }}

env

The env context allows the user to pass data from the repo that is unavailable in the other context variables. Thus, the structure of the variable is not fixed and depends on user configuration.

To configure the env variable, add the env field to gitstream's workflow job configurations on .github/workflows/gitstream.yml. For more information, visit GitHub's guide for Using secrets in GitHub Actions

Note

env is read from the environment of the process that runs the automation, so what you can set depends on how gitStream runs:

  • On GitHub, the job-level env shown above reaches the automation directly.
  • On GitLab and Bitbucket, the automation runs in a container started by the pipeline in your cm project. A CI/CD variable is visible to the pipeline job, but it only reaches the automation if that pipeline forwards it to the container, for example -e MY_VAR=$MY_VAR on the docker run step.
  • In Managed mode the automation runs on gitStream's infrastructure, so its process environment is not yours to configure.
examle: add secrets to the env variable
...
jobs:
  gitStream:
    timeout-minutes: 5
    runs-on: ubuntu-latest
    name: gitStream workflow automation
    env:
      SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
...

To use the context variable, access to the env variable's fields as configured in gitstream.yml

example: use slack webhook secret
automations:
  send_slack:
    if:
      - true
    run:
      - action: send-slack-message@v1
        args:
          message: "Hello world :tada:."
          webhook_url: "{{ slack_webhook }}"

slack_webhook: {{ env.SLACK_WEBHOOK }}

files

The files context includes the list of changed files in the branch compared to the main branch.

Values Type Description
files [String] List of all changed files with their full path

For example, a typical files context can look like this:

[
  "README.md",
  "package.json",
  "src/app.js",
  "src/index.js",
  "docs/examples.md"
]

Example for checking if certain changes are made:

automations:
  ui_review:
    if:
      - {{ files | match(list=ui_templates_files) | some }}
    run:
      - action: add-reviewers@v1
        args:
          reviewers: [GitHubUser1, GitHubUser2]

ui_templates_files:
  - resources/app/ui_template.yml
  - resources/app/role_template.yml
  - resources/app/account_template.yml

pr

The pr context includes metadata related to the pull request.

Values Type Description
pr Map Includes the info related to the PR
pr.approvals [String] A list of the of reviewers that approved the PR
pr.assignees [String] A list of the people assigned to this pull request
pr.author String The PR author name
pr.author_is_org_member Bool true if the PR author is a member of the organization where gitStream is installed
pr.author_teams [String] The teams which the PR author is member of
pr.author_type String The kind of account that opened the PR: user, bot or organization. See note
pr.checks [Check] List of checks, names and status
pr.comments [Comment] List of PR comments objects
pr.commit_statuses [CommitStatus] List of commit status check objects from external CI systems.
pr.conflicted_files_count Integer The number files in the PR with conflicts
pr.conversations [Conversation] List of PR conversation objects, usually when reviewer have comments about the source code
pr.created_at String The date and time the PR was created
pr.description String The PR description text
pr.draft Bool true when the PR is marked as Draft/WIP
pr.labels [String] The labels that are attached to the PR
pr.number Integer The PR or MR Id number
pr.requested_changes [String] List of users that requested changes
pr.reviewers [String] The list of reviewers set for this PR
pr.reviews [Review] List of PR reviews
pr.source String The branch from which the PR originates
pr.status String The PR status: open, closed and merged. On GitLab the open state is reported as opened
pr.target String The branch the PR is intended merged into
pr.title String The PR title
pr.unresolved_threads Integer The number of open review comments in the PR
pr.updated_at String The date and time the PR was last updated
pr.url String A link to the PR on
PR author type

pr.author_type reports the kind of account that opened the PR, so automations can skip machine-authored changes without maintaining a list of bot names:

automations:
  senior_review:
    if:
      - {{ pr.author_type != 'bot' }}
    run:
      - action: add-reviewers@v1
        args:
          reviewers: [senior-devs]

The value is lowercase, like pr.status and repo.visibility.

Two limitations are worth knowing:

  • On GitHub, only GitHub Apps report bot. Automation that authenticates with a personal access token - self-hosted Renovate, in-house CI bots - reports user.
  • On Bitbucket, apps report bot and workspaces report organization, but the bot user that Bitbucket creates for each access token still reports user.

The value is empty when gitStream could not determine the account kind. For full coverage, keep matching on the author name as well:

is:
  bot_author: {{ pr.author_type == 'bot' or (pr.author | match(list=["[bot]", "dependabot"]) | some) }}

Example for checking the PR title includes a Jira ticket:

automations:
  check_jira_ticket:
    if:
      - {{ not has.jira_ticket }}
    run:
      - action: add-label@v1
        args:
          label: "missing-ticket"
          color: 'F6443B'

has:
  jira_ticket: {{ pr.title | includes(regex=r/^\[?\w{3,4}-\d{1,6}\]?(\s|-|_).{20,}$/) }}

repo

The repo context includes metadata related to the repo.

Values Type Description
repo Map Includes the info related to the current repo
repo.age Integer Number of days since first commit (of any user)
repo.author_age Integer number of days since first commit to this repo
repo.blame GitBlame The percentage of each user's lines in a file, the list includes all changed files in the branch. The ratio field sorts the list
repo.contributors Contributor List of contributors in the repo
repo.git_activity GitActivity Per file and user, the number of lines changed every week for the last 52 weeks
repo.languages Map Lists the languages used in the specified repository. The returned object is a map of key-value pairs representing a language and the percentage of bytes in that language within the code.
repo.name String Repository name
repo.owner String Repository owner account name
repo.provider String The Git cloud provider name. Value is one of: github, gitlab, or bitbucket
repo.visibility String The visibility of the source branch repo. Value is one of: private, internal, or public

source

The source context includes a list of FileDiff objects that can be used to get insights based on code changes. The changes compared to the latest main branch.

Values Type Description
source.diff.files FileDiff List of changed files with their code changes

The source context include all code changes, it is not safe to share it with unknown services.

Check structure

{
  "name": String, # The check name
  "status": String, # The check status: `queued`, `in_progress`, `completed`
  "conclusion": String, # The check conclusion: `action_required`, `cancelled`, `failure` `neutral`, `success`, `skipped`, `stale`, `timed_out`
  "title": String, # the check title
  "total_time": Integer, # the total time the check took, in Seconds
}

Comment structure

{
  "commenter": String, # The user that add the comment
  "content": String, # The comment body
  "created_at": String, # The time on which the comment was created
  "id": String, # The provider's identifier for the comment
  "updated_at": String, # The time on which the comment was last updated. Not available on GitHub
}

CommitStatus structure

Represents the status of external CI systems like Docker builds or test results. Note gitStream doesn't respond to commit status events, only collects them when other events trigger.

{
  "state": String, # The status of the check: `pending`, `success`, `failure`, `error`
  "context": String, # The identifier for the CI system or check (e.g., "continuous-integration/jenkins")
  "description": String # Human-readable description of the status (e.g., "The build succeeded!")
}

Example:

[
  {
    "state": "pending",
    "context": "continuous-integration/jenkins",
    "description": "The build succeeded!"
  }
]

Conversation structure

The fields available depend on the provider:

{
  "commenter": String, # The user that add the comment
  "content": String, # The comment body
  # GitHub only:
  "start_line": Integer, # The first line marked for this comment
  "end_line": Integer, # The last line marked for this comment
  "is_resolved": Boolean, # `true` when marked as resolved
  # GitLab only:
  "created_at": String, # The time on which the comment was created
  "updated_at": String, # The time on which the comment was updated
  "id": String, # The provider's identifier for the comment
  "file_path": String, # The file the comment is attached to, including its path
}

Contributor structure

The repo.contributors mapping includes a list of Contributor, where the user name is used as dynamic key:

{
  USER_NAME: Integer # Number of commits
}

FileDiff structure

The source.diff.files mapping includes a list of FileDiff:

{
  "diff": String, #  The content in diff format `+` for additions, `-` for deletions
  "new_content": String, # The new content in this branch
  "new_file": String, # The name of the file after the changes, including its path
  "original_content": String, #  The content as is in the `main` branch
  "original_file": String, #  The name of the file before the changes, including its path
}

FileMetadata structure

The branch.diff.files_metadata mapping includes a list of FileMetadata:

{
  "additions": Integer, # The number of lines edited or added to the file
  "deletions": Integer, # The number of lines removed from the file
  "file": String, # The name of the file after the changes, or before them when the file was deleted
  "new_file": String, # The name of the file after the changes, including its path
  "original_file": String, # The name of the file before the changes, empty for a new file
}

For example, sum additions in javascript code files:

{{ branch.diff.files_metadata | filter(attr='new_file', regex=r/\.js$|\.ts$/) | map(attr='additions') | sum }}

GitActivity structure

This structure include per changed file, for every user, the number of lines changed every week for the last 52 weeks.

{
  FILE_NAME: # The file name and path
  {
    # The git user identifier (String)
    GIT_USER: {
      "week_INDEX": Integer # Number of lines changed that week
      # ... for the last 52 weeks
    }
  }
}

For example:

{
  "src/utils/service.js": {
    "popeye <popeye@acme.com>": {
      "week_1": 20,
      "week_2": 15,
      "week_10": 250
    },
    "olive <olive@acme.com>": {
      "week_1": 3,
      "week_3": 50,
      "week_52": 250
    }
  },
  "README.md": {
    "popeye <popeye@acme.com>": {
      "week_2": 15,
      "week_3": 10
    }
  }
}

GitBlame structure

For each file, a list of user's blame ratio.

{
  FILE_NAME: # The file name and path
  {
    # The git user identifier (String)
    GIT_USER: Integer, # Precentage 0-100, ratio of user's lines / total lines in file
  }
}

For example:

{
  "src/utils/service.js": {
    "popeye <popeye@acme.com>": 78,
    "olive <olive@acme.com>": 22,
  },
  "README.md": {
    "popeye <popeye@acme.com>": 13,
    "olive <olive@acme.com>": 22,
    "brutus <brutus@acme.com>": 65,
  }
}

Review structure

{
  "commenter": String, # The user that add the comment
  "content": String, # The comment body
  "state": String, # Either `approved`, `changes_requested`, `commented`, `pending`, `submitted`
  "conversations": [Conversation], # Conversations that are relvant to this Review feedback
}

Note

The conversations nested in a Review carry commenter, content, created_at, state and id - not the line and resolution fields of a top-level Conversation.