Skip to content

Commit

Permalink
Add next-gen future documentation (slackapi#761)
Browse files Browse the repository at this point in the history
  • Loading branch information
WilliamBergamin authored Nov 29, 2022
1 parent df35180 commit 929008e
Show file tree
Hide file tree
Showing 40 changed files with 1,191 additions and 179 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ coverage.xml
.python-version
pip
.mypy_cache/
.ruby-version

# JetBrains PyCharm settings
.idea/
Expand Down
1 change: 1 addition & 0 deletions docs/Gemfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
source 'https://rubygems.org'
gem 'github-pages', group: :jekyll_plugins
gem 'dotenv'
gem 'webrick'
11 changes: 8 additions & 3 deletions docs/_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ collections:
tutorials:
output: true
permalink: /tutorials/:slug
future:
output: true
permalink: /future/:slug

defaults:
-
scope:
- scope:
path: ""
values:
layout: "default"
Expand All @@ -35,12 +37,16 @@ t:
advanced: Advanced concepts
start: Getting started
contribute: Contributing
beta: BETA
legacy: LEGACY
ja-jp:
basic: 基本的な概念
steps: ワークフローステップ
advanced: 応用コンセプト
start: Bolt 入門ガイド
contribute: 貢献
beta: BETA
legacy: LEGACY

# Metadata
repo_name: bolt-python
Expand All @@ -56,7 +62,6 @@ google_tag_manager: GTM-KFZ5MK7
markdown: kramdown
kramdown:
parse_block_html: true
parse_span_html: true
syntax_highlighter_opts:
block:
line_numbers: true
Expand Down
19 changes: 19 additions & 0 deletions docs/_future/concepts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
title: Slack developer beta
lang: en
slug: concepts
order: 0
layout: future
permalink: /future/concepts
---
# Slack developer beta concepts <span class="label-beta">BETA</span>

<div class="section-content">

This page contains all the concepts that are necessary to allow you to use the next-gen Slack features in Python.

<p class="alert alert_info">
<ts-icon class="ts_icon_info_circle"></ts-icon>
Our next-generation platform is currently in beta. <a href="https://api.slack.com/future/survey" target="_blank">Your feedback is most welcome</a> - all feedback will help shape the future platform experience!
</p>
</div>
16 changes: 16 additions & 0 deletions docs/_future/deploy_your_app.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---

title: Deploy your app
lang: en
slug: deploy-your-app
order: 6
layout: tutorial
permalink: /tutorial/deploy-your-app
---
# Deploy your app <span class="label-beta">BETA</span>

<div class="section-content">
Instructions for deploying your next-generation Bolt Python application to third-party infrastructure are coming soon! Stay tuned.

<p class="alert alert_info"><ts-icon class="ts_icon_info_circle"></ts-icon>Our next-generation platform is currently in beta. <a href="https://api.slack.com/future/survey" target="_blank">Your feedback is most welcome</a> - all feedback will help shape the future platform experience!</p>
</div>
145 changes: 145 additions & 0 deletions docs/_future/getting_started_future.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
---
title: Getting started
order: 1
slug: getting-started-future
lang: en
layout: tutorial
permalink: /tutorial/getting-started-future
---
## Getting started <span class="label-beta">BETA</span>

<div class="section-content">
This guide will cover how to get started with your next-gen platform using Bolt for Python, by setting up the Slack CLI and installing the required dependencies.

Find out about the next-generation platform on Slack's <a href="https://api.slack.com/future/intro" target="_blank">official introduction page.</a>
</div>

---

### Limitations

Bolt for Python supports app development using next-gen platform features like <a href="/bolt-python/future/concepts#functions" target="_blank">Functions</a>, <a href="/bolt-python/future/concepts#manifest-workflows" target="_blank">Workflows</a> and tools such as the Slack CLI alongside all current generally available Slack Platform features.

#### We do not yet support

- Deployment to secure and managed Slack infrastructure.
- Datastores API <a href="https://api.slack.com/future/datastores" target="_blank">Datastores</a> functionality.

> 💡 If you'd like to deploy your app with Slack infrastructure, consider building your next-generation application with the Deno Slack API. You can get started with that <a href="https://api.slack.com/future/get-started" target="_blank">here</a>.
---

### Setting up {#setting-up}

#### Slack CLI {#setting-up-cli}

To build a next-generation app with Bolt for Python, you'll need to get the Slack CLI.

Install the Slack CLI by following this <a href="https://api.slack.com/future/quickstart" target="_blank">Quickstart</a>. Since we won't be using Deno to build our next-generation app, you can skip any instructions related to installing Deno or creating an app using a Deno template. Once you've logged into the CLI using `slack login` and verified your login using `slack auth list`, you can proceed with the instructions in this guide.

#### Dependencies {#setting-up-dependencies}

Once the CLI is set up, make sure your machine has the most recent version of <a href="https://www.python.org/" target="_blank">Python</a> installed. You can install Python through a package manager (such as <a href="https://brew.sh/" target="_blank">Homebrew</a> for macOS) or directly from the <a href="https://www.python.org/downloads/" target="_blank">website</a>.

---

### Create a new app {#create-app}

Before you start developing with Bolt, you'll want to create a Slack app.

To create the app, you'll run the following command:

```bash
slack create my-app -t slack-samples/bolt-python-starter-template -b future
```

This command creates an app through the CLI by cloning a specified template. In this case, the template is the <a href="https://github.com/slack-samples/bolt-python-starter-template/tree/future" target="_blank">Bolt for Python Starter Template</a> on the `future` branch. This starter template includes a "Hello World" example that demonstrates how to use <a href="/bolt-python/future/concepts#built-in-functions" target="_blank">built-in</a> and <a href="/bolt-python/future/concepts#functions" target="_blank">custom</a> Functions, <a href="https://api.slack.com/future/triggers" target="_blank">Triggers</a> and <a href="/bolt-python/future/concepts#manifest-workflows" target="_blank">Workflows</a>.

Once the app is successfully created, you should see a message like this:

```text
✨ my-app successfully created
🧭 Explore your project's README.md for documentation and code samples, and at any time run slack help to display a list of available commands
🧑‍🚀 Follow the steps below to try out your new project
1️⃣ Change into your project directory with: cd my-app
2️⃣ Develop locally and see changes in real-time with: slack run
3️⃣ When you're ready to deploy for production use: slack deploy
🔔 If you leave the workspace, you won’t be able to manage any apps you’ve deployed to it. Apps you deploy will belong to the workspace even if you leave the workspace
```

---

### Set up your trigger {#setup-trigger}

As mentioned, this app comes with pre-existing functionality - it uses Functions, Workflows and a <a href="https://api.slack.com/future/triggers/link" target="_blank">Link Trigger</a> that will allow users in Slack to initiate the functionality provided by the app. Let's run a command to initialize that Link Trigger via the CLI.

First, make sure you're in the project directory in your command line: `cd my-app`

Then, run the following command to create a Trigger:

```bash
slack triggers create --trigger-def "triggers/sample-trigger.json"
```

The above command will create a <a href="https://api.slack.com/future/triggers/link" target="_blank">Link Trigger</a> for the selected workspace. Make sure to select the workspace you want. Once the trigger is successfully created, you should see an output like this:

```bash
⚡ Trigger created
Trigger ID: [ID]
Trigger Type: shortcut
Trigger Name: Sample Trigger
URL: https://slack.com/shortcuts/[ID]/[Some ID]
```

The provided URL can be pasted into Slack; Slack will unfurl it into a button that users can interact with to initiate your app's functionality! Copy this URL and save it somewhere; you'll need it for later.

---

### Run your app {#run-your-app}

Now that your app and Trigger are successfully created, let's try running it!

```bash
# install the required project dependencies
pip install -r requirements.txt

# start a local development server
slack run
```

Executing `pip install -r requirements.txt` installs all the project requirements to your machine.

Executing `slack run` starts a local development server, syncing changes to your workspace's development version of your app.

You'll be prompted to select a workspace to install the app to&mdash;select the development instance of your workspace (you'll know it's the development version because the name has the string `(dev)` appended).

> 💡 If you don't see the workspace you'd like to use in the list, you can `CTRL + C` out of the `slack run` command and run `slack auth login`. This will allow you to authenticate in your desired workspace to have it show up in the list for `slack run`.
You'll see an output in your Terminal to indicate your app is running, similar to what you would see with any other Bolt for Python app. You can search for the `⚡️ Bolt app is running! ⚡️` message to make sure that your app has successfully started up.

### Trigger your app's workflow {#trigger-workflow}

With your app running, access your workspace and paste the URL from the Trigger you created in the [previous step](/bolt-python/tutorial/getting-started-future#setup-trigger) into a message in a public channel.

> 💡 App Triggers are automatically saved as a channel bookmark under "Workflows" for easy access.
Send the message and click the "Run" button that appears. A modal will appear prompting you to enter information to greet someone in your Slack workspace. Fill out the requested information.

![Hello World modal](https://slack.dev/bolt-js/assets/hello-world-modal.png "Hello World modal")

Then, submit the form. In the specified channel submitted in the form, you should receive a message from the app tagging the submitted user. The message will also contain a randomly generated greeting and the message you wrote in the form.

The full app flow can be seen here:
![Hello World app](https://slack.dev/bolt-js/assets/hello-world-demo.gif "Hello World app")

---

### Next steps {#next-steps}

Now we have a working instance of a next-generation app in your workspace and you've seen it in action! You can explore on your own and dive into the code yourself <a href="https://github.com/slack-samples/bolt-python-starter-template/tree/future" target="_blank">here</a> or continue your learning journey by diving into [App Manifests](/bolt-python/future/concepts#manifests) or looking into adding more [Functions](/bolt-python/future/concepts#functions), [Workflows](/bolt-python/future/concepts#manifest-workflows), and [Triggers](#setup-trigger) to your app!
105 changes: 105 additions & 0 deletions docs/_future/listening_responding_functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
title: Listening & responding to functions
lang: en
slug: functions
order: 5
layout: future
---

<div class="section-content">

Your app can use the `function()` method to listen to incoming function requests. The method requires a function `callback_id` of type `str`. This `callback_id` must also be defined in your [Function](/bolt-python/future/concepts#manifest-functions) definition. Functions must eventually be completed with the `complete()` function to inform Slack that your app has processed the function request. `complete()` requires **one of two** keyword arguments: `outputs` or `error`. There are two ways to complete a Function with `complete()`:

* `outputs` of type `dict` completes your function **successfully** and provides a dictionary containing the outputs of your function as defined in the app's manifest.
* `error` of type `str` completes your function **unsuccessfully** and provides a message containing information regarding why your function was not successful.

</div>

<div>
<span class="annotation">Refer to <a href="https://slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html" target="_blank">the module document</a> to learn the available listener arguments.</span>
```python
# The sample function simply outputs an input
@app.function("sample_function")
def sample_func(event: dict, complete: Complete):
try:
message = event["inputs"]["message"]
complete(
outputs={
"updatedMsg": f":wave: You submitted the following message: \n\n>{message}"
}
)
except Exception as e:
complete(error=f"Cannot submit the message: {e}")
raise e
```
</div>

<details class="secondary-wrapper">
<summary markdown="0">
<h4 class="secondary-header">Function Interactivity</h4>
</summary>

<div class="secondary-content">

The `function()` method returns a `SlackFunction` decorator object. This object can be used by your app to set up interactive listeners such as [actions](/bolt-python/concepts#action-respond) and [views](/bolt-python/concepts#view_submissions). These listeners listen to events created during the handling of your `function` event. Additionally, they will only be called when a user interacts with a block element that has the following attributes:

* It was created during the handling of a `function` event.
* The `action_id` matches the interactive listeners `action_id`.

These listeners behave similarly to the ones assigned directly to your app. The notable difference is that `complete()` must be called once your function is completed.

</div>

```python
# Your listener will be called when your function "sample_function" is triggered from a workflow
# When triggered a message containing a button with an action_id "approve_button" is posted
@app.function("sample_function")
def sample_func(event: dict, complete: Complete):
try:
client.chat_postMessage(
channel="a-channel-id",
text="A new button appears",
blocks=[
{
"type": "actions",
"block_id": "approve-button",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Click",
},
"action_id": "sample_action",
"style": "primary",
},
],
},
],
)
except Exception as e:
complete(error=f"Cannot post the message: {e}")
raise e

# Your listener will be called when a block element
# - Created by your "sample_func"
# - With the action_id "sample_action"
# is triggered
@sample_func.action("sample_action")
def update_message(ack, body, client, complete):
try:
ack()
if "container" in body and "message_ts" in body["container"]:
client.reactions_add(
name="white_check_mark",
channel=body["channel"]["id"],
timestamp=body["container"]["message_ts"],
)
complete()
except Exception as e:
logger.error(e)
complete(error=f"Cannot react to message: {e}")
raise e
```

</details>
Loading

0 comments on commit 929008e

Please sign in to comment.