完璧にSlackボットを作成し、Hubotを介してGitHubアクションを呼び出す方法

GitHub Actionsをビルドおよびリリースパイプラインとして使用し、チームがSlackも使用している場合、Slackを離れる必要すらありませんか?Slackボットを作成して、Slackから直接GitHub Actionsワークフローを呼び出すように設定しましょう!

このチュートリアルでは、Hubotというボット構築ツールを使用して新しいSlackチャットボットを設定し、GitHub Actionsワークフローを自動的に開始してコードをサーバーにデプロイする方法を学びます。

さあ、始めましょう!

前提条件

このチュートリアルは実演形式です。一緒に進める場合は、次のものがあることを確認してください:

  • A Slack Workspace
  • A GitHub account and a GitHub personal token
  • A Linux server to deploy code to – This tutorial will use Ubuntu 19.
  • A local Linux machine – This tutorial will use Ubuntu so that all local commands will be Linux. If you’re running another operating system, the commands may be slightly different.
  • サーバーに接続するためのSSH資格情報。
  • A code editor of your choice that understands YAML like Visual Studio Code.

プロジェクトの作成とGitHub Actionsワークフロー

SlackからGitHub Actionsワークフローを簡単に呼び出す前に、まずワークフローを作成する必要があります。

ワークフローを作成するには、まずプロジェクトフォルダーを作成して、作業に使用するすべてのファイルを格納します。

1. お気に入りのターミナルアプリケーションを開きます。

2. 次に、以下のコマンドシリーズを実行して、プロジェクトフォルダーHubotを作成し、そのフォルダーに移動します。

mkdir ~/Hubot # Hubotというディレクトリを作成
cd ~/Hubot    # Hubotディレクトリに移動

3. 次に、npm initを実行して、Node.JS package.jsonファイルを作成します。npm initを実行すると、プロジェクトに関するさまざまな情報と依存するNPMパッケージに関する情報を含むpackage.jsonファイルが作成されます。

npm init      # package.jsonファイルを初期化

4. そして、workflowsディレクトリとdeploy.yml ワークフローファイルを作成します。ワークフローファイルは、GitHub Actionsが従う一連のステップを定義したものです。

mkdir .github/workflows && touch deploy.yml

5. 次に、ワークフローが読み取るGitHubのシークレットをそれぞれ定義します。あなたが作成しようとしているワークフローは、これらのシークレットを参照します。SSHにサーバーアドレス、ユーザー名、パスワード、およびサーバーのポートが必要になるので、GitHubのシークレットを作成しましょう。

このURLhttps://github.com/yourusername/yourrepository/settings/secrets/actionsを訪問して、GitHubのシークレットを追加します。yourusernameをあなたのGitHubのユーザー名、yourrepositoryをあなたのGitHubのリポジトリに置き換えてください。

以下に示すように、新しいリポジトリのシークレットボタンをクリックして、追加するシークレットの情報を入力してください。

Adding GitHub Secrets

6. 次に、シークレットの名前と値のフィールドを入力し、[シークレットを追加] をクリックして保存します。ページはGitHubのシークレットページにリダイレクトされ、すべてのシークレットが表示されます。さらにシークレットを追加するには、前述の手順と同じく、[新しいリポジトリのシークレット] ボタンをクリックしてください。

指定された変数のシークレットを正確に同じ名前で保存してください。これらは、HOST、USERNAME、PASSWORD、およびPORTという同じ変数を参照するためです。

Filling up Information for a GitHub Secret
Viewing All GitHub Secrets

7. 最後に、コードエディターで~/Hubot/.github/workflows/deploy.ymlワークフローファイルを開き、以下のコードをコピー/貼り付けてください。以下のコードは、後でSlackを介してワークフローをトリガーするたびに実行されるワークフローです。

ワークフローを呼び出すと、いくつかのアクションが実行されます:

  • GitHub Actionsは、以下のワークフローファイルを解析して、HOSTシークレットで定義されたターゲットhostにSSHできます。そして、USERNAMEおよびPASSWORDもシークレットで定義され、それらを使用しています。
  • その後、ワークフローは特定のブランチ($branchName)のGitHubリポジトリの内容をダウンロードします。これはgit pull origin$branchNameを実行することによって行われます。ブランチ名には、デプロイしたいコードが含まれていることを確認してください。
  • あなたはWorkflow Packageを使用しています。これはGithub Marketplaceからのもので、ssh-remote-commandsと呼ばれています。このパッケージには、本番環境で実行するホスト、ユーザー名、パスワード、ポート、およびコマンドだけを提供する必要があるという便利なラッパーがあります。

サーバーには、GitHubリポジトリからコードをプルするために必要なログイン資格情報が含まれていることを確認してください。

# 名前は、プログラム的にはるかに多くのことを参照されます 
name: deploy 
on:
  # イベント respository_dispatch は、すべての API トリガーで意味します。 
  # このファイル全体が実行されます
  repository_dispatch: 
    types: [deploy-service]
# 複数のジョブがあるかもしれませんが、現時点では、 
# このチュートリアルでは、1つのみ動作します
jobs:
  deploy:
    name: Deploy
    # YAML で全てのコードが実行されるベースイメージの名前
    runs-on: ubuntu-latest
    steps:
    - name: executing remote ssh commands using password
      # appleboy/ssh-action@master は、オープンソースのパッケージです 
      # ssh 経由でサーバーにログインし、スクリプトを実行します
      uses: appleboy/ssh-action@master
      # これらは、一般的にパッケージが必要とする変数です 
      # サーバーにログインし、スクリプトを実行するために
      with:
       # シークレットは、次の変数です 
       # https://docs.github.com/en/actions/security-guides/encrypted-secrets

       # サーバーのホストは、github シークレットに保存されています。同じ名前の HOST
        host: ${{ secrets.HOST }} 
        # ログインするサーバーのユーザー名 
        # これは、github シークレットに保存されています。名前は USERNAME
        username: ${{ secrets.USERNAME }} 
        # ログインするサーバーのパスワード 
        # これは、github シークレットに保存されています。名前は PASSWORD        
        password: ${{ secrets.PASSWORD }} 
        # ログインするサーバーのポート 
        # これは、github シークレットに保存されています。名前は PORT
        port: ${{ secrets.PORT }}  
        # deploy-app.sh は、GitHub からコードをプルして
        # Web サーバーを再起動するなど、何でもかまいません
        # サーバーにリポジトリがクローンされていることを確認してください 
        # 好きなだけ多くのスクリプトを実行できます
        script: git pull origin {{ github.event.client_payload.branch 

ワークフローを手動で実行する

Slackから呼び出すためにGitHub Actionsのワークフローを作成しましたが、この時点ではコードはローカルマシン上にしかありません。ワークフローをトリガーするには、コードをGitHubにプッシュする必要があります。

以下のコマンドを実行すると、gitにコードをプッシュおよびプルすべき場所を指定します。以下のgit remote add originコマンドでは、yourusernameyourrepositoryをGitHubのユーザー名とリポジトリに置き換えてください。

# github.comを開いてリポジトリを作成します
git init # gitを初期化します
git remote add origin https://github.com/yourusername/yourrepository.git
git add . # gitが追跡するために新しく作成したファイルを追加します
git commit -m "Created GitHub workflow file"
git push -u origin master

まず、コードが正常に動作するかテストしましょう。人気のあるcurlユーティリティを使用してコードを手動で呼び出します。

以下のコマンドを実行して、GitHubリポジトリhttps://github.com/username/repository/dispatchesのURLにPOSTリクエストを送信し、先に作成したdeploy.ymlというワークフローファイルをトリガーするようGitHubに指示します。usernameを実際のGitHubのユーザー名、repositoryをGitHubのリポジトリに置き換えてください。

以下のコード内の$github_personal_tokenを、個人のトークンで置き換えてください。

# https://github.com/username/repository/dispatches URL で投稿リクエストを作成します 
curl-X POST  https://github.com/username/repository/dispatches \
# コンテンツタイプを受け入れるためのヘッダーを追加
-H 'Accept: application/vnd.github.everest-preview+json' \
# 認証のためのヘッダーを追加
-H "Authorization: token $github_personal_token" \
# 複数のパラメータを送信できるように、投稿リクエストのボディに JSON コンテンツを追加します 
# このデータセクションから引数に基づいてさまざまなアクションを実行できます
--data '{"event_type": "deploy-service", "client_payload": {"environment": "'"$1"'", "ref": "'"$2"'"}}' # 環境の名前と ref をブランチ名として渡すことができるため、どのサーバーにデプロイするかがわかります

Hubot で Slack ボットを作成

GitHub アクションワークフローを手動でトリガーできたので、良いスタートです。これから、同じ手動手順を Slack ボットを介して自動化してみましょう。Slack ボットを作成し、コマンドを受け取って引数で GitHub アクションをトリガーします。

Slack ボットを作成する方法は2つあります。Scratch から作成するか、Slack ワークスペース用の事前ビルドされた hubot パッケージを使用するかです。このチュートリアルでは、Hubotと呼ばれる事前ビルドのボットパッケージを使用します。Hubot は、Slack、Discord、Gitter、TeamSpeak などのチャットサービスと統合されたオープンソースの自動化ツールです。

Hubotを使用せずにカスタムボットを作成するには、多くの時間がかかります。なぜなら、すべてのセットアッププロセス(Webフックの受信、ボットのホスティング)を自分で処理する必要があるからです。そのため、このチュートリアルでは、Hubot Slackアプリを使用してこれらのプロセスを簡略化します。

HubotのNpmによるインストール

Hubotを使用してSlackボットを作成するために、まずローカルマシンにHubotをダウンロードしてインストールします。Hubotは、SlackとGitHubのアクションをリンクするコネクタとなります。

1. ターミナルで、プロジェクトディレクトリ(~/Hubot)に移動(cd)します。

cd ~/Hubot

2. 次のnpm installコマンドを使用して、yogenerator-hubotパッケージをローカルマシンにグローバルに(-g)インストールします。 yoパッケージは新しいプロジェクトをインストールするために使用され、任意の言語(Web、Java、Python、C#など)のプロジェクトを生成します。 generator-hubotパッケージは、yoパッケージを使用してすべての依存関係と初期セットアップをインストールします。

インストールが完了すると、グローバルにインストールされたため、どこからでもyoコマンドを実行できます。

npm install -g yo generator-hubot

3. 以下のコマンドで基本的なHubotのボイラープレートを作成します。ボイラープレートは、多くの場所に含まれるコードのセクションです。ボイラープレートがないと、常にゼロからコードを書く必要があります。

以下のコマンドは、プロジェクトディレクトリに基本的なHubotのボイラープレートを作成します。Hubotのボイラープレートは、Slack(--adapter=slack)とリンクしているため、ボットはSlackチャンネル内のメッセージを受信し、応答することができます。yo hubot --adapter=slack

yo hubot --adapter=slack

SlackワークスペースにHubotを追加する

Hubotがローカルマシンにインストールされたので、HubotをSlackとの通信に設定する必要があります。

SlackワークスペースにHubotをインストールしましょう。

1. ウェブブラウザを開き、https://workspacename.slack.com/admin/settingsのようなURLでSlackの管理設定に移動します。workspacenameを実際のSlackワークスペース名に置き換えてください。

左側のパネルでアプリの設定をクリックし、下の画像のようにHubotをマーケットプレイスで検索できるようにします。Slackには事前に作成されたアプリケーションがあるマーケットプレイスがあります。

Accessing Slack Admin Settings

2. 検索バーをクリックし、hubotと入力してマーケットプレイスでHubotを検索し、Hubotを選択します。

次に、下の画像に示すように、Slackに追加ボタンをクリックしてHubotをSlackワークスペースに追加します。

Searching Hubot and Adding it to Slack Workspace

3. 最後に、Botの名前(deployerhubot)やアイコンなど、Botに関する一般情報を入力します。後でHubot DeployerでBotをアクティブ化する際に、APIトークンを控えておいてください。以前に作成したHubotプロジェクトからBotをアクティブ化するために使用します。

Setting up Bot Information and Taking Note of the API Token

SlackとのGitHub Actionsワークフローの統合をテストする

SlackワークスペースにHubotがインストールされたので、Botをテストしてみましょう。まず、Botをアクティブ化する必要があります。

1. プロジェクトのルートディレクトリ内で以下のコマンドを実行して、Hubotリポジトリ(./bin/hubot)からSlack(--adapter slack)のためのBotをアクティブ化します。以前に控えた$tokenをAPIトークンで置き換えてください。

HUBOT_SLACK_TOKEN=$token ./bin/hubot --adapter slack

2. 以下のコマンドを実行して、Bot(botusername)をSlackチャンネルに招待(/invite)します。ステップ3の「SlackワークスペースにHubotを追加する」セクションで登録したBotの名前でbotusernameを置き換えてください。

/invite deployerhubot

そして、Slackでテキストと一緒にBotをメンションして、@deployerhubot ping,のようにして、統合が機能しているかテストしてください。BotがPONGと応答した場合は、以下のように表示されます。それで準備完了です。

Testing Hubot and Slack Integration

Botが応答しない場合は、WebブラウザでGitHubリポジトリに移動し、Actionsタブをクリックしてください。ラウンドの赤いチェックバッジが表示されているワークフローが失敗したことがわかります。失敗したワークフローをクリックして、失敗の原因を確認し修正してください。

Viewing Failed Workflows

以下、失敗が発生しているのを見ることができます:パスワードを使用してリモートSSHコマンドを実行する。 ワークフローを修正した後、ステップ3に戻って、BotがPONGと応答するかどうかを確認してください。

Navigating to GitHub repository to fix failed workflow

SlackからGitHubアクションワークフローを開始する

Slack Botを有効にしたら、SlackからGitHubアクションワークフローを開始する時間です!

指定されたブランチを指定されたサーバーにデプロイする柔軟性が必要です。指定されたブランチからコードをプルするようにします。誰かがSlackチャンネルで***@*bot deploy API feature-x to productionと入力すると、Botが自動的に応答するように教えます。環境名を検証できるようにします。後で、人々は特定の環境とブランチのみをデプロイできます。

Botの応答を自動化するには:

1. 〜/Hubot/scriptsという名前のディレクトリを作成します。 〜/Hubot/scriptsディレクトリは、GitHubワークフローをトリガするスクリプトを保存する場所です。

2. コードエディタで、〜/Hubot/scriptsディレクトリ内にbot.jsという名前のファイルを作成します。 次に、以下のコードをコピーしてbot.jsファイル内に貼り付けます。

以下のコードは、BotがSlackチャンネル上のチャットメッセージをリッスンし、次にワークフローをトリガしてSlackチャンネルに応答を送信することを可能にします。

const validServices = ['api','app'];
const validEnvironments = ['production'];
robot.hear (`@${process.env.BOT_ID}`,async (bot) => {
    //ボットはメッセージを聞くことに興味があります
    //例:@deploy api featurexを本番環境にデプロイ
    //再利用可能な変数の設定
	  const payload = bot.message.text.split(" ")
    const service = payload[2];
    const branch = payload[3];
    const environment = payload[5];
    const username = bot.message.user.name;
    //処理中であることをユーザーに通知
    bot.send(`Roger that! Please wait.`);
//使用されたコマンドが有効かどうかを検証
//ユーザーは無効なコマンドも使用できるため
if(!validateCommand(bot,username,service,branch,environment)) {
      return;
    }
    //コマンドが有効に見える場合は、ワークフローをトリガー
    await triggerWorkflow(bot,username,service,environment,branch)
    
    //ユーザーにワークフローが正常にトリガーされたことを通知
    bot.send(`Github Action has been triggered successfully`);
  })
  const validateCommand = (bot,username,service,branch,environment) => {
    //サービスを制限する(ユーザーはリストにないサービスを使用できるため)
    //これにより、ワークフローがトリガーされ、エラーが発生します
    if(!validServices.includes(service)) {
       bot.send(`${service} is not availble, Only ${validServices.join(', ')} are available`);
      return false;
      }
      //環境を制限する(ユーザーは無効な環境のリストも使用できるため)
      if(!validEnvironments.includes(environment)) {
        bot.send(`${environment} is not availble. Only ${validEnvironments.join(', ')} are available`);
        return false;
      }
      return true;
  }

  const triggerWorkflow = (bot,username,service,environment,branch) => {
    try {
      //これは、curlから実際のJavaScriptの投稿リクエストに変換された手動のワークフロートリガーコードです
      //Slackで@botusername deploy api staging to devというメッセージを送信し、以下に示すような応答が表示されます。
      const data = await axios.post(`https://api.github.com/repos/yourusername/yourreponame/dispatches`,{
        'event_type': 'deploy-service',
        'client_payload': {'environment': environment, 'ref': branch}
      },{headers:{
      Authorization: `token ${token}`,
      }})
    }
      catch(e) {
        bot.send(`Sorry @${username} could not trigger github action. Please check my logs ${e.message}`);
      }
  }

3. 最後に、Slackで@botusername deploy api staging to devというメッセージを送信すると、以下のような応答が表示されます。

ワークフローファイルは、特定のブランチにコードをプッシュしたり、タグを作成したり、プルリクエストを作成したり、URLをリクエストしたりするなど、さまざまなGitHubイベントでトリガーされることがあります。

send the @botusername deploy api staging to dev message in slack

結論

このチュートリアルを通じて、GitHubワークフローについて、Slackでの応答のコードを手動でトリガーする方法からチャットボットの構築まで学びました。また、Slackにチャットボットを持つことで、GitHubアクションのワークフローを呼び出してタスクを自動化できることも学びました。

この新しい知識をさらに高め、リマインダーボットを追加するか、インタラクティブメッセージを作成するなど、どうでしょうか?

Source:
https://adamtheautomator.com/create-slack-bot/