We're going to go through creating a step (properly) and sharing it with the Bitrise community. Tutorial based on a real step created and written by SΓ©bastien Pousse.
Guest blog post by SΓ©bastien Pousse, the original appeared on Developers @ Yellow Pages in French.
SΓ©bastien works for PagesJaunes (French Yellow Pages) as head of innovation and mobile strategy and he likes sports, especially climbing, squash, mountain biking and running.
Summary
Bitrise is a solution that allows you to industrialize your mobile compilations (iOS, Android, Xamarin, ReactNative, Ionic etc.) by making dedicated virtual machines available for a defined period of time.
These virtual machines are launched on demand following trigger events (activity on your source code repositories for example) and execute a workflow containing a set of steps.
A step is a cogwheel of your workflow, that will run and perform a specific task.
Bitrise offers a catalogue of steps already written:
The objective of this tutorial
In this tutorial I'll assist you in the creation of a step, explaining all the essential steps until the submission of the step to the Bitrise team to appear in the catalogue above.
Customer in the command line
Bitrise is a SAAS solution but it is still possible to work locally with it. For that, we will first install a Bitrise client in CLI with homebrew .
brew install bitrise
Setup
We will do updates with a bitrise setup, which will take care of updating the kernel tools like envman, stepman. It'll also install Bitrise plugins, in particular, the one for steps that is important for us.
bitrise setup
βββββββ βββββββββββββββββββ βββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββ βββ βββββββββββββββββββββββββ
βββββββββββ βββ βββββββββββββββββββββββββ
βββββββββββ βββ βββ ββββββββββββββββββββββ
βββββββ βββ βββ βββ ββββββββββββββββββββββ
version: 1.12.0
Setup
Full setup: false
Clean setup: false
Detected OS: darwin
Checking Bitrise Core tools...
[OK] envman (1.1.9): /Users/spousse/.bitrise/tools/envman
[OK] stepman (0.9.37): /Users/spousse/.bitrise/tools/stepman
Doing OS X specific setup
Checking required tools...
[OK] Homebrew 1.5.2: /usr/local/bin/brew
[OK] Homebrew/homebrew-core (git revision f4c7d; last commit 2018-01-30)
[OK] xcodebuild (Xcode 8.1 | Build version 8B62): /usr/bin/xcodebuild
[OK] active Xcode (Command Line Tools) path (xcode-select --print-path): /Applications/Xcode.app/Contents/Developer
Checking Bitrise Plugins...
[OK] Plugin workflow-editor (1.1.3): /Users/spousse/.bitrise/plugins/workflow-editor
[OK] Plugin analytics (0.9.11): /Users/spousse/.bitrise/plugins/analytics
[OK] Plugin init (1.0.1): /Users/spousse/.bitrise/plugins/init
[OK] Plugin step (0.9.5): /Users/spousse/.bitrise/plugins/step
Checking Bitrise Toolkits...
[OK] go (1.9.2): /Users/spousse/.bitrise/toolkits/go/inst/go/bin/go
[OK] bash (GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)): /bin/bash
All the required tools are installed! We're ready to rock!!
To start using bitrise:
* cd into your project's directory (if you're not there already)
* call: bitrise init
* follow the guide
That's all :)
β
Initialization of the step
Let's get down to business. We will start with an actual case: at the moment I need to be able to upload a build to wetransfer to send it to a third party.
We will design a step which uploads a file on wetransfer.
The small novelty is that since version 1.6 of the Bitrise client in CLI, the creation of a step is simplified. Go to a working directory and run the command bitrise :step create
bitrise :step create
Who are you / who's the author? : kawaiseb
What's the title / name of the Step? : wetransfer
Generated Step ID (from provided Title): wetransfer
Please provide a summary : Upload files to wetransfer and share a short url to download
Please provide a description : This step send files to wetransfer. Wetransfer give you a short url to download files. Limit 2GO.
β
Answer all the questions above.
What's the primary category of this Step?
Please select from the list:
[1] : access-control
[2] : artifact-info
[3] : installer
[4] : deploy
[5] : utility
[6] : dependency
[7] : code-sign
[8] : build
[9] : test
[10] : notification
(type in the option's number, then hit Enter) : 5
β
Choose a category. I chose utility.
Toolkit: the entry/base language of the Step.
Our recommendation is to use Bash for very simple Steps
and for more complex ones use another language, one which we have toolkit support for.
If you're just getting started with Step development our suggestion is to select Bash,
as that's the easiest option. It's possible to convert the step later, if needed.
Note: Of course even if you select e.g. Bash as the entry language, you can run other scripts from there,
so it's possible to write the majority of the step's code in e.g. Ruby,
and have an entry Bash script which does nothing else except running the Ruby script.
Which toolkit (language) would you like to use?
Please select from the list:
[1] : bash
[2] : go
(type in the option's number, then hit Enter) : 1
In my case, I chose to do the step in nodejs and the script will be launched in bash so 1) it is.
Website & source code URL:
Will you host the source code on GitHub? [YES/no]: YES
What's your GitHub username (user/org where you'll register the step's repository)? : kawaiseb
We'll use https://github.com/kawaiseb/bitrise-step-wetransfer as the website/repo URL for this step.
Please when you create the repository on GitHub for the step
create it under the user/org: kawaiseb
and the name of the repository should be: bitrise-step-wetransfer
Creating Step directory at: /Users/spousse/bitrise-step-wetransfer
* [OK] created: /Users/spousse/bitrise-step-wetransfer/README.md
* [OK] created: /Users/spousse/bitrise-step-wetransfer/LICENSE
* [OK] created: /Users/spousse/bitrise-step-wetransfer/.gitignore
* [OK] created: /Users/spousse/bitrise-step-wetransfer/step.yml
* [OK] created: /Users/spousse/bitrise-step-wetransfer/bitrise.yml
* [OK] created: /Users/spousse/bitrise-step-wetransfer/.bitrise.secrets.yml
* [OK] created: /Users/spousse/bitrise-step-wetransfer/step.sh
Initializing git repository in step directory ...
$ git "init"
$ git "remote" "add" "origin" "https://github.com/kawaiseb/bitrise-step-wetransfer"
Step is ready!
You can find it at: /Users/spousse/bitrise-step-wetransfer
TIP: cd into /Users/spousse/bitrise-step-wetransfer and run bitrise run test for a quick test drive!
I've decided to store the step on GitHub. The repository of my step is created, as well as all the necessary files.
Let's check that the test workflow starts all right...
bitrise run test
Achtung!
There are some basic rules to know before you start:
- Every input, output and parameter in any step is an Environment Variable
- The value of an Environment Variable can only be a String
- If you create an environment variable in a child process, it will not be visible from the parent process
I repeat these here because these caused me some trouble π (Read more about these concepts here.)
Workflows
bitrise.yml
This file is actually the main configuration file. It will allow you to create one or more workflow(s) and define one or more step(s) to execute. This is your scheduler, which you will find in the cloud. This file is in YAML format.
Let's look at some elements of the file.
Environment variables
We have a series of variables defined globally to our application. These variables are reusable from anywhere thereafter.
app:
envs:
# If you want to share this step into a StepLib
- BITRISE_STEP_ID: wetransfer
- BITRISE_STEP_VERSION: "0.0.4"
- BITRISE_STEP_GIT_CLONE_URL: https://github.com/kawaiseb/bitrise-step-wetransfer.git
- MY_STEPLIB_REPO_FORK_GIT_URL: https://github.com/kawaiseb/bitrise-steplib
For the variable MY_STEPLIB_REPO_FORK_GIT_URL, the bitrise-steplib project will have to be forked. Indeed it is in this project that our step will be placed in the end.
The test workflow
The test workflow contains a step with a bash script that will display the environment variable declared above. Nothing really exciting at the moment.
workflows:
test:
steps:
- script:
inputs:
- content: |
#!/bin/bash
echo "Just an example 'secrets' print."
echo "The value of 'A_SECRET_PARAM' is: $A_SECRET_PARAM"
The test workflow will later allow you to test your step in the command line and also on Bitrise.
Specification
Back to the step. I will declare all the parameters I need for uploading to wetransfer. Here's what I need:
- The sender's email address
- The email address of the recipient(s)
- A short message to accompany the link
- The files to send to wetransfer
It's as simple as that. Once the problem is posed, here is how to solve it.
Production
The description of the step (step.yml)
You can find the source here. In this file, we will describe the operation of the step and set all the parameters necessary for its proper functioning.
I will not go into all the details, I'll only deal with the input variables which are the most interesting in our case:
inputs:
# All parameter we need to upload files to wetransfer
- wtu_mailsender:
opts:
title: Email of the sender
is_expand: true
is_required: true
- wtu_mailreceiver:
opts:
title: One or more email separated by comma for receiver
is_required: true
This will materialize as follows:
The is_expand statement is used to directly expand the description field
The is_required statement specifies that the variable is required.
And so on for all the expected parameters. There is also a possibility of making lists.
For example, for the debug mode I just want to make an enum {yes, no}.
# Debug mode deactivated by default
- wtu_debug_mode: "no"
opts:
title: "Debug mode ?"
description: |
Step prints additional debug information if this option
is enabled
is_expand: true
is_required: false
value_options:
- "yes"
- "no"
β
Fill in the form ...
Execution of the step (step.sh)
You can find the source here. This file will be executed each time the step is launched.
Following feedback from Bitrise, I had to make some changes. The most important thing is not to change the working directory. This is advocated by Bitrise.
In the end, the step.sh will launch my nodejs script with the set of parameters that have been entered in the configuration interface of the step.
#!/bin/bash
set -ex
THIS_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
npm install --prefix $THIS_SCRIPT_DIR wetransfert --save
$THIS_SCRIPT_DIR/upload.js "${wtu_debug_mode}" "${wtu_mailsender}" "${wtu_mailreceiver}" "${wtu_filepath}" "${wtu_message}" "${wtu_language}"
The main script (upload.js)
(Source file.) I will not go into the details of the script, it is not really the object of the tutorial, just understand that as a default, you can develop steps in bash and go languages. If you'd like to use any other language, you can, but you have to check if the interpreter belonging to the given language is pre-installed on the Bitrise virtual machines or not. If they are not, then choosing bash, you have to install the chosen interpreter from the bash script and also run your choice of script from there.
The transfer.js script takes arguments on the standard input that match the expected parameters and are provided by the step.
#!/usr/bin/env node
const fs = require('fs');
const { upload } = require('wetransfert');
// USAGE : node wetransfertupload.js debug sender receiver filepath message lang
let debug = process.argv[2]; //debug true/false
let sender = process.argv[3]; //email of the sender
let receivers = process.argv[4]; //email of the receiver
let filepath = process.argv[5]; //filepath where files to send are
let message = process.argv[6]; //body of the mail
let lang = process.argv[7]; //langage of the mail
let tabReceivers;
// testing parameters
if(debug == null || sender == null || receivers == null || filepath == null || lang == null) {
console.log('ERROR : One or more parameters are invalid');
return 1;
}
β
What is important in particular is to be able to notify the user quickly enough when the step does not have all the required parameters. I did not go very far with this in this first version, especially since we specify values as is_required in the step.yml.
But for example, I could verify that the given directory exists and contains many files, and if it is not the case I could directly send an error message. This saves time and interrupts the step directly.
The audit of the step
Once our step finished running, we will check that everything is ok by launching the audit of our step via the command:
bitrise run audit-this-step
A priori it is a format validation of the step.yml which is tested here. If all went well we'll see this:
+ stepman audit --step-yml ./step.yml
INFO[13:47:49] * [OK] Success audit (./step.yml)
β
Forking the bitrise-steplib project
The final goal is to put this step in the project bitrise-steplib and make a PR so that Bitrise can validate the step (or not).
Fork the project: https://github.com/bitrise-io/bitrise-steplib
Then fill in the url of the fork in the file bitrise.yml
- MY_STEPLIB_REPO_FORK_GIT_URL:https://github.com/kawaiseb/bitrise-steplib
Once this is done, you can share his step.
Share the step
Start with the command:
bitrise-step-wetransfer [master] bitrise run share-this-step
This command will prepare the PR for the stepLib. Then what only remains is to submit it to Bitrise.
Well... I will not hide that I had to go back to it 3 times. π
Before the step was accepted, here are the main reasons for the refusal by the Bitrise team:
- Cleanness of the step: I left a lot of unnecessary things in the code
- Bad compliance with the guidelines on variable names. The input variables must be in lower case, the output variables in upper case, for example
- Then in my step, I made a change in a directory which could actually have an impact for a person who executed my step in his workflow
Conclusion
Well, this is it, now you can create and share a step. The nice thing is that you can use the technology of your choice, we could have done a script in Ruby or php, in short: I did not see any limits. The only limitation is to preinstall the necessary dependencies.
Feel free to write me comments, ask questions or tell me if some points are not clear enough :)
Links
You can find the source files of the step in question here: https://github.com/kawaiseb/bitrise-step-wetransfer
The bitrise-steplib Bitrise project that will need to be forked: https://github.com/bitrise-io/bitrise-steplib
The lib nodejs to use the wetransfer API: https://www.npmjs.com/package/wetransfert
The discussion forum (they are very responsive):
https://discuss.bitrise.io/
English version by Anna BΓ‘tki.