Enhanced Environment Variables in Bitrise for intelligent automation

Scrolling through the build log to find what caused your CI pipeline to fail isn’t fun. Or even spending hours inventing custom logic to automate workflows based on who triggered a build or what files changed? There might be a better solution.

Enhanced Environment Variables have recently arrived – a suite of new variables designed to give you better control over Bitrise CI.

Unlocking new workflows with enhanced environment variables

Here's a summary of all the new environment variables available in Bitrise:

Environment variable Description
👩‍🚒 Build failure diagnostics
BITRISE_FAILED_STEP_TITLE The title of the step that first fails in a build. Set when a step fails.
BITRISE_FAILED_STEP_ERROR_MESSAGE The error message for the first step that fails the build. Set when a step fails.
🚀 Build trigger information
BITRISE_TRIGGER_BY Identifies who/what triggered the build (username).
  • The Git user's name when a Git provider triggers the build.
  • The Bitrise user's name if the build is triggered manually from the Bitrise web UI.
  • The value specified in the triggered_by build parameter if the build is triggered any other way (such as scheduled builds or builds triggered by the API).
BITRISE_TRIGGER_METHOD Method of triggering (schedule, webhook, manual)
✅ Pull request intelligence
BITRISE_GIT_PULL_REQUEST_COMMENT The comment message from a pull request is available when using the PR comment trigger for GitHub, Gitlab, and Bitbucket.
BITRISE_GIT_PULL_REQUEST_COMMENT_ID The unique ID of the PR comment is available when using the PR comment trigger for GitHub, GitLab, and Bitbucket.
BITRISE_GIT_PULL_REQUEST_LABELS List of PR labels (new and existing). Available for Label change trigger.
👩🏽‍💻 Code change awareness
BITRISE_GIT_CHANGED_FILES File paths changed in the PR or push. Available for Push or PR triggers.
BITRISE_GIT_COMMIT_MESSAGES Commit messages included in PR or push. Available for Push or PR triggers.

Sometimes your CI workflows require more intelligent automation and better debugging capabilities. These nifty additions to Bitrise give mobile development and DevOps teams the contextual information needed to create more thoughtful, efficient workflows. Let’s dive into each of these and see some real-world examples of where they can be used.

👩‍🚒 Build failure diagnostics

When a build fails, the traditional approach involves combing through verbose logs to pinpoint exactly what went wrong. The new failure diagnostics variables can speed this up a little bit.

BITRISE_FAILED_STEP_TITLE The title of the step that first fails in a build. Set when a step fails.
BITRISE_FAILED_STEP_ERROR_MESSAGE The error message of the step that first fails. Set when a step fails.

Example 1: Smart Slack notifications

Instead of generic "build failed" notifications, send Slack messages with precise information about what went wrong. Notice the usage of new variables in the Slack message step:

1workflows:
2  run_tests:
3    steps:
4    - git-clone@8: {}
5    - xcode-test@6:
6        inputs:
7        - project_path: "$BITRISE_PROJECT_PATH"
8        - scheme: "$BITRISE_SCHEME"
9        - destination: platform=iOS Simulator,name=Bitrise iOS default,OS=9.1
10    - deploy-to-bitrise-io@2: {}
11    - slack@4:
12        run_if: "{{.IsBuildFailed}}"
13        inputs:
14        - workspace_slack_integration_id: "$SLACK_INTEGRATION_ID"
15        - text: |-
16            Failing step: $BITRISE_FAILED_STEP_TITLE
17            Error: $BITRISE_FAILED_STEP_ERROR_MESSAGE

Below is the Slack message when the above build fails:

Xcode test failure slack message

Example 2: Team-specific failure routing

Different failures might require attention from different teams. Route notifications based on which step failed: In this example, the workflow notifies iOS devs about Xcode test failures and platform engineers about other build failures. Notice the run_if conditions in the Slack message steps.

1workflows:
2  run_tests:
3    steps:
4    - git-clone@8: {}
5    - xcode-test@6:
6        inputs:
7        - project_path: "$BITRISE_PROJECT_PATH"
8        - scheme: "$BITRISE_SCHEME"
9        - destination: platform=iOS Simulator,name=Bitrise iOS default,OS=9.1
10    - deploy-to-bitrise-io@2: {}
11    - slack@4:
12        run_if: "{{enveq \"BITRISE_FAILED_STEP_TITLE\" \"Xcode Test for iOS\"}}"
13        inputs:
14        - workspace_slack_integration_id: "$IOS_DEVS_SLACK_INTEGRATION_ID"
15        - text: |-
16            Xcode Test for iOS has failed with error:
17            $BITRISE_FAILED_STEP_ERROR_MESSAGE
18    - slack@4:
19        run_if: "{{enveq \"BITRISE_FAILED_STEP_TITLE\" \"Xcode Test for iOS\" | not}}"
20        inputs:
21        - workspace_slack_integration_id: "$PLATFROM_ENGINEERS_SLACK_INTEGRATION_ID"
22        - text: |-
23            $BITRISE_FAILED_STEP_TITLE has failed with error:
24            $BITRISE_FAILED_STEP_ERROR_MESSAGE

Xcode test failure Slack message (sent to $IOS_DEVS_SLACK_INTEGRATION_ID ):

Xcode test failure Slack message
Git clone failure Slack message

🚀 Build trigger information

Build trigger variables help you understand the origin of each build, enabling you to create trigger-aware workflows:

BITRISE_TRIGGER_BY Identifies who/what triggered the build (username).
BITRISE_TRIGGER_METHOD Method of triggering (schedule, webhook, manual)

Example 1 - Elevated security for third-party contributors

This workflow runs extensive security scans for external contributors and standard scans for internal team members based on the email domain in BITRISE_TRIGGER_BY.

1workflows:
2  primary:
3    steps:
4    - git-clone@8: {}
5    - script@1:
6        inputs:
7        - content: |-
8            #!/bin/bash
9            # Run extended security scans for external contributors
10            if [[ "$BITRISE_TRIGGER_BY" != *"@yourcompany.com"* ]]; then
11              envman add --key SECURITY_SCAN_LEVEL --value "extensive"
12            else
13              envman add --key SECURITY_SCAN_LEVEL --value "standard"
14            fi
15    - dependency-security-scan@0:
16        inputs:
17        - scan_level: "$SECURITY_SCAN_LEVEL"

Example 2 - Audit trail for production deployments

This workflow deploys an app to the App Store while maintaining an audit trail of who triggered the deployment and when, storing these records in Google Cloud Storage.

1workflows:
2  production_deploy:
3    steps:
4    - git-clone@8: {}
5    - script@1:
6        inputs:
7        - content: |-
8            #!/bin/bash
9            echo "Production deployment triggered by: $BITRISE_TRIGGER_BY at $(date)" >> deployment_audit.log
10            echo "Trigger method: $BITRISE_TRIGGER_METHOD" >> deployment_audit.log
11    - google-cloud-storage-upload@1:
12        inputs:
13        - source_path: "deployment_audit.log"
14        - bucket_url: "gs://your-company-audit-logs/"
15    - deploy-to-itunesconnect-application-loader@1: {}

Example 3 - Leaner scheduled builds

Conserve resources during automated scheduled builds by skipping resource-intensive steps:

1workflows:
2  nightly_build:
3    steps:
4    - git-clone@8: {}
5    - script@1:
6        inputs:
7        - content: |-
8            #!/bin/bash
9            if [[ "$BITRISE_TRIGGER_METHOD" == "schedule" ]]; then
10              # Skip resource-intensive UI tests on scheduled builds
11              envman add --key SKIP_UI_TESTS --value "true"
12              # Use lower simulator spec for overnight builds
13              envman add --key SIMULATOR_DEVICE --value "iPhone 8"
14            else
15              envman add --key SKIP_UI_TESTS --value "false"
16              envman add --key SIMULATOR_DEVICE --value "iPhone 14 Pro"
17            fi
18    - xcode-test@6:
19        run_if: "{{enveq \"SKIP_UI_TESTS\" \"false\"}}"
20        inputs:
21        - destination: "platform=iOS Simulator,name=$SIMULATOR_DEVICE"

Example 4 - Intelligent notification routing

Send notifications to different channels based on who triggered the build:

1workflows:
2  release_build:
3    steps:
4    - git-clone@8: {}
5    - xcode-archive@4: {}
6    - script@1:
7        inputs:
8        - content: |-
9            #!/bin/bash
10            # Determine who should receive notifications
11            if [[ "$BITRISE_TRIGGER_BY" == "jenkins-automation" ]]; then
12              # CI system triggered this build
13              envman add --key NOTIFY_CHANNEL --value "ci-automation"
14            elif [[ "$BITRISE_TRIGGER_BY" == *"product-manager"* ]]; then
15              # PM triggered this build
16              envman add --key NOTIFY_CHANNEL --value "product-releases"
17            else
18              # Developer triggered this build
19              envman add --key NOTIFY_CHANNEL --value "engineering"
20            fi
21    - slack@4:
22        inputs:
23        - channel: "$NOTIFY_CHANNEL"
24        - text: "Build completed for version $BITRISE_GIT_TAG"

Keep Slack channels focused.

✅ Pull request intelligence

BITRISE_GIT_PULL_REQUEST_COMMENT The comment message from a pull request. Available when using PR comment trigger for GitHub, Gitlab, & Bitbucket.
BITRISE_GIT_PULL_REQUEST_COMMENT_ID The unique ID of the PR comment. Available when using PR comment trigger for GitHub, Gitlab, & Bitbucket.
BITRISE_GIT_PULL_REQUEST_LABELS List of PR labels (new and existing). Available when using Label change trigger for GitHub, Gitlab, & Bitbucket.

Pull request variables give you insight into PR comments and labels, enabling comment-driven workflows and label-based automation.

Example 1 - Automated PR comment responses

The below example replies to the original PR comment with the results from the build.

1format_version: 11
2default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
3
4workflows:
5  comment_driven_actions:
6    steps:
7    - git-clone@8: {}
8    
9    - script@1:
10        title: Process PR Comment Commands
11        inputs:
12        - content: |
13            #!/bin/bash
14            set -e
15            
16            echo "PR Comment: $BITRISE_GIT_PULL_REQUEST_COMMENT"
17            echo "Comment ID: $BITRISE_GIT_PULL_REQUEST_COMMENT_ID"
18            
19            # Set default action flags
20            RUN_SCREENSHOT_TESTS="false"
21            DEPLOY_TO_TESTFLIGHT="false"
22            
23            # Check for specific commands in the comment
24            if [[ "$BITRISE_GIT_PULL_REQUEST_COMMENT" == *"/test-screenshots"* ]]; then
25              echo "Screenshot test command detected"
26              RUN_SCREENSHOT_TESTS="true"
27            fi
28            
29            if [[ "$BITRISE_GIT_PULL_REQUEST_COMMENT" == *"/deploy-testflight"* ]]; then
30              echo "TestFlight deployment command detected"
31              DEPLOY_TO_TESTFLIGHT="true"
32            fi
33            
34            # Save the comment ID to reply to it later
35            envman add --key REPLY_TO_COMMENT_ID --value "$BITRISE_GIT_PULL_REQUEST_COMMENT_ID"
36            envman add --key RUN_SCREENSHOT_TESTS --value "$RUN_SCREENSHOT_TESTS"
37            envman add --key DEPLOY_TO_TESTFLIGHT --value "$DEPLOY_TO_TESTFLIGHT"
38    
39    - script@1:
40        title: Run Screenshot Tests
41        run_if: '{{enveq "RUN_SCREENSHOT_TESTS" "true"}}'
42        inputs:
43        - content: |
44            #!/bin/bash
45            echo "Running screenshot comparison tests..."
46            # Commands to run screenshot tests
47            mkdir -p screenshots
48            echo "Screenshot results would be generated here" > screenshots/results.txt
49            
50            # Create flag file to indicate test was run
51            echo "true" > screenshots_run.txt
52    
53    - xcode-archive@4:
54        title: Build for TestFlight
55        run_if: '{{enveq "DEPLOY_TO_TESTFLIGHT" "true"}}'
56        inputs:
57        - export_method: app-store
58    
59    - deploy-to-itunesconnect-deliver@2:
60        title: Deploy to TestFlight
61        run_if: '{{enveq "DEPLOY_TO_TESTFLIGHT" "true"}}'
62        inputs:
63        - itunescon_user: "$ITUNES_CONNECT_USER"
64        - password: "$ITUNES_CONNECT_PASSWORD"
65        - app_id: "$IOS_APP_ID"
66        - submit_for_beta_review: "no"
67        - skip_metadata: "yes"
68        - skip_screenshots: "yes"
69    
70    - github-status@2:
71        title: Report Status Back to PR
72        inputs:
73        - auth_token: "$GITHUB_TOKEN"
74        - status_identifier: "bitrise-ci"
75        - repository_url: "$GIT_REPOSITORY_URL"
76        - commit_hash: "$GIT_CLONE_COMMIT_HASH"
77    
78    - script@1:
79        title: Reply to PR Comment
80        run_if: '{{ne (getenv "REPLY_TO_COMMENT_ID") ""}}'
81        inputs:
82        - content: |
83            #!/bin/bash
84            if [ -n "$GITHUB_TOKEN" ] && [ -n "$REPLY_TO_COMMENT_ID" ]; then
85              # Extract repo info from repository URL (assuming GitHub)
86              REPO_URL=$(echo "$GIT_REPOSITORY_URL" | sed 's/.*github.com[\/:]//g' | sed 's/\.git$//g')
87              
88              # Prepare the response message
89              MESSAGE="✅ Command processed!"
90              
91              if [ "$RUN_SCREENSHOT_TESTS" == "true" ] && [ -f "screenshots_run.txt" ]; then
92                MESSAGE="$MESSAGE\n\n📸 Screenshot tests completed."
93              fi
94              
95              if [ "$DEPLOY_TO_TESTFLIGHT" == "true" ]; then
96                MESSAGE="$MESSAGE\n\n🚀 Deployed to TestFlight."
97              fi
98              
99              # Post reply comment via GitHub API
100              curl -X POST \
101                -H "Authorization: token $GITHUB_TOKEN" \
102                -H "Content-Type: application/json" \
103                -d "{\"body\": \"$MESSAGE\"}" \
104                "https://api.github.com/repos/$REPO_URL/issues/comments/$REPLY_TO_COMMENT_ID/replies" || \
105                echo "Unable to post reply comment. This might be because the API doesn't support comment replies or due to permissions."
106            else
107              echo "Missing GitHub token or comment ID, cannot reply to PR comment"
108            fi

How to use the above example:

Comment on your PR with these commands:

  • /test-screenshots: Triggers screenshot comparison tests
  • /deploy-testflight: Builds and deploys the app to TestFlight

The workflow will process these commands and reply to the original comment with the results of the requested actions.

👩🏽‍💻 Code change awareness

BITRISE_GIT_CHANGED_FILES File paths changed in the PR or push. Available for Push or PR triggers for GitHub, Gitlab, & Bitbucket.
BITRISE_GIT_COMMIT_MESSAGES Commit messages included in the PR or push. Available for Push or PR triggers for GitHub, Gitlab, & Bitbucket.

Example 1 - Conditional test execution

Only run certain tests when relevant files change:

1workflows:
2  primary:
3    steps:
4    - git-clone@8: {}
5    - script@1:
6        inputs:
7        - content: |-
8            #!/bin/bash
9            if [[ "$BITRISE_GIT_CHANGED_FILES" == *"/ui/"* ]]; then
10              envman add --key RUN_UI_TESTS --value "true"
11            fi
12            if [[ "$BITRISE_GIT_CHANGED_FILES" == *"/database/"* ]]; then
13              envman add --key RUN_DB_TESTS --value "true"
14            fi
15    - xcode-test@6:
16        run_if: "{{enveq \"RUN_UI_TESTS\" \"true\"}}"
17        inputs:
18        - test_plan: UITests
19    - xcode-test@6:
20        run_if: "{{enveq \"RUN_DB_TESTS\" \"true\"}}"
21        inputs:
22        - test_plan: DatabaseTests

Example 2 - Deploy based on commit messages or labels

Deploy to production only when commit messages or PR labels indicate a release:

1workflows:
2  deploy:
3    steps:
4    - git-clone@8: {}
5    - script@1:
6        inputs:
7        - content: |-
8            #!/bin/bash
9            if [[ "$BITRISE_GIT_COMMIT_MESSAGES" == *"[deploy-prod]"* ]] || [[ "$BITRISE_GIT_PULL_REQUEST_LABELS" == *"production-ready"* ]]; then
10              envman add --key DEPLOY_TARGET --value "production"
11            else
12              envman add --key DEPLOY_TARGET --value "staging"
13            fi
14    - deploy-to-bitrise-io@2: {}
15    - firebase-app-distribution@0:
16        inputs:
17        - app: "$FIREBASE_APP_ID_$DEPLOY_TARGET"
18        - groups: "$FIREBASE_GROUPS_$DEPLOY_TARGET"

Example 3 - Trigger security scans for sensitive changes

Run security scans only when critical files change:

1workflows:
2  build:
3    steps:
4    - git-clone@8: {}
5    - script@1:
6        inputs:
7        - content: |-
8            #!/bin/bash
9            if [[ "$BITRISE_GIT_CHANGED_FILES" == *"Podfile"* ]] || [[ "$BITRISE_GIT_CHANGED_FILES" == *"Gemfile"* ]]; then
10              envman add --key RUN_SECURITY_SCAN --value "true"
11            fi
12    - dependency-security-scan@0:
13        run_if: "{{enveq \"RUN_SECURITY_SCAN\" \"true\"}}"

Level up your Bitrise CI

These new environment variables are another step on the journey to making Bitrise unrivalled as the most intelligent, innovative, and developer-friendly mobile CI/CD platform. By providing rich contextual information about builds, failures, triggers, and code changes, you can create more efficient, targeted, and automated workflows.

We're excited to see how you'll use these new variables to streamline your mobile CI/CD workflows. Questions or creative use cases? Reach out to our support team or drop a message on our socials!

Happy building!

Get Started for free

Start building now, choose a plan later.

Sign Up

Get started for free

Start building now, choose a plan later.