Workflow button
Build a workflow trigger with named input parameters. Replace the example URL with your real link trigger; this example does not activate a workflow.
Output
Local preview of the selected language’s tested example. Slack client appearance may differ; controls here do not send requests.
Run the release workflow with the parameters below.
Serialized output
{
"channel": "#release",
"mrkdwn": true,
"blocks": [
{
"type": "section",
"block_id": "<generated-block-id>",
"text": {
"type": "mrkdwn",
"text": "Run the release workflow with the parameters below."
}
},
{
"type": "actions",
"block_id": "<generated-block-id>",
"elements": [
{
"type": "workflow_button",
"text": {
"type": "plain_text",
"text": "Release"
},
"action_id": "release",
"workflow": {
"trigger": {
"url": "https://slack.com/shortcuts/Ft012KXZK1MZ/...",
"customizable_input_parameters": [
{
"name": "env",
"value": "prod"
},
{
"name": "retries",
"value": "3"
}
]
}
}
}
]
}
],
"text": ""
}
Code
Workflow.from_url collapses the most common workflow construction:
from slackblocks import (
ActionsBlock,
Message,
SectionBlock,
Workflow,
WorkflowButton,
)
msg = Message(
channel="#release",
blocks=[
SectionBlock("Run the release workflow with the parameters below."),
ActionsBlock(
elements=[
WorkflowButton(
text="Release",
action_id="release",
workflow=Workflow.from_url(
"https://slack.com/shortcuts/Ft012KXZK1MZ/...",
env="prod",
retries="3",
),
),
],
),
],
)
print(msg.json())
Each keyword pair becomes one InputParameter on the underlying Trigger. Calling Workflow.from_url(url) with no parameters omits the customizable_input_parameters field.
import * as S from "@nicklambourne/slackblocks";
const workflow = S.Workflow().trigger(S.Trigger().url("https://slack.com/shortcuts/Ft123/example")
.customizableInputParameters(S.InputParameter().name("env").value("prod")));
const button = S.WorkflowButton().text("Release").actionId("release").workflow(workflow).build();
console.log(JSON.stringify(button));
package main
import (
"encoding/json"
s "github.com/nicklambourne/slackblocks/go/v3"
"os"
)
func main() {
value, err := s.NewWorkflowButton().Text("Release").ActionID("release").Workflow(
s.NewWorkflow().Trigger(s.NewTrigger().URL("https://slack.com/shortcuts/Ft123/example").CustomizableInputParameters(
s.NewInputParameter().Name("env").Value("prod"),
)),
).Build()
if err != nil {
panic(err)
}
if err := json.NewEncoder(os.Stdout).Encode(value); err != nil {
panic(err)
}
}
import io.github.nicklambourne.slackblocks.*;
import io.github.nicklambourne.slackblocks.block.*;
import io.github.nicklambourne.slackblocks.component.*;
import io.github.nicklambourne.slackblocks.element.*;
import io.github.nicklambourne.slackblocks.object.*;
import io.github.nicklambourne.slackblocks.payload.*;
import java.util.List;
import java.util.Map;
public final class Recipe {
public static void main(String[] args) throws Exception {
var workflow = Workflow.builder().trigger(Trigger.builder().url("https://slack.com/shortcuts/Ft123/example")
.customizableInputParameters(InputParameter.builder().name("env").value("prod").build()).build()).build();
var value = WorkflowButtonElement.builder().text("Release").actionId("release").workflow(workflow).build();
System.out.println(value.toJson());
}
}
using System;
using System.Collections.Generic;
using Slackblocks;
using Slackblocks.Blocks;
using Slackblocks.Components;
using Slackblocks.Elements;
using Slackblocks.Objects;
using Slackblocks.Payloads;
var workflow = new Workflow(new Trigger("https://slack.com/shortcuts/Ft123/example",
customizableInputParameters: [new InputParameter("env", "prod")]));
var value = new WorkflowButtonElement("Release", workflow, "release");
Console.WriteLine(value.ToJson());
require "slackblocks"
include Slackblocks
workflow = Workflow.new(trigger: Trigger.new(url: "https://slack.com/shortcuts/Ft123/example",
customizable_input_parameters: [InputParameter.new(name: "env", value: "prod")]))
value = WorkflowButtonElement.new(text: "Release", workflow: workflow, action_id: "release")
puts value.to_json
Input parameters retain iterator order. An empty iterator omits the parameter list.
use slackblocks::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let workflow = Workflow::from_url(
"https://slack.com/shortcuts/Ft012KXZK1MZ/example",
[
InputParameter::builder()
.name("env")
.value("prod")
.build()?,
InputParameter::builder()
.name("retries")
.value("3")
.build()?,
],
)?;
let button = WorkflowButtonElement::builder()
.text("Release")
.action_id("release")
.workflow(workflow)
.build()?;
println!("{}", serde_json::to_string(&button)?);
Ok(())
}
See Troubleshooting for typed error handling, omission rules and safe editing.
<?php
declare(strict_types=1);
require 'vendor/autoload.php';
use Slackblocks as S;
$workflow = S\Workflow::fromUrl('https://slack.com/shortcuts/Ft123', [new S\InputParameter(name: 'deployment', value: '482')]);
echo (new S\WorkflowButtonElement(text: 'Release', workflow: $workflow, actionId: 'release'))->toJson();
alias Slackblocks.{Elements.WorkflowButton, Objects.Workflow, Objects.InputParameter}
workflow = Workflow.from_url!("https://slack.com/shortcuts/Ft123/abc", [
InputParameter.new!(name: "ticket", value: "INC-42")
])
WorkflowButton.new!(text: "Open workflow", workflow: workflow, action_id: "workflow")
|> Slackblocks.to_map!()
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson (encode)
import qualified Data.Map.Strict as Map
import Slackblocks
example = do
parameter <- buildInputParameter (inputParameter "ticket" "INC-42")
workflow <- workflowFromURL "https://slack.com/shortcuts/Ft123/abc" [parameter]
label <- buildPlainText (plainText "Open workflow")
buildWorkflowButtonElement (workflowButtonElement label workflow "workflow")