Icon

Workflow concepts & best practices

Workflow concepts

A workflow is defined by one Transposit Dev Platform application and implements a functionality end-to-end (E.g. merge a change on Jenkins). A workflow application is broken up into two parts: Input and execute. Let's take a look at these operations.

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 a workflow, 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.

Execute operations

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

An execute operations generally contains code that:

  • Retrieves environmental variables and input prompt parameters
  • Runs any necessary logic
  • Makes API calls
  • Formats API response so that it is useful for the user
  • Posts to Slack and the timeline

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 workflow applications that don’t require a specific user. Only one user on the team needs to provide this connection.
  • Authorization for workflow applications that are performed as you

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

For the second, where workflows are performed 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 creates 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 application 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 a workflow in Mission Control you can specify their values.

Think of environment variables as configuration of a workflow application for a specific workflow. You can have multiple workflows for a single application, 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 application 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 workflow itself.

Debugging errors while creating workflow applications

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 {}