make SaaS その他

make 基本操作編 機能紹介:Scenario、Template

この記事は「make Advent Calendar 2024」4日目の記事です。

このアドベントカレンダーについて

このアドベントカレンダーは25日間でIPaaS製品の「make」について使い方や、実践を学べる連続ブログ企画です。

おかしん」「ばるす」「たにあん」の3名がリレー形式でお届けします。

25日間のスケジュールは以下の通りです。

日付内容担当
12/1話題のIPaaS製品「make」とはおかしん
12/2makeで作ってみたScenario紹介ばるす
12/3make 基本操作編 機能紹介:Organizationたにあん
12/4make 基本操作編 機能紹介:Scenario、Templateおかしん
12/5make 基本操作編 機能紹介:Connectionsばるす
12/6make 基本操作編 機能紹介:Webhooksたにあん
12/7make 基本操作編 機能紹介:DataStores、DataStructuresおかしん
12/8make 基本操作編 機能紹介:Devicesばるす
12/9make 基本操作編 機能紹介:Functionsたにあん
12/10make 基本操作編 機能紹介:CustomAppsおかしん
12/11make 基本操作編 機能紹介:Flow Control,Tools,Text parserばるす
12/12make ドキュメント動線の話:ResourceHubたにあん
12/13make 検証:Make Bridgeおかしん
12/14make 検証:Make REST APIばるす
12/15make 検証:AI Searchたにあん
12/16make Community Hub:Overviewおかしん
12/17make Community Hub:Academy Courses,Blog Articlesばるす
12/18make Community Hub:Showcase,CustomAppsたにあん
12/19makeの管理運用の話:Github連携おかしん
12/20makeの管理運用の話:実行ログと再実行と停止中リクエスト滞留ばるす
12/21makeの管理運用の話:Connection権限管理たにあん
12/22makeで作ってみた事例:(未定)おかしん
12/23makeで作ってみた事例:(未定)ばるす
12/24makeで作ってみた事例:(未定)たにあん
12/25makeの総論を語るばるす

Scenarioとは

この記事ではmakeのScenarioについて解説します。makeにおけるScenarioとは、ZapierにおけるZap、Power Automateにおけるフローです。

つまり今回の連載企画の中で、一番重要なのがこの記事ということになります。

実際に作ってみる

Scenarioを作成するとこのような画面になります

例えば、「Slackで新しいチャンネルが作成されたら、特定のチャンネルに通知する」といったScenarioを作ってみます。

トリガーの設定

アプリの一覧からSlackを探して、トリガーを追加します。

ですが、Zapierに慣れている私は、この時点でちょっと戸惑いました。

「え、用意されてるトリガー少なくない???」

makeの場合Slackで用意されているトリガーは7つしかありません。

  • チャンネルなどにメッセージが投稿されたら発火する
    • Watch Public Channel Messages
    • Watch Private Channnel Messages
    • Watch Direct Messages
    • Watch Multiparty Direct Messages
  • ファイルが追加されたら発火
    • Watch Files
  • 新しいユーザーが追加されたら発火
    • Watch Users
  • 新しいイベントが発生したら発火
    • New Event

この7つの中で「New Event」だけが異質ですが、試しに追加してみます。

Create a webhookして、Event typeを選択します。

ご覧のように、選べるEvent Typeは6つしかありません。そのうち5つは、New Event以外のものとかぶっています。(メッセージ系の4つと、特定の新しいファイルが追加されたら発火するもの。)

かぶっていないのは「New reaction」ですが、これは新しい絵文字が追加されたら発火するのではなく、特定のメッセージにリアクションがつくと発火するものです。

ですので、実質Slackで用意されているトリガーはやはり7個です。

余談:makeでトリガーに取れるもの

Watchって書いてるもの

TRRIGERSというカテゴリでくくられているもの

INSTANTタグがついているもの

基本的にはこの3種類だけです。ほとんどの場合「Watch」がついています。残念ながら今のところトリガーだけを表示したりといったことはできないので、これらを目で見て判断するしか無いです。

INSTANTとついているものだけが即時実行され、それ以外は定期実行です(makeが各システムに対して更新が無いかどうかを見に行く)

詳しくは以下のヘルプをご参考ください。

https://www.make.com/en/help/modules/types-of-modules#triggers–searches–actions–and-universal-modules

即時発火の「Webhook」トリガーがあるので、HTTPリクエストさえ飛ばせれば基本的には即時発火できます。

mailhookは少しユニークで、HTTPリクエストではなく、makeが作成してくれたメールアドレスにメールが届いたら発火します。メール通知しか無いシステムと連携させる際に便利かもしれません。

Webhookトリガーを作る

というわけで今回は「新しいチャンネルが作成されたら発火」したいので、Slackのモジュールは使わず「Custom webhook」のトリガーを使います。

「Create a webhook」でWebhookを受けるURLを生成するのですが、私のおすすめとしては「advansed settings」をオンにして、「Get request headers」をオンにしておくことです。これをオンにしておくことで、後続のモジュールや分岐の際に飛んできたリクエストのヘッダーの情報を使うことができるからです。これをオンにしていない場合は後続のモジュールではリクエストボディしか表示されません。

毎回使うわけではありませんが、ヘッダーを見る癖をつけておくと条件分岐などの制御の幅が広がるので、常にオンにしておくことをおすすめします。

作成したらURLをコピーしておきます

SlackのイベントをWebhookトリガーに飛ばすための準備

Slack Appを作成する必要があります。

こちらのページから新しくアプリを作成します。

App Homeからアプリの名前を設定しておきます(これをやらないとアプリのインストールでこけます)

Event SubscriptionsのEnable Eventsをオンにします

Request URLに先ほどコピーしておいたmakeのWebhookトリガーのURLをペーストすると、「Your URL didn’t respond with the value of the challenge parameter」というエラーが出るはずです。

これは何を意味しているかというと、SlackのEvent Subscriptionsは最初にChallengeというリクエストを送って、応答が返ってこないと使えないという仕組みになっているのです。(詳細はこちら

Enable Eventsをオンにして、URLをペーストした時点で、そのURLに対してSlackは以下のようなリクエストを投げます。

{
    "token": "Jhj5dZrVaK7ZwHHjRyZWjbDl",
    "challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P",
    "type": "url_verification"
}

challenge の値をそのままオウム返ししてあげることで、Slackは送信先のURLが有効であることを確認できます。

ではこれをmakeで行うにはどうすれば良いか?

まずはScenarioを「Run once」状態にします。これは一度だけ実行待ち状態にするということです。

その後、Slack App側でリトライします。

すると、make側でChallengeリクエストを確認することができます

この challenge の値を返してあげればよいので、後続モジュールとして、もう一つ「Webhook response」を追加します

SlackAPIのヘルプによると、ステータスは200で、valueだけを返しても良いし、 challenge=valueとしても良いし、{challenge:"value"}のようにJSONで返しても良いと書かれているので一番簡単な値だけを返すように作ります。

このまま保存して再度「Run Once」します。

再度リトライします

Verifiedになりました

これで、やっとWebhookトリガーが使える状態になりました。

リクエストのタイプを設定する

今回は channel_created のBot User Eventを使います。(なおパブリックチャンネルでしか機能しません)

イベントを保存して、アプリをワークスペースにインストールしておきます。

実際にチャンネル通知のリクエストを受けてみる。

再度、ScenarioをRun once状態にして、Slackでチャンネルを追加してみます。

すると先ほどと同様に、makeにリクエストが飛んできます。

ではここから通知の方を作っていきます。

通知用のモジュールを追加する

まずは分岐を作らないといけないので、2つのモジュールの間のスパナのようなアイコンをクリックして、「Add a router」します。

追加したRouterをクリックすると分岐が生まれて、もう一つモジュールを追加できるようになります

Slackモジュールの「Create a Message」を追加します

Botとしてconnectionを追加します

通知の文章を作ります。

通知を行うBotのアイコンや名前を設定したい場合は「advanced settings」で設定します。

試しにこのモジュールをテストしてみます。これはmakeの特徴の一つなのですが、モジュール単位でテストの入力を設定してテストが可能です。モジュールを右クリックして「Run this module only」

設定したチャンネルに通知が届くのを確認できます

チャンネルがリンク化されていないので、モジュールの設定を変更します。advanced settingsの「Link names」を「Yes」にするとリンク化されます。

再度モジュールをテストするとリンク化されていることが確認できます(Link namesを有効にしてもリンク化されない場合は、「#チャンネル名」と「が作成されました」の間にスペースが入っていることを確認してください)

では、機能が完成したので、受信待ちの状態にしてからCmd-SでScenarioを保存し、左上から画面を一つ戻ります

Scenarioを有効にします

新しく #test-channel2 というチャンネルを作成してみます

makeでScenarioが実行されます。

通知が届きました

Scenarioのその他の機能を理解する

Scenarioを作るということに関して基本的な動作を解説しましたが、Scenario作成画面には他にも様々な機能があります。

Router発展編

先ほどの実行結果ですが、Challengeリクエストに使っていたWebhookレスポンスも起動してしまっていることが確認できます。

ただ、この処理は初回のEvent Subscriptionを追加する際にのみ必要な処理です。makeでは実行されたモジュール数で課金体系が変わってくるので極力余計な処理はしたくありません。

Routerモジュールは何も条件を指定しない場合は全ての後続モジュールを順番に実行します。今回の場合はWebhookレスポンスもSlack通知もどちらも実行されました。

Slack通知だけが実行されるようにRouterに条件を追加します。正確に言えばRouterとその後ろのモジュールの間に設定します。Challengeリクエスト用のモジュールの間にあるスパナアイコンから「Set up a filter」します

Requestのタイプが url_verification の時のみ実行されるように設定しました

Scenarioを保存して、 #test-channel3 を作成すると、再度Scenarioが実行されますが、Challengeリクエストの方は実行されていないことがわかります。

もちろん通知は正しく実行されました

ちなみにですが、「初回しか使わないのならChallengeリクエスト終わったらモジュールごと削除すれば?」という意見もあるかと思います。何故そのまま残してRouterで処理しているかというと再利用性を考えてのことです。この後説明しますが、コピペ機能やエクスポートの機能で他のScenarioで一連のモジュールを再利用することができます。SlackのEventトリガーとして今回の処理は何度も使うことになるので、あえて残しています。

Auto-align

Scenarioを作っていると、各モジュールを綺麗に整頓したくなる時があります。そんな時に便利なのが Auto-align。

いい感じに綺麗にしてくれます

Notes

モジュールなどにメモを残す機能です。モジュールを右クリックして「Add a note」

モジュールごとに何をやっているのかをメモできます。Webhookの場合は、当該Webhookを飛ばしているアプリなどへリンクしておくとチーム管理しやすいと思います。

ビルトインモジュール

makeには、Webアプリに関するモジュール以外にもビルトインで様々な機能があります。

Frow Control

配列を作ったり、繰り返し処理を行ったりするのはこちらのモジュールを使います。また、エラーハンドリングにも多用します。

Tools

手動実行のトリガーや、変数宣言、変数への代入、変数からの取り出しなどはこれらのモジュールを使います。後日解説するData Store(データベースのようなもの)などと組み合わせることで大規模なシステムを構築することも可能です。

Text Parser

文字列の変換を行ったりマッチ検索を行ったりといった操作はこれらのモジュールで行います。

コピペ機能

モジュールを右クリックして Copy module

何もないところを右クリックして「Paste」

これは別のScenarioでも有効に機能します。また、メモ帳などにペーストしてみると以下のようなJSONであることがわかります。

{
    "subflows": [
        {
            "flow": [
                {
                    "id": 5,
                    "module": "slack:CreateMessage",
                    "version": 4,
                    "parameters": {
                        "__IMTCONN__": 31494
                    },
                    "mapper": {
                        "text": "#{{1.event.channel.name}} が作成されました",
                        "parse": false,
                        "mrkdwn": true,
                        "channel": "C083LJ8F1N1",
                        "username": "チャンネル追加通知",
                        "icon_emoji": "tada",
                        "link_names": true,
                        "channelType": "public",
                        "channelWType": "list"
                    },
                    "metadata": {
                        "designer": {
                            "x": 600,
                            "y": 300
                        },
                        "restore": {
                            "expect": {
                                "parse": {
                                    "mode": "chose"
                                },
                                "mrkdwn": {
                                    "mode": "chose"
                                },
                                "channel": {
                                    "mode": "chose",
                                    "label": "info-channel"
                                },
                                "link_names": {
                                    "mode": "chose"
                                },
                                "channelType": {
                                    "label": "Public channel"
                                },
                                "channelWType": {
                                    "label": "Select from the list"
                                },
                                "unfurl_links": {
                                    "mode": "chose"
                                },
                                "unfurl_media": {
                                    "mode": "chose"
                                },
                                "reply_broadcast": {
                                    "mode": "chose"
                                }
                            },
                            "parameters": {
                                "__IMTCONN__": {
                                    "data": {
                                        "scoped": "true",
                                        "connection": "slack3"
                                    },
                                    "label": "My Slack (bot) connection (make)"
                                }
                            }
                        },
                        "parameters": [
                            {
                                "name": "__IMTCONN__",
                                "type": "account:slack2,slack3",
                                "label": "Connection",
                                "required": true
                            }
                        ],
                        "expect": [
                            {
                                "name": "channelWType",
                                "type": "select",
                                "label": "Enter a channel ID or name",
                                "required": true,
                                "validate": {
                                    "enum": [
                                        "manualy",
                                        "list"
                                    ]
                                }
                            },
                            {
                                "name": "text",
                                "type": "text",
                                "label": "Text"
                            },
                            {
                                "name": "blocks",
                                "type": "text",
                                "label": "Blocks"
                            },
                            {
                                "name": "thread_ts",
                                "type": "text",
                                "label": "Thread message ID (time stamp)"
                            },
                            {
                                "name": "reply_broadcast",
                                "type": "boolean",
                                "label": "Reply broadcast"
                            },
                            {
                                "name": "link_names",
                                "type": "boolean",
                                "label": "Link names"
                            },
                            {
                                "name": "parse",
                                "type": "boolean",
                                "label": "Parse message text"
                            },
                            {
                                "name": "mrkdwn",
                                "type": "boolean",
                                "label": "Use markdown"
                            },
                            {
                                "name": "unfurl_links",
                                "type": "boolean",
                                "label": "Unfurl primarily text-based content"
                            },
                            {
                                "name": "unfurl_media",
                                "type": "boolean",
                                "label": "Unfurl media content"
                            },
                            {
                                "name": "icon_emoji",
                                "type": "text",
                                "label": "Icon emoji"
                            },
                            {
                                "name": "icon_url",
                                "type": "url",
                                "label": "Icon url"
                            },
                            {
                                "name": "username",
                                "type": "text",
                                "label": "User name"
                            },
                            {
                                "name": "channelType",
                                "type": "select",
                                "label": "Channel type",
                                "required": true,
                                "validate": {
                                    "enum": [
                                        "public",
                                        "private",
                                        "im",
                                        "mpim"
                                    ]
                                }
                            },
                            {
                                "name": "channel",
                                "type": "select",
                                "label": "Public channel",
                                "required": true
                            }
                        ],
                        "advanced": true
                    }
                }
            ]
        }
    ],
    "metadata": {
        "version": 1
    }
}

そうなのです、 makeでは全てのモジュールは単一のJSONで構成されているのです。この記法で書けばモジュールを作ることも可能ですし、もしかしたらGitHubで管理することも可能ではないかと思案しているところです。

Export機能

Scenario全体をJSONファイルとしてエクスポート可能です

勘の良い方ならお気づきかと思いますが、エクスポートしたファイルは先ほどのモジュールのJSONを内包したJSONになっています。もちろんこれをインポートすることも可能です。

余談ですが、Power Automateも似たようなことができるのですが、エクスポートしたJSONの視認性や再利用性は make の方が圧勝している印象です。

Templateについて

Templateを使ってみる

makeにはScenarioのTemplateという機能があります。サイドバーからアクセス可能です。

公式に提供されているものやコミュニティベースのテンプレートなど様々なテンプレートが公開されており、利用しているアプリを絞って検索することも可能です。マウスオーバーすることで大まかな説明を見ることができます。

Templateを利用することで、Scenarioを簡単に作ったり、参考にしたりできます。試しに使ってみましょう。ZoomのレコーディングをOpenAIのWhisperで翻訳・要約してSlackに通知するようなシナリオがありました。

Start guided setupをクリックするとこのように、個別に設定しなければいけない箇所がステップごとに表示されて簡単にScenarioを作ることができます。

Templateを作ってみる

Templateは自分で作ることもできます。またPublicに公開することもできますし、組織内にのみ公開することもできます。Template画面の右上の「New template」から作成します。

せっかくなので先ほどExportしておいたBlueprintを使います

先ほど作ったScenarioが読み込まれました

SlackのEvent Subscriptionを受け取るWebhookトリガーはしょっちゅう使うので、その部分だけテンプレ化してみます。Slack通知のモジュールを削除して保存します。

Team Templateの中に保存されます

テンプレートを開いて、Create Scenarioすると、このテンプレートを使って新たにScenarioを作成することができます。

そのはずだったのですが、エラーが出てしまいました。

ヘルプによるとWebhookトリガーのテンプレートは作れないとのことでしたので、トリガーを削除したテンプレートにしてみました。

このテンプレートを使ってみると新しくScenarioが作成されました。

ここからWebhookトリガーを追加してやれば良さそうです

今回作ったテンプレートはSlackのEvent SubscriptionのChallengeリクエストの処理部分だけだったので恩恵が少ないですが、もっと複雑なものをテンプレート化しておくと、チーム内での自動化開発が捗りそうです。

また、公式が審査をしているということは公開されているテンプレートはある程度安心して使えそうな気はします。

なお、テンプレートを公開しようとすると審査が入るようです。いつかテンプレートの公開もやってみたいですね。

とりあえず今回のものはおそらく通らないのでUnpublishしておきます。

あとがき

いかがでしょうか?makeの根幹部分であるScenarioについて紹介させていただきました。皆さんも是非たくさんのScenarioやTemplateを作ってみてください。

明日(というかもう今日ですが)は「ばるす」さんによるConnectionの解説です。

okash1n

香川大学医学部医学科中退→SES・情シス・SREを経てクラウドネイティブ入社。趣味はIT。

・有限会社脇屋 代表取締役
・一般社団法人日本ビジネステクノロジー協会 代表理事
・一般社団法人 SRE NEXT 理事
・情シスSlack、BTCONJP、SRENEXT運営