Logo

dev-resources.site

for different kinds of informations.

Rapid Bolt app development w/ Slack CLI and sandboxes

Published at
4/8/2024
Categories
slack
typescript
python
Author
seratch
Categories
3 categories in total
slack
open
typescript
open
python
open
Author
7 person written this
seratch
open
Rapid Bolt app development w/ Slack CLI and sandboxes

This blog post guides you on how to rapidly develop a Slack Bolt app using Slack CLI and sandbox organizations/workspaces.

Slack's Developer Program

At TrailblazerDX held in San Francisco on March 6th, new valuable features for Slack app developers were announced:

https://slack.com/blog/developers/developer-program-launch

Utilizing Enterprise Grid sandboxes for local development simplifies your Bolt app development like never before! This article provides a guide on the minimum steps to get started.

What's exciting about this?

Prior to the Developer Program, developing Slack apps required the following steps:

  1. Accessing https://api.slack.com/apps to configure the app
  2. Installing the app being developed into the Slack workspace
  3. Specifying the obtained access token as an environment variable
  4. Finally launching the app

However, with the combination of the newly available Slack CLI and sandboxes by Developer Program, the process has become extremely simple. In fact, all you need to do are creating a sandbox, connecting the CLI to it, and then slack run to start your app.

"... Wait, isn't Slack CLI only usable for the Deno thing?"

Yes, indeed, initially it was provided as a tool exclusively for Deno apps. However, from now on, it will also be available for Bolt app development too!

Now, let's get right to the point.

Create your first sandbox

First, access the developer portal:

https://api.slack.com/developer-program

If you haven't registered yet, create a new account first.

Provisioning a sandbox requires a workspace with a paid plan or registering a credit card, but there is no cost for creating a sandbox or testing the functionality of an app.

However, for executing custom workflow functions, excess usage beyond a certain free quota will be billed based on the number of workflow executions, in the same manner with the production environment. For more details, please refer to this help page.

Once you've set up your account, go ahead and create a sandbox. If everything goes well, you should see a screen similar to the one below.

img

What's Enterprise Grid?

By the way, you may not be familiar with Enterprise Grid, so let me provide a brief explanation about the "Org" within a sandbox.

In plans other than Enterprise Grid, which most people are familiar with, you can only use one workspace. However, Enterprise Grid has the concept of an "organization" above workspaces, allowing you to create multiple workspaces within an org.

Since the sandbox environment provided by the Developer Program is for Grid, the process involves creating an org first and then creating workspaces. At this point, it'd be enough if you understand this as "that's how it works."

For general information about Enterprise Grid, please refer to the following help page and official guides:

https://slack.com/help/articles/115005481226-Enterprise-Grid-launch-guide

Set up Slack CLI

Once you have provisioned a sandbox, the next step is to install Slack CLI. Please refer to the following page for installation instructions for each platform. You only need to complete the steps before running slack login:

https://api.slack.com/automation/quickstart

After installing the slack command, execute slack login in your terminal. You should see a screen like this:

$ slack login

📋 Run the following slash command in any Slack channel or DM
   This will open a modal with user permissions for you to approve
   Once approved, a challege code will be generated in Slack

/slackauthticket MGIwNTczNzktYWQ5Y***********************************

? Enter challenge code
Enter fullscreen mode Exit fullscreen mode

Copy the part /slackauthticket MGIwN...., and execute it in the message composer in the Slack workspace you created earlier for the sandbox.

A modal dialog like the following will appear:

img

Press the "Confirm" button, and you will see the "Challenge Code" displayed as follows:

img

Copy that string and paste it into your terminal to complete the setup.

The result of this integration is saved in a file called $HOME/.slack/credentials.json. If you want to revoke the authentication, you can run slack logout comamnd.

OK, now you're all set!

Create a Python app

Let's start by connecting the simplest Python app to your sandbox org.

Set up Python venv and libraries

You can use Poetry or any other method you prefer, but set up your Python environment and install the necessary dependencies (just two!) as follows:

# Set up Python environment (you can use Poetry or any other tool)
python3 -m venv .venv
source .venv/bin/activate

# Install the necessary dependencies, just these two for now
pip install slack-bolt slack-cli-hooks
Enter fullscreen mode Exit fullscreen mode

Place required files for CLI

For Slack CLI to work with Python, it expects at least the following files:

File name Description
slack.json Configuration required for CLI to run locally
manifest.json App settings (automatically synchronized with Slack when running slack run)
app.py Code to execute the app (file name can be changed)

For slack.json, save the following content as it is:

{
  "hooks": {
    "get-hooks": "python3 -m slack_cli_hooks.hooks.get_hooks"
  }
}
Enter fullscreen mode Exit fullscreen mode

Next is manifest.json, which is a file that you can modify as needed. For this demo, please copy and paste it as is.

{
  "display_information": {
    "name": "Hello",
    "description": "You can update this later",
    "background_color": "#4361ba",
    "long_description": ""
  },
  "features": {
    "app_home": {
      "home_tab_enabled": false,
      "messages_tab_enabled": false,
      "messages_tab_read_only_enabled": true
    },
    "bot_user": {
      "display_name": "Hello Bot",
      "always_online": true
    },
    "slash_commands": [
      {
        "command": "/hello-sandbox",
        "description": "Say hello to sandbox",
        "usage_hint": "",
        "should_escape": true
      }
    ]
  },
  "oauth_config": {
    "scopes": {
      "bot": ["commands"]
    }
  },
  "settings": {
    "interactivity": { "is_enabled": true },
    "org_deploy_enabled": true,
    "socket_mode_enabled": true
  },
  "outgoing_domains": []
}
Enter fullscreen mode Exit fullscreen mode

Finally, place app.py with the following content:

import os
import logging
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler

logging.basicConfig(level=logging.DEBUG)

app = App(token=os.environ["SLACK_BOT_TOKEN"])

# Add your code here


if __name__ == "__main__":
    SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()
Enter fullscreen mode Exit fullscreen mode

Start your app

Now that the preparation is complete, please try launching the app with slack run. If there are no apparent errors, then everything should be fine.

At this stage, the slash command /hello-sandbox should already be available in your workspace. Please try executing it.

While you may encounter an error on the UI, in the terminal, you should see warnings similar to the following. These are suggestions provided by Bolt for Python to guide your implementation.

WARNING:slack_bolt.App:Unhandled request ({'type': None, 'command': '/hello-sandbox'})
---
[Suggestion] You can handle this type of event with the following listener function:

@app.command("/hello-sandbox")
def handle_some_command(ack, body, logger):
    ack()
    logger.info(body)
Enter fullscreen mode Exit fullscreen mode

Let's add code to pass "Hello!" to ack() method call. Please add this before the line if __name__ == "__main__":.

@app.command("/hello-sandbox")
def handle_some_command(ack, body, logger):
    ack("Hello!")
    logger.info(body)
Enter fullscreen mode Exit fullscreen mode

At the time of posting this article, Python CLI support does not have automatic code reloading. Please relaunch slack run whenever you make changes to the code.

To avoid selecting the workspace every time, you might find it convenient to specify the displayed App ID like slack run -a A06P0E7LY48.

With the updated code, you should not encounter execution errors on the UI, and the bot should respond with 'Hello!' 🎉

Create a Node.js app

Let's do the same thing with Node.js. There's no need to change manifest.json. Modify slack.json as follows:

{
  "hooks": {
    "get-hooks": "npx -q --no-install -p @slack/cli-hooks slack-cli-get-hooks",
    "start": "npm start"
  }
}
Enter fullscreen mode Exit fullscreen mode

Let's add package.json and app.js as well.

npm init -y
npm i @slack/bolt
npm i --save-dev @slack/cli-hooks nodemon
Enter fullscreen mode Exit fullscreen mode

Next, update the "scripts" in package.json as follows. If you want a name other than npm start, please name it in line with slack.json.

  "scripts": {
    "start": "nodemon --watch '*.js' --exec node app.js"
  },
Enter fullscreen mode Exit fullscreen mode

Finally, save app.js with the following content:

const { App, LogLevel } = require('@slack/bolt');

const app = new App({
  socketMode: true,
  token: process.env.SLACK_BOT_TOKEN,
  appToken: process.env.SLACK_APP_TOKEN,
  logLevel: LogLevel.DEBUG,
});

app.command("/hello-sandbox", async ({ ack }) => {
  await ack("Hello!");
});

;(async () => {
  await app.start();
  console.log("⚡️ Bolt app is running!");
})();
Enter fullscreen mode Exit fullscreen mode

Try launching it with slack run. Is it working properly?

In this example, nodemon automatically detects file changes. Thus, you'll be able to smoothly develop without restarting the server each time.

Create a TypeScript + Node.js app

Lastly, let's set up the Node.js app in TypeScript.

First, add a tsconfig.json file. The following is just an example, so feel free to adjust the details according to your preferences.

{
  "compilerOptions": {
    "target": "es2022",
    "module": "commonjs",
    "lib": ["es2022", "dom"],
    "outDir": "lib",
    "strict": true,
    "esModuleInterop": true,
    "resolveJsonModule": true
  }
}
Enter fullscreen mode Exit fullscreen mode

Next, install additional dependencies:

npm i --save-dev typescript ts-node @types/node
Enter fullscreen mode Exit fullscreen mode

Then, update the command in package.json to "start": "nodemon --watch 'src/**/*.ts' --exec \"ts-node\" src/app.ts".

Finally, save src/app.ts with the following content:

import { App, LogLevel } from "@slack/bolt";

const app = new App({
  socketMode: true,
  token: process.env.SLACK_BOT_TOKEN,
  appToken: process.env.SLACK_APP_TOKEN,
  logLevel: LogLevel.DEBUG,
});

app.command("/hello-sandbox", async ({ ack }) => {
  await ack("Hello!");
});

;(async () => {
  await app.start();
  console.log("⚡️ Bolt app is running!");
})();
Enter fullscreen mode Exit fullscreen mode

If configured correctly, it should work similarly. Also, try changing the code and verifying that it gets reflected.

Benefits of using CLI + sandboxes

The real joy of using Slack CLI begins here.

No longer do you need to access https://api.slack.com/apps, make app configuration changes, reinstall, and go through that hassle.

Let's rewrite and save manifest.json with the following content:

{
  "display_information": {
    "name": "Hello",
    "description": "You can update this later",
    "background_color": "#4361ba",
    "long_description": ""
  },
  "features": {
    "app_home": {
      "home_tab_enabled": false,
      "messages_tab_enabled": false,
      "messages_tab_read_only_enabled": true
    },
    "bot_user": {
      "display_name": "Hello Bot",
      "always_online": true
    }
  },
  "oauth_config": {
    "scopes": {
      "bot": ["commands", "chat:write", "app_mentions:read"]
    }
  },
  "settings": {
    "interactivity": { "is_enabled": true },
    "event_subscriptions": {
      "bot_events": ["app_mention"]
    },
    "org_deploy_enabled": true,
    "socket_mode_enabled": true
  },
  "outgoing_domains": []
}
Enter fullscreen mode Exit fullscreen mode

When you save the file, Slack CLI will automatically reflect these changes in the metadata managed by Slack's servers.

The slash command you were using earlier will disappear from the workspace, and instead, this app will be able to receive events, which can be delivered when a user mentions your app's bot.

Please add the following code to the src/app.ts file that you added earlier. This change should also be automatically reflected by nodemon.

app.event("app_mention", async ({ say }) => {
  await say("Hi!");
});
Enter fullscreen mode Exit fullscreen mode

For testing, invite @Hello Bot (local) to a channel and mention it. If you receive a response saying "Hi!", then it's successful! 🎉

Wrap up

You should now understand how easy it is to get started and develop smoothly.

For production, if you're using Socket Mode, it's a good idea to prepare a Dockerfile for deployment (you won't need nodemon in that case).

For setting up manifest.json, please refer to the following page. Note that if it's in YAML format, it won't be loaded with CLI integration, so be sure to specify it in JSON format.

https://api.slack.com/reference/manifests

You might wonder, "Can I use this with runtimes/languages other than Node.js or Python?" Technically, it's possible, but it might require a bit more effort to get it up and running. I hope to cover this in another article someday.

That's all for now!

slack Article's
30 articles in total
Favicon
Open-Source Collaboration Progress
Favicon
Collaborating to Slack as an Open-Source Developer: Part 2
Favicon
Collaborating to Slack as an Open-Source Developer
Favicon
How to integrate Alerta into your Business
Favicon
[Apache Superset] Topic #5, Automated Alerts and Reporting via Slack/Email in Superset
Favicon
How to send a message to Slack workspace members using an SQL statement
Favicon
Enable Slack Notifications for Amplify Builds Directly to a Slack Channel
Favicon
How to use Slack for Beginners.
Favicon
How to make Slack Workflow input form
Favicon
Magento 2 Slack Notifier Module
Favicon
We Built our First SaaS - Sweet Kudos
Favicon
How to Customize Slack Fonts Using Stylus for Improved Readability
Favicon
10 Slack emojis that developers should use
Favicon
Format your Slack messages, please!
Favicon
ChatGPT Slack Bot
Favicon
Effortless Bug Tracking: Pcloudy’s Integration with Asana and Monday.com
Favicon
AI-Powered News Summaries for Slack
Favicon
Enhancing Decision-Making: AI In Microsoft Teams & Slack
Favicon
Slack vs. Discord: Choosing Your Tech Community's Playground
Favicon
Laravel 10 Send Notifications in Slack Channel
Favicon
Build a Slack app with SlackKit
Favicon
Automatically create Google Tasks from Slack/Cisco Webex Teams keywords with webMethods.io Integration
Favicon
How can you become an AWS Community Builder?
Favicon
Automate PagerDuty alerts in Slack/Cisco Webex Teams with webMethods.io Integration
Favicon
I developed a no-code tool that integrates Anthropic into Slack, Teams, and HubSpot
Favicon
"Community Communication: Slack vs. Discord - Deciding the Ideal Platform"
Favicon
Easier TypeScript API Testing with Vitest + MSW
Favicon
Further Tips on Slack's files.upload Deprecation
Favicon
New on Zeeve: Slack & Microsoft Teams Integration for Streamlined Deployment Alerts
Favicon
Rapid Bolt app development w/ Slack CLI and sandboxes

Featured ones: