Workflow concepts & best practices

Workflow concepts

The general flow through the modals are:

Home -> Browse Runbooks, where you select a runbook -> Runbook steps -> Actions for a step, where you select an action -> Input prompt -> Execute

Modal views and updates are completely controlled only by Transposit. As a workflow author, you will not have control over updating or pushing modals.

Input operations

Input operations (recommended operation name: input_prompt) return the Slack Block Kit UI you will want to display when a user clicks on an action, like in the example below. Make sure to add a parameter (located on the right side) named context in this operation.

Input prompt example

Right now, if the Block Kit JSON is not valid, it will fail silently.

Important: Use the block_kit_lib connector to make it easier to form Slack Block Kit UI. You will need to add it as a connector in your workflow application. Under Code > Data connectors, search for Slack Block Kit. Select the "-- None --" operation and save.

You can also write raw block kit code using the Slack Block Kit Builder. If you use it, make sure you change the top left dropdown from “Message Preview” to “Modal Preview” because it changes the code.

Execute operations

Execute operations (recommended operation name: execute) run when a user clicks the Run button in an action modal in Slack. This is where most of the workflow logic is written and most external API calls are made.

Running execute operation

Currently, due to some Python speed limitations, you will need to call your Python execute operation from a JavaScript operation (recommended operation name: execute_js). Slack requires us to respond within 3 seconds or it retries, so this is why we are using the setImmediate function which is currently only implemented in JavaScript

Example:

(params) => {
// console.log(params)
setImmediate(() => {
api.run("this.execute",{context: params.context});
});
return {};
}

Retrieving results from input prompt

Make sure to add a parameter (located on the right side) of type object named context in this operation.

The context parameter contains the input_prompt user input and other important information. In the execute operation, you will find it as params[“context”][“parameters”].

The block_kit_lib also contains a retrieve_text_input operation to help you retrieve user input. Here's an example:

    my_text_value = api.run(
"block_kit_lib.retrieve_text_input", {
"field_name": "my_text_field",
"context": params["context"],
"default_value": "default value"
})[0]

Posting messages

Use mc.postMessage.blockKit(blocks) to send a message to the channel. For example, if you are building a simple block to send a message:

mc.postMessage.blockKit([api.run("block_kit_lib.markdown_section", {"text": message})[0]])

To log an event to the timeline (seen under the Activities in main Transposit site), use:

mc.logEvent(
type: "info" | "error" | "done" | ...,
payload: String
)

Try to at least include a done type. Some workflows don’t make as much sense to include the full results, like large log responses. Currently, it is only text based, but images are coming soon.

Integrations

Integrations are how Transposit is able to connect your existing services and APIs together to interactive runbooks.

Authentication

Authentication for an integration is done in Transposit in the Integrations section in the left sidebar.

You will need to check the box to enable the specific integration and either connect:

  • Authorization for workflows that don’t require a specific user. Only one user on the team needs to provide this connection.
  • Authorization for workflows that are performed as you

For authorizations for workflows that don’t require a specific user, you are done here after you connect.

For the second, where actions are preformed by a specific user:

If you want a user to connect to other services as themselves (E.g. so they can post to GitHub as themselves or create a Jira ticket with their credentials), you need to do the following:

  1. Make sure the user create a Transposit account with Slack login
  2. Make sure this account is added to the team
  3. If the team integration auth was set up before (I.e. “Authorization for workflows that don’t require a specific user. Only one user on the team needs to provide this connection.”), make sure the workflow on the Transposit Dev Platform is set up to use the user based authentication under Users > User Configuration, as opposed to team based authentication. This box needs to be checked as seen below:
    Require users to authenticate with these data connections box

Lastly, no matter what authorization type you use, you can go to your Transposit Dev Platform workflow application and add corresponding data connector for the integration. You will be prompted to use an existing auth for the integration, which you will need to confirm.

Configuration

You can see the existing Transposit Dev Platform environment variables documentation here.

You will create your environment variables first in the Transposit Dev Platform, then when creating an action you can specify their values.

Think of environment variables as configuration of a workflow for a specific action. You can have multiple actions for a single workflow, but you might want them configured differently. This might be for different services, projects, regions, APIs, clusters, etc.

The code to get an env variable in the Transposit Dev Platform:

env.get("variable_name_here")

Overriding Data Connector Config

This is not commonly needed, but only BaseUrl or Region can be overridden/managed at this time. In order to make use of this new feature, the Workflow needs to have declared that the Region (E.g. AWS Region) or Base URL "can be managed" or "can be overridden." Under Code > your specific data connector > Configuration > Edit:

Check box for Allow consumers to override this value

Note: After you have checked this box, the value for this configuration is set in the Integration section of the main Transposit site, not in the action itself.

Debugging errors while creating workflows

Most of your debugging with happen by adding print() statements in Python and viewing them in the Monitor section on the left sidebar in the Transposit Dev Platform.

Note: Some server side errors may be only viewable by the Transposit team at this time, please feel free to reach out to support if you are experiencing an error and don't see anything in the Monitor section.

Best practices

Sharing errors with users

Currently, there are two ways to return errors to a user:

  1. When input_prompt runs and show the error in the input modal

This case is good for validation on environment variables that does not require an API call.

Example: There is missing environment variable, and you want tell user what is missing and to go update it.

Here’s an example from the GitHub commit log workflow:

    blocks = []
repo_name = env.get("gh_repo_name")
if repo_name == None:
message = "Invalid settings, please verify that 'gh_repo_name' is correct."
message += " Values seen for gh_repo_name: " + str(repo_name)
blocks.append(api.run("block_kit_lib.text_section", {"text": message})[0])
return blocks
  1. When execute runs and shows in the channel

This case is good for errors that involve API calls. It can also be used for validation.

Example: There is a bad API response and you want to let the user know something is wrong. Currently, it is not a great of user experience because they might have to go back into the modal, but since the modal gets closed with setImmediate, it is the only way for right now.

See the catching API errors section below for an example.

Catching API errors

Here’s an example from the GitHub commit log workflow:

    try:
commits = api.run("this.list_commits", {
"repo": repo_name,
"owner": owner_name
})
except ValueError as ex:
message = "Error from GitHub API: " + str(ex)
result = api.run("block_kit_lib.post_error", {
"context": params["context"],
"message": message
})[0]
return {}