Admin
Installation guide
The installation process on the occasion of a fresh system is several steps which are listed below, in the case of steps that were previously performed on a particular computer, you can skip individual steps.
Install dependencies
The first step would be to install a package manager if you still don't have one, for Windows this would be choco, and for macOS homebrew.
To do this you need to paste the following command into Powershell or Terminal respectively.
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
If you have encountered any problems, it is recommended to check the program's documentation, which for Windows can be found here and for macOS here.
If you use Windows you will also need to install git, which you can do by running.
choco install git -Y
The next step will be to install Chrome and Chromedriver.
choco install googlechrome -Y
brew install google-chrome
choco install chromedriver -Y
brew install chromedriver
In the next step, we will install python.
choco install python -Y
brew install pyenv
python -m pip install -U pip
pyenv install $(pyenv install -l | grep -v - | tail -1)
If you encounter a problem with pip installation, you can use instead of command above:
pyenv global $(pyenv install -l | grep -v - | tail -1)
python -m ensurepip
eval "$(pyenv init -)"
pip install --upgrade setuptools pip
In this step, we will take care of the installation of Ruby.
choco install ruby --version=3.0.0.1
brew install rbenv ruby-build
rbenv init
gem install bundler
rbenv install 3.0.0
rbenv global 3.0.0
The final step will be to install imagemagic.
choco install imagemagick
brew install imagemagick
brew install mono-libgdiplus
In addition, on Windows, you need to download msys2 and you can do this with the following command.
choco install msys2
If you are using Windows before proceeding further you must first download .NET Runtime 5.X from here.
Adding licenses to Runner
to be released...
macOS System Access
On macOS, when you launch the application, the first screen you see will inform you of the current status of your granted permissions.

You need to click the buttons one by one which will open the appropriate tab in the settings and grant all the necessary access to the application.
After doing this, the window will close and you can proceed to the next step.
Automatic updates
Automatic updates work in a very simple way in which you won't even notice them. The important thing is that you don't have to worry about the update interrupting your work as this process doesn't start while the bot is running. After the update is finished the bot will turn itself on and connect to the portal so that it can continue working.
The only thing you need to check is whether you need to create an exception in the firewall to allow the bot to update itself. A list of hosts that the runner can reach can be found at Firewall exceptions.
Runner behavior
The following is a description of the path of how a runner that is ready to work behaves.
We check the server to see if there is a new job for us (every 5 seconds).
There is an empty answer - there is nothing to do, and we return to point 1.
When we have something to do we execute a job.
The result of the job is returned to the server.
We return to point 1.
Running file based jobs
First, Runner creates a folder for himself with Job, at the following address: ~/.anyrobot/{job_id}
There you will find two folders and such files in such a structure:
input - input files directory.
script
- the content of the downloaded task.payload.json
- that is the entire response from the server, example below.
output - output files directory
console.txt
- what the console showed - with timestamps, logs etc.result.txt
- What the script showed on the console itself.
Example payload.json
response:
{
"secret": "d7dd76a0-b7a5-44d7-b98f-8712aa0e5707",
"job_id": "bc55c654-94a6-11eb-a8b3-0242ac130003",
"workflow_id": "c6d0fd24-94a6-11eb-a8b3-0242ac130003",
"workflow_name": "Test workflow",
"trigger_name": "schedule",
"trigger_id": "2d11707c-96ce-11eb-a8b3-0242ac130003",
"task": {
"method": "download",
"name": "task_dir/task_name",
"download_url": "https://wwww.serwer/test.rb"
}
"assist_requests_url": "https://serwer.xxx.yyy.com/api/v1/jobs/123e4567-e89b-12d3-a456-426614174000/assist_requests",
"results_url": "https://serwer.xxx.yyy.com/api/v1/jobs/123e4567-e89b-12d3-a456-426614174000/results",
"parameters": {
"hello": "world",
"lorem": "ipsum"
}
}
Script used as an example:
#!/usr/bin/env ruby
require 'json'
# Load payload
file = File.read("input/payload.json")
payload = JSON.parse(file)
# Print ARGV + ENV
puts "Payload: #{payload.inspect}"
puts "Arguments: #{ARGV.inspect}"
puts "Environment: #{ENV.inspect}"
Note that the working directory is set to the job directory, not the input directory. This may affect the paths of loaded files like "payload.json"
→ "input/payload.json"
.
We already have everything downloaded, in the right folder, so the application executes this file (in case you need to give, for example, chmod +x
on it, using the built-in console. The application is agnostic to the programming language used, so it is very important that the first line of the file is a shebang:
#!/usr/bin/env ruby
#!/usr/bin/env python
#!/usr/bin/env node
#!/usr/bin/env dart
Thanks to this Runner knows how to run such a file. The command contained in the shebang (ruby, python, node, etc...) can be changed at will and is passed as a script call command. For known types, additional environment configurations are put in place for the Activity Monitor to work seamlessly.
Running project based jobs
For project-based Jobs, the principle is very similar to file-based. The biggest difference is the appearance of the anyrobot.yml
file which is presented in more detail here.
As with a regular job, its folder is created.
Then the Runner, based on the
DownloadUrl
from the Task from Job, checks if it has such a repository cloned on disk, and if it hasanyrobot.yml
.If there is not then:
Clones and changes the branch to a value with
BranchName
from Task from Job.Checks if the project
anyrobot.yml
file exists.Parses the
anyrobot.yml.
Executes
install_command
fromanyrobot.yml
.Executes
after_install
fromanyrobot.yml
.If something goes wrong it aborts the operation.
It checks if there is a new version using
git branch
and determines possibly if it is detached, thengit rev-parse HEAD
andgit ls-remote -q origin refs/heads?{branch}
.If there is a new version:
Executes
before_update
fromanyrobot.yml
.Saves information about the last commit.
Updates to a newer version:
git reset --hard
, thengit switch {branchName}
andgit pull
.Checks for
anyrobot.yml
and parses it.Executes
after_update
fromanyrobot.yml
.If the update procedure did not go as planned and something went wrong it performs a
git reset --hard
and checkout commit, which he saved for himself in point 2.
Once everything is ok the following are launched in sequence:
Executes
before_runner
fromanyrobot.yml
.Executes
runner_command
fromanyrobot.yml
with passed parameters. For more detailed information about this step, see File-based jobs above.Executes
after_runner
fromanyrobot.yml
.
If nothing threw an exception or no bad execution code appeared in the terminal Job returns success. In any other case, if something goes wrong during any step a fail is returned (and a report to sentry).
Job result
There are two possibilities, the executed Job can be successful or failed, and accordingly, then different responses are sent.
Success - simple output
Let's assume that the executed script will display something like this:
Hello, I'm AnyRobot! 😀
Chromedriver is present ✅
Here there is no special tag, so the return to the server is quite simple afterwards:
# Request
POST /api/v1/jobs/94916326-9344-43f5-9187-1aea2931eac7/results
Authorization: Bearer 123e4567-e89b-12d3-a456-426614174000
{
"genre": "success",
"code": 0,
"output": "Hello, I'm AnyRobot! 😀
Chromedriver is present ✅"
}
# Response
201 Created
404 job not found
422 bad format
Failure - simple output
Let's assume that the executed script will display something like this:
zsh: command not found: dart
Thus, to the server goes the information about the failure:
# Request
POST /api/v1/jobs/94916326-9344-43f5-9187-1aea2931eac7/results
Authorization: Bearer 123e4567-e89b-12d3-a456-426614174000
{
"genre": "failure",
"code": 127,
"output": "zsh: command not found: dart"
}
# Response
201 Created
404 job not found
422 bad format
Success - with additional results
The script is responsible for preparing the files result.json
and attachments.json
in the output
directory. If either file is created its contents will be attached to the corresponding key in the uploaded result: "result"
for result.json
and "attachments"
for attachments.json
. If no file is created, the key will not be added.
{
"genre": "success",
"code": 0,
"output" : "My first output line... hello world!",
"result": {
"lorem": "ipsum"
},
"attachments": [
{
"genre": "html",
"attachment_id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Lorem Ipsum",
"code": "electrical_parameters_voltage",
"body": "<!doctype html> <html lang=\"en\"> <head> <meta charset=\"utf-8\"> <title>The HTML5 Herald</title> <meta name=\"description\" content=\"The HTML5 Herald\"> <meta name=\"author\" content=\"SitePoint\"> <link rel=\"stylesheet\" href=\"css/styles.css?v=1.0\"> </head> <body> <script src=\"js/scripts.js\"></script> </body> </html>"
},
{
"genre": "file",
"attachment_id": "123e4567-e89b-12d3-a456-426614174000",
"name": "test.png",
"code": "electrical_parameters_voltage",
"body": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
}
]
}
More is explained in the chapter Attachments and Job Results.
Firewall exceptions
Here is the list of hosts used by the applications:
your portal address
sentry address - check out sentry docs here
Last updated