Developing a new Step
A Step is a task in a bigger CI/CD workflow: for example, the Git Clone Repository Step clones your Git repository at the start of a build while the Manage iOS Code Signing Step is performing code signing for your iOS app.
Sharing your team's custom Steps is optional: if the problem you are solving with a Step is specific to your team or company, you may not need to share it. As you can run a Step from your own machine or from any Git repository, your custom Steps do not have to be part of the Bitrise Step Library. However, if the Step solves a common problem, it is worth sharing it with the community.
For more info on sharing Steps with other users, check out the Sharing Steps guide.
Before deciding to create a new Step, don't forget to check if existing (first-party or third-party) Steps already cover your use case. Contributing new behavior to existing Steps is always preferred over creating a brand new Step.
A Step contains the code that performs the build task. You can configure the inputs and parameters that define the task, and view and reuse the outputs a Step generates. Reusing the output means that a subsequent Step in the workflow can use it as its input.
First-party Bitrise Steps are written in Go, but you can use any language and framework as long as you wrap it in a Bash step and set up its entrypoint. Each step has its own git repo that includes code and the step.yml metadata file. If you wish to make the Step available to other users, the <GlossTerm baseform="step.yml">step.yml</GlossTerm> file needs to be submitted to Bitrise Step Library (bitrise-steplib repository) so that it can be discovered and re-used in the Workflow Editor.
Creating the StepClick to copy link
We start with scaffolding the basic structure of the Step. Certain properties and inputs will be generated and assigned automatically. You can change these later. At the end of this process, you will have a step.yml file, a README.md file and either a main.go or a step.sh file in the repository.
During the Step creation process, you will be prompted to set a number of options. Note that you can change any of these before submitting your Step to Bitrise for review: the data will be included in the generated step.yml file that you can edit at your leisure later. During the initial Step creation process, you can use placeholders if you want to.
- Make sure to install the Bitrise CLI.
- Create a new directory and run
bitrise :step createinside it. - Follow the prompts to set up your Step.
You are all done! You should now have a step.yml, a README.md file, and either a main.go or a main.sh file.
The step.yml fileClick to copy link
The step.yml file contains all metadata that Bitrise systems need to know about a Step. It's where you define the inputs and outputs of your Step, as well as the dependencies required for the Step to function.
For a complete reference of the step.yml file, see About step code.
Naming and describing a StepClick to copy link
Every Step must have at least a title and a summary defined in the step.yml file. These appear on the Integrations page and in the Workflow Editor.
All text properties are rendered as Markdown, you are encouraged to use external links and other Markdown features.
TitleClick to copy link
It should be short and descriptive. Include the name of the service and the function it fulfils, such as Git Clone Repository.
The title is not the same as the unique Step ID: the ID is used in the configuration YAML files to reference the Step. For example, git-clone is the ID of the Git Clone Repository Step.
A few other guidelines to follow:
- Do not use the word ‘Step’.
- Use imperative verbs instead of nouns when possible. For example, instead of Script Runner, it should be Run Script.
- Make sure you use the correct name of a service or tool. For example, GitHub instead of Github.
- Do not include implementation details.
SummaryClick to copy link
A single line of the most significant information about the Step. Keep it below 100 characters.
The summary is visible by default on the Workflow Editor. If a user expands the summary, the Step’s description will be presented.
DescriptionClick to copy link
A detailed explanation of the Step. The description property contains a longer and more detailed description so that other users better understand how your Step works. It also contributes to search rankings when users search Steps in the Workflow Editor.
It should include:
- What the Step does.
- External services the Step interacts with (if any).
- Configuration, including the most important inputs.
- Troubleshooting information: potential issues and their solutions.
By default, the Step’s description is collapsed on the Workflow Editor and the summary is presented.
Step categoriesClick to copy link
There is another thing we’d like to know about your Step: what type of Step is it? As you can see on our Integrations page or on the Workflow Editor, Steps are sorted into different categories based on two factors: the platforms for which they are available and their functionality.
PlatformsClick to copy link
The relevant platforms are controlled by the project_type_tags attribute. If your Step is available for every platform or project type, do not specify project_type_tags. In any other case, select all platform types for which your Step is relevant and fully supported.
The available values are:
iosmacosandroidreact-nativecordovaionicflutterwebkotlin-multiplatform
CategoryClick to copy link
Functional categories are controlled by the type_tags attribute in the step.yml. One Step should have only a single type tag assigned to it. Use utility only if you believe none of the other types fit your Step.
The available values are:
buildcode-signtestdeploynotificationaccess-controlartifact-infoinstallerdependencyutilitysecurity
Step inputsClick to copy link
Inputs are the primary way for users to configure a Step. For example, the Git Clone Step has an input called branch, which controls the branch to check out.
title: Git Clone Repository
summary: Clone a repository to the specified path on the VM
inputs:
- branch: $BITRISE_GIT_BRANCH
Implementation-wise, Step inputs are Environment Variables with additional metadata and validation rules.
Step inputs are visible on the Workflow Editor: they are presented in the order as they appear in the step.yml. As such, required and frequently used inputs should be at the top.
A minimal input definition:
- install_defaults: "yes"
opts:
title: Installs default Codesign Files
value_options:
- "no"
- "yes"
The above input is defined as install_defaults, and its default value is yes. There is additional validation for the two valid input values.
Use lower case snake case style input keys (e.g. project_path, not ProjectPath or PROJECT_PATH).
There is no need to add domain-specific prefixes to the input keys, as inputs are only exposed at runtime for that single Step process. This means the project_path input will not overlap with subsequent Steps’ project_path inputs.
Step input values are strings, but you can define additional validation rules for the values (see below).
Provide default values for Step inputs if possible (and if it makes sense). That makes the Step configuration easier for Bitrise users.
Environment Variables must not be used as default values, unless:
- They are exposed by the Bitrise CLI or by bitrise.io.
- They are generated as an output by another Step (for example,
$BITRISE_IPA_PATH,$BITRISE_AAB_PATH).
This is because the Workflow Editor highlights required inputs without values to express the Step will not work without setting a valid value for the given input. If you set an Env Var, which does not have an automatically assigned value, as the default value for an input, the Workflow Editor will think the required input in question has a valid value set (even if the default Env Var has no value yet).
Also, there is no reason to suggest a certain name for an Environment Variable this way: users might have the same value assigned to an Env Var with a different name.
In addition to a key and a value, Step inputs are required to have an opts property. This property contains the different options that define how the inputs are passed to the code of the Step and how it is presented in the Workflow Editor. The possible values of the input can be set in opts as well. Let’s see an example.
Naming and describing Step inputsClick to copy link
A Step input can have a name, a summary, and a description, just like the Step itself. To define these:
- Include an
optsproperty with the Step input. - Under
opts, provide atitle, asummary, and adescriptionoption.
Both description and summary accept Markdown formatting.
title: User-friendly name of the input. It should not be too different from the input key, but you have more flexibility than with the raw YML key. For example,apk_signature_schemeandAPK Signature Scheme.summary: Short version of the description, which provides a quick overview of the input. On the Bitrise Workflow Editor, the summary of the inputs is presented by default when you click on a Step.description: This should provide a deeper, more detailed explanation of the input. By default, it is not visible in the Workflow Editor, unless the user clicks on the input in question.
Here is an example:
- track: alpha
opts:
title: Track
summary: The distribution track you want to assign the uploaded app to.
description: |-
The distribution track you want to assign the uploaded app to.
Can be one of the built-in tracks (internal, alpha, beta, production), or a custom track name you added in Google Play Developer Console.
is_required: true
Required inputsClick to copy link
When the input is marked as required (and the input has no default value defined), the user must provide a value, either a static string or an Environment Variable which resolves to a non-empty string.
A required input is also displayed as REQUIRED on the Workflow Editor and validated when saving changes.
To mark a Step input as required, use the is_required option of the opts property.
- keychain_password: $BITRISE_KEYCHAIN_PASSWORD
opts:
title: "Keychain password"
is_required: true
Using Env Vars as input values (is_expand)Click to copy link
As noted earlier, it is possible to use Environment Variables as the value of any given input. By default, Env Vars in Step inputs are expanded to the value behind that Env Var. This is controlled by the is_expand option of the opts property.
- project_path: $BITRISE_PROJECT_PATH
opts:
is_expand: true
If set to true, the value of $BITRISE_PROJECT_PATH is expanded and used as the string input of project_path. If set to false, the string value $BITRISE_PROJECT_PATH will be used without any expansion (and this particular Step will fail as it will not find the project location).
If possible, avoid reading Environment Variables without exposing them as Step inputs via step.yml. This helps users configure and understand Step behavior, and you don't need to write input validation by hand (required inputs, default values, value options, and so on).
Sensitive inputsClick to copy link
You can mark Step inputs as sensitive to avoid leaking them to build logs and UIs. Sensitive inputs only accept Secrets as values.
To mark a Step input as sensitive, use the is_sensitive option of the opts property. If set to true, the input will be displayed as SENSITIVE on the Workflow Editor and even if it gets logged in builds, the value is replaced with [REDACTED] in the build log.
is_expand optionIf you mark an input as sensitive, the is_expand option of the input also must be true, which is the default setting.
inputs:
- certificate_urls: $BITRISE_CERTIFICATE_URL
opts:
title: "Certificate URL"
is_sensitive: true
Input groupingClick to copy link
The category property is used to group related inputs. Inputs with a category are collapsed by default in the Workflow Editor, only displaying the category name.
- default_certificate_passphrase: $BITRISE_DEFAULT_CERTIFICATE_PASSPHRASE
opts:
category: Default code signing files
description: |
Certificate passphrase of the default certificate.
is_sensitive: true
title: Default certificate passphrase
Categories may be used if the Step has many related inputs, or infrequently used ones. The suggested maximum number of inputs in a group or in the root is six.
Please keep in mind, when designing Step categories, that:
- Required inputs should not be grouped as they are easy to miss when configuring the Step.
- Grouped inputs should be defined after inputs without a category.
Lists as input valuesClick to copy link
At the moment, a string list is not a supported Step input type. The following conventions are used for list-like inputs:
- We strongly recommend adding a
listsuffix to the key of the input (for example,input_path_list). - Step code should parse the input value by splitting at a newline character (\n) (for example,
first value\nsecond value). Don't forget to filter out empty items after the split. - Make sure the input
summaryanddescriptionclearly indicate that the input is a list of values, and how to format it.
Step outputsClick to copy link
Steps can generate outputs which can then be used in other Steps as inputs. That means that if a Step generates an artifact, the path to that artifact can be the input of another Step in the build. For example, the Xcode Archive & Export for iOS Step exposes the $BITRISE_IPA_PATH output which can then be used as an input value for the Deploy to Bitrise.io Step.
Outputs are defined in the step.yml file, under the outputs property. They have the same structure as Step inputs and the guidelines above also apply to them.
Lists as output valuesClick to copy link
The same limitation applies to Step outputs as to Step inputs, see the Lists as input values section above.
Setting conditions for running the StepClick to copy link
There are three properties that define whether a Step is run in a given Workflow or not: is_always_run, is_skippable and run_if.
These properties can be set in the step.yml file to govern the default behavior of the Step. User-provided values in the bitrise.yml file override these defaults.
is_always_run: By default, Steps do not run if a previous Step in the Workflow failed. However, if the is_always_run property is set to true, the Step runs regardless of the status of previous Steps in the Workflow. This can be useful for sending notifications or cleaning up resources after a failed step.
is_skippable: If a Step’s is_skippable property is set to true, the build will not fail and subsequent Steps will run even if this particular Step fails. Useful for optional tasks, which should not block the build if they fail.
run_if: Use the run_if property to make Step execution dependent on a certain condition. For example, you can configure a Step to only run in PR-triggered builds. Read more in our Enabling or disabling a Step conditionally guide about the possible use cases.
Step dependenciesClick to copy link
Step code often relies on local CLI tools or interacts with external APIs. Steps are run in various environments (macOS and Linux, different OS versions with different pre-installed tools), so it's important to make sure that your Step works in all of them.
You can declare dependencies from OS dependency managers (APT and Homebrew). A Step dependency is installed by the Bitrise CLI before the Step runs. List every dependency, even if you know that they are pre-installed on the Bitrise stacks as this might not be true for future stacks.
deps:
brew:
- name: cmake
apt_get:
- name: cmake
If a Step dependency is not packaged in OS dependency managers, the next best option is to install it at runtime. A few guidelines to follow:
- Add network retries for reliable downloads, such as
curl's--retry --connect-timeout 10 --max-time 30flags. - Use checksum and signature verification wherever possible.
- Make sure to only download from domains that you trust and control (or listed as the official source of the dependency).
- Do not use git submodules as a dependency management solution: they are not cloned when the Step is run.
Accessing files in the Step repo with an Env VarClick to copy link
If you need to keep a binary, assets or anything else required for your Step that should be bundled in the Step repository, then you can include them beside your step.yml file and the code of your Step. The Bitrise CLI automatically exports an Environment Variable called $BITRISE_STEP_SOURCE_DIR that allows you to access these files at any time.
For example, you can access a .jar file in the root of your Step’s repository like this: $BITRISE_STEP_SOURCE_DIR/mytool.jar