Actions
Actions are the building blocks of Workflows. A Workflow allows you to run a sequence of actions that can reference contextual data from your workspace.
Configuring actions in a workflow
To learn how to create a Workflow and configure actions, see the Workflows documentation.
You must have the Edit Workflows
permission to create, update, and delete Workflows.
Available types of actions
You can configure the following action types in a Workflow:
- Branch
- Data transformation
- HTTP request
- Manual approval
- Scaffolder
- Slack
- User input
Read more about each type of action in the Workflows documentation under Step 3: Add actions to your workflow.
Duplicating an action
There may be an instance where you want to repeat an action within your Workflow. It is possible to duplicate an existing action.
To copy an action:
- In Cortex, navigate to the workflow that contains the action you want to copy.
- Click the 3 dots icon on the right side of the action.
- In the dropdown menu, click Duplicate action.
- A copy of the action will be duplicated in place within the Workflow.
- If needed, drag and drop the action to reorder it in the Workflow.
Using request signing with Workflow actions
If you're using a Workflow as a way to trigger hooks into internal tooling, we recommend validating that the request is actually originating from Cortex using request signing. Signing secrets are added to requests coming from Workflow actions.
We add the following headers to each request made by Cortex. Use these headers to verify that the request is valid and originated from Cortex:
x-cortex-timestamp
(current timestamp in millis, used to prevent replay attacks)x-cortex-signature
x-cortex-signature-256
x-cortex-signature
uses the SHA1 algorithm and exists for backward compatibility. SHA1 has been cracked and this signature should be considered deprecated. It is highly recommended to use x-cortex-signature-256
, which uses the SHA256 algorithm.
To configure a signing secret:
- In Cortex, navigate to Settings > Secrets, then scroll down to the "Request signing secret" section.
- Create a secret, then click Save.
- Calculate the signature (an RFC2104 HMAC):
- Create a string with the value
$timestamp.$requestBody
if the request body is non-null OR$timestamp
if the request body is null. - Calculate an HMAC using the SHA256 algorithm. Use the Secret you provided to Cortex as the key and the string from Step 1 as the payload.
- Verify that the
x-cortex-signature-256
matches the HMAC calculated in Step 2.
- Create a string with the value
Workflow states
Each workflow, when run, will build up a state object. This state can be referenced throughout the workflow and allows actions to reference both the top-level state (e.g., who initiated a workflow) and the state of a previous action.
The Workflow state object includes top-level context
and actions
keys:
context
is immutable, set at the beginning, and available to all actions.- If an entity changes during workflow execution, those changes will not be represented in
context.entity
. - If secrets change during a workflow, those changes will not be represented in
context.entity
. - You can examine the context object via the Run context tab when viewing a Workflow run.
- Read more about the
context
key below.
- If an entity changes during workflow execution, those changes will not be represented in
actions
is built up as actions execute.- Each action will have an
inputs
andoutputs
key, but their format differs based on the action’s type.
- Each action will have an
The state object looks similar to the following:
Workflow state object example
{
"context": {
"initiatedBy": {
"email": string
"name": string
"identityMappings": { provider key to external id }
},
"initiatedAtIso8601Timestamp": string, // ISO8601 timestamp
"entity": { // only present for entity-scoped workflows
"tag": string,
"name": string,
"descriptor": { cortex.yaml as JSON object }
}
"secrets": { key to each decrypted secret }
},
"actions": {
"action-slug-1": {
"inputs": { defined per action type },
"outputs": { defined per action type }
},
"action-slug-2": {
"inputs": { defined per action type },
"outputs": { defined per action type }
}
...
}
}
The workflow state context
key
If the action is being run in the context of a catalog entity, the template context will contain data about the entity:
tag
name
descriptor
(this is thecortex.yaml
, as an object)
These can be accessed under the {{context.entity}}
key, for example {{context.entity.tag}}
or {{context.entity.descriptor.info.x-cortex-git.github.repository}}
The context object also has the following keys:
{{context.initiatedAtIso8601Timestamp}}
: The timestamp at which this action was initiated{{context.initiatedBy}}
: The user object of the initiatoremail
: The user's emailname
: The initiator's nameidentityMappings
: A mapping of the identities listed below and their corresponding external IDs:azure_devops
bitbucket
clickup
github
gitlab
jira
microsoft_teams
opsgenie
pagerduty
service_now
slack
Example: initiatedBy.identityMappings.azure_devops
with value 1234
.
Access configured secrets
You can access your configured secrets by tag: {{context.secrets.SECRET_TAG}}
. Note that Mustache performs HTML escaping by default, so if your configured secret contains a reserved HTML character, use triple braces to use raw content: {{{context.secrets.SECRET_TAG}}}
. Secret values are redacted in inputs and outputs of the workflow state.
Accessing a secret in the context
object is not supported for Slack actions.
Referencing an action or workflow state in a workflow
You can reference a previous action or a workflow state in several ways:
- Templated into action schemas via Mustache (
{{ }}
) - Accessed directly from JQ actions
- Referenced to define "User input" action overrides
- Referenced in "Branch" action path expressions using CEL syntax
Action and workflow state reference example
Assume a workflow was created where you gather names from an "HTTP request" action, a "data transformation" action parses the array of names, the names are surfaced to users in a "user input" action where they can select a name, then a "branch" action runs a different path based on which name was selected during the previous "user input" action. In one of the branch paths, there is a "Slack" action that sends a templated message based on the output of previous actions.
The workflow contains the following actions:
- HTTP request action called
users
- In this example, the action sends a GET request to gather user names from a URL containing sample data.
- Data transformation action called
names
- It contains a JQ query referencing the output of the
users
action:
[.actions.users.outputs.body[] | .name]
- It contains a JQ query referencing the output of the
- User input action called
pick-name
- It contains an override that references the output of the
names
action:
actions.names.outputs.result
- It contains an override that references the output of the
- Branch action called
create-services
- There are multiple paths in this branch, depending on which name you chose in the previous action. One of the name options is
Ervin
, and there is a conditional path calledErvin
within this action that contains the following path expression. It referencesErvin
as the output of thepick-names
action:actions['pick-name'].outputs.name == 'Ervin' && context.entity.descriptor.info['x-cortex-type'] == 'team'
. - The
Ervin
path contains a Slack action to send a templated message via Slack, referencing the output of thepick-name
action and referencing the workflow state by including the email address of the user who initiated the workflow:
We created a service for {{actions.pick-name.outputs.name}}. [message from workflow triggered by {{context.initiatedBy.email}}]
- There are multiple paths in this branch, depending on which name you chose in the previous action. One of the name options is
When you run the workflow, the following chain of events occurs:
- The HTTP request action gathers user names.
- In the "Inputs" tab of this action, you can see where the data was pulled from.
- In the "Outputs" tab of this action, you can see the list of names under the body.
- The data transformation action parses an array of names from the HTTP request action.
- In the "Outputs" tab of this action, you can see the list of names.
- The workflow is paused while awaiting user input. The user input action surfaces a
name
field where the user can select a name from the list. The names are from the array parsed in the previous action. - The user selects the name
Ervin
, and the workflow continues to the next action. - The branch action runs a path depending on which name you chose in the previous action. In this example, the
Ervin
path runs because the CEL expression for that conditional path was configured to run when thepick-name
action's output isErvin
.- In the "Outputs" tab of this action, you can see the conditions that were checked to verify which path to run.
- The
Ervin
path contains a Slack action that sends a templated message referencing the output the previous action and the user who initiated the workflow. The message is sent to the user with the templated references translated:
We created a service for Ervin. [message from workflow triggered by jdoe@example.com]
Additional information on Workflows
To learn more about using actions in a Workflow, see the Workflows documentation.