Camunda external task Robot Framework RCC client
================================================

**Technology preview.**

`carrot-rcc` is an opinionated [Camunda external task](https://docs.camunda.org/manual/latest/user-guide/process-engine/external-tasks/) client for executing [Robot Framework](https://robotframework.org/rpa/) [RPA framework](https://rpaframework.org/) automation tasks. It is based on Robocorp [RCC toolchain](https://robocorp.com/docs/rcc/overview) and [Camunda external task client for Node JS](https://github.com/camunda/camunda-external-task-client-js).

`carrot-rcc` executes automation tasks built and wrapped into robot.zip packages as instructed by [Robocorp documentation](https://robocorp.com/docs/). Single `carrot-rcc` service can subscribe multiple topics and execute tasks from same or different robot-packages concurrently, although only locally on the same computer. `carrot-rcc` should work fine on Windows, Linux and on MacOS.

```bash
usage: carrot-rcc [<robots>...]
                  [--base-url] [--authorization]
                  [--worker-id] [--max-tasks] [--poll-interval] [--log-level]
                  [--rcc-executable] [--rcc-encoding] [--rcc-telemetry]
                  [-h] [--help]

<robots> could also be passed as a comma separated env RCC_ROBOTS

options:

  --base-url[=<url>]                       [env: CAMUNDA_API_BASE_URL] [default: http://localhost:8080/engine-rest]
  --authorization[=<header>]               [env: CAMUNDA_API_AUTHORIZATION] [example: Basic ZGVtbzpkZW1v]

  --worker-id[=<string>]                   [env: CLIENT_WORKER_ID] [default: carrot-rcc]
  --max-tasks[=<cpus>]                     [env: CLIENT_MAX_TASKS] [default: [cpu count]]
  --poll-interval[=<milliseconds>]         [env: CLIENT_POLL_INTERVAL] [default: 10000]
  --log-level[=<debug|info|warn|error>]    [env: CLIENT_LOG_LEVEL] [default: info]

  --rcc-executable[=<path>]                [env: RCC_EXECUTABLE] [default: rcc]
  --rcc-encoding[=<encoding>]              [env: RCC_ENCODING] [default: utf-8]
  --rcc-telemetry                          [env: RCC_TELEMETRY] (default: do not track)

  -h, --help

examples:

  $ carrot-rcc robot1.zip

  $ carrot-rcc robot1.zip robot2.zip --log-level=debug

  $ RCC_ROBOTS="robot1.zip,robot2.zip" LOG_LEVEL="debug" carrot-rcc

  $ CAMUNDA_API_AUTHORIZATION="Bearer MY_TOKEN" carrot-rcc robot1.zip
```

Design
======

When `carrot-rcc` is started, it examines every given robot-package and examines available task names from their `robot.yaml`. Currently, `carrot-rcc` can only find packages preloaded onto local filesystem.

Then `carrot-rcc` subscribes every found task name as they were Camunda external task topics, and starts listening for new tasks for its topics to become available at Camunda.

On a new task, `carrot-rcc` remembers which topic was mapped to which task on which robot-package, and unpacks the correct robot-package into a new temporary directory. Then it creates another temporary directory with all external task variables and files as a local [robot work item](https://robocorp.com/docs/libraries/rpa-framework/rpa-robocloud-items).

Similarly to work item, for convenience, all `carrot-rcc` process environment variables are made available as `env` secret to keep their use out of Robot Framework logs when used with [RPA framework's Secrets -library](https://robocorp.com/docs/libraries/rpa-framework/rpa-robocloud-secrets).

Next [RCC](https://robocorp.com/docs/rcc/overview) is called to resolve robot's dependencies and execute the robot. Robot package may declare any available Conda or Pip package as its dependency. For example, this makes it possible to have [fully functional browser automation stack as a task dependency](https://github.com/datakurre/carrot-rcc/blob/main/xkcd-bot/conda.yaml) independently what the local machine actually has available. RCC caches the dependency environments on the machine to enable their fast re-use.

Finally, `carrot-rcc` saves all the changed and added variables from the saved work item back to Camunda. In addition, it also saves full [Robot Framework execution logs](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#log-file). All these are saved back into the task execution context, to leave their further use for the BPMN designer. At the end `carrot-rcc` either completes of fails the task at Camunda.

[![Screencast of carrot-rcc in action](https://github.com/datakurre/carrot-rcc/raw/main/example-process.gif)](https://github.com/datakurre/carrot-rcc/raw/main/example-process.gif)


Usage
=====

`carrot-rcc` requires only [NodeJS](https://nodejs.org/en/) 12 or later and expects [RCC](https://downloads.robocorp.com/rcc/releases/index.html) to be on the environment PATH. RCC location may also be configured manually with ``--rcc-executable`` argument.

It is also possible to bootstrap everything with just using RCC:

1. Create a directory for `carrot-rcc` and download [RCC](https://downloads.robocorp.com/rcc/releases/index.html) into that directory.

2. Download an example [conda.yaml](https://raw.githubusercontent.com/datakurre/carrot-rcc/main/conda.yaml) defining the requirements for `carrot-rcc`.

3. Install `carrot-rcc` into RCC managed environment with

   ```bash
   $ rcc env new conda.yaml
   ```
   or
   ```bash
   $ rcc.exe env new conda.yaml
   ```

4. The hard part is to figure out from the logs where RCC did create the environment. When found, copy a few files back and forth to give you access the environment and `carrot-rcc`, and give `carrot-rcc` access to RCC:

   ```bash
   $ cp /home/user/.robocorp/live/850002f365eee60f/rcc_activate.sh .
   $ cp rcc /home/user/.robocorp/live/850002f365eee60f/bin
   ```
   or
   ```bash
   $ copy C:\Users\User\AppData\Local\robocorp\live\850002f365eee60f\rcc_activate.cmd .
   $ copy C:\Users\User\AppData\Local\robocorp\live\850002f365eee60f\Scripts\carrot-rcc.exe .
   $ copy rcc.exe C:\Users\User\AppData\Local\robocorp\live\850002f365eee60f
   ```

5. Finally, activate the environment:

   ```bash
   $ source rcc_activate.sh
   ```
   or
   ```bash
   $ rcc_activate.cmd
   ```

Done. Now `carrot-rcc` should be ready to be run, for example:

```bash
$ carrot-rcc robot.zip --base-url=http://localhost:8080/engine-rest --log-level=debug
```
or
```bash
$ carrot-rcc.exe robot.zip --base-url=http://192.168.86.156:8080/engine-rest --log-level=debug
```

The project's repository includes [an example Camunda process](https://github.com/datakurre/carrot-executor/tree/main/camunda/deployment) with an [an example RCC compatible robot](https://github.com/datakurre/carrot-rcc/blob/main/xkcd-bot/robot.zip?raw=true) available.

![](https://github.com/datakurre/carrot-rcc/raw/main/example-process.png)
