通过Hubot完美创建Slack机器人以调用GitHub Actions

如果您使用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会创建一个标准的 Node.JS 项目,其中包含package.json文件,该文件包含有关项目和任何依赖NPM 包的各种信息。

npm init      # 初始化 package.json 文件

4. 现在,创建一个workflows目录和deploy.yml 工作流文件。工作流文件是 GitHub Actions 将遵循的一系列按顺序定义的步骤。

mkdir .github/workflows && touch deploy.yml

5. 接下来,定义工作流程将读取的每个GitHub secrets。您即将创建的工作流程将引用这些机密信息。由于您需要服务器地址、用户名、密码和服务器的SSH端口,让我们创建GitHub secrets。

访问此网址https://github.com/yourusername/yourrepository/settings/secrets/actions,您将在这里添加GitHub secrets。将yourusername替换为您的GitHub用户名,将yourrepository替换为您的GitHub存储库。

单击新存储库机密按钮,如下所示,填写有关您正在添加的机密的信息。

Adding GitHub Secrets

6. 现在填写机密的名称和值字段,然后单击“添加机密”以保存。页面将重定向到GitHub secrets页面,您将看到所有机密。要添加更多机密,点击“新存储库机密”按钮,就像您之前所做的那样。

确保您为给定变量保存机密,名称与您将引用的相同变量名称相同,这些变量是HOST、USERNAME、PASSWORD和PORT。

Filling up Information for a GitHub Secret
Viewing All GitHub Secrets

7. 最后,打开〜/Hubot/.github/workflows/deploy.yml工作流程文件,将以下代码复制/粘贴到您的代码编辑器中。下面的代码是工作流程,将在稍后通过Slack触发工作流程时运行。

当您调用工作流程时,将发生一系列操作:

  • GitHub Actions将解析以下工作流文件以SSH登录到定义在HOST秘密中的目标host,并使用在USERNAMEPASSWORD中定义的凭据。
  • 然后,该工作流将通过运行git pull origin$branchName来下载特定分支($branchName)的GitHub存储库内容。请确保分支名称包含您想要部署的代码。
  • 您将使用来自Github MarketplaceWorkflow Package,名称为ssh-remote-commands。该软件包具有一个很好的封装器,可以解决您只需提供主机、用户名、密码、端口和要在生产环境中运行的命令的情况。

确保您的服务器已安装git,并具有从GitHub存储库拉取代码所需的登录凭据

# 通过编程方式引用的名称 
name: deploy 
on:
  # 事件存储库触发的含义是在每次 API 触发时 
  # 执行整个文件
  repository_dispatch: 
    types: [deploy-service]
# 可以有多个作业,但目前 
# 本教程仅在一个作业上运行
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 secrets 中的服务器主机
        host: ${{ secrets.HOST }} 
        # 登录的服务器用户名 
        # 存储在 github secrets 中的用户名
        username: ${{ secrets.USERNAME }} 
        # 登录的服务器密码 
        # 存储在 github secrets 中的密码 
        password: ${{ secrets.PASSWORD }} 
        # 登录的服务器端口 
        # 存储在 github secrets 中的端口
        port: ${{ secrets.PORT }}  
        # deploy-app.sh 可以是任何东西,比如可以从 GitHub 拉取代码
        # 并重新启动您的 web 服务器或队列等
        # 确保您在服务器上克隆了存储库 
        # 您可以运行任意数量的脚本
        script: git pull origin {{ github.event.client_payload.branch 

执行手动工作流程

您现在已经创建了通过Slack调用的GitHub Actions工作流程。但是此时,您的代码仅在本地机器上。要触发工作流程,您需要将代码推送到GitHub。

运行下面一系列命令告诉git代码应该从哪里推送和拉取,在这个例子中,是从您的远程GitHub仓库。在下面的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请求,告诉GitHub触发您之前创建的Workflow文件deploy.yml。将username替换为您的GitHub用户名,将repository替换为您的GitHub存储库。

在下面的代码中,用您的个人令牌替换$github_personal_token

# 在 https://github.com/username/repository/dispatches URL 处进行 POST 请求 
curl-X POST  https://github.com/username/repository/dispatches \
# 添加接受内容类型的头部
-H 'Accept: application/vnd.github.everest-preview+json' \
# 添加授权的头部
-H "Authorization: token $github_personal_token" \
# 在 POST 请求的主体中添加 JSON 内容,以便您可以发送多个参数 
# 从此数据部分,并且您可以根据参数执行各种操作
--data '{"event_type": "deploy-service", "client_payload": {"environment": "'"$1"'", "ref": "'"$2"'"}}' # 您可以将环境名称和 ref 作为分支名称传递,以便您知道要在哪个服务器上部署哪个分支

使用 Hubot 创建 Slack 机器人

由于您能够手动触发 GitHub Action 工作流程,这是一个良好的开始。现在让我们尝试通过 Slack 机器人自动执行相同的手动步骤。您将创建一个 Slack 机器人,它会侦听您的命令并使用参数触发 GitHub Action。

创建 Slack 机器人有两种选择,可以从头开始创建,也可以使用预先构建的适用于 Slack 工作区的 Hubot 包。在本教程中,您将使用一个名为 Hubot 的预构建的机器人包。Hubot 是一个开源的自动化工具,与 Slack、Discord、Gitter、TeamSpeak 等聊天服务集成。

创建一个自定义机器人而不使用像Hubot这样的应用程序需要很长时间。为什么?因为你将处理所有设置过程,监听webhooks,并托管机器人。因此,在本教程中,您将使用Hubot Slack应用程序来简化所有这些过程。

使用Npm安装Hubot

由于您正在使用Hubot创建Slack机器人,让我们首先在本地计算机上下载并安装Hubot。Hubot将是连接Slack和GitHub操作的连接器。

1. 在终端中导航(cd)到项目目录(〜/Hubot)。

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

将Hubot添加到您的Slack工作区

现在Hubot已经安装在您的本地机器上,您需要配置Hubot与Slack通信。

让我们在您的Slack工作区中安装Hubot。

1. 打开您的网络浏览器,使用URL导航到您的Slack管理员设置,例如 https://workspacename.slack.com/admin/settings。 用您实际的Slack工作区名称替换workspacename

点击左侧面板上的配置应用,如下图所示,这样您就可以在市场中搜索Hubot。Slack有一个市场,您可以在其中找到预构建的应用程序。

Accessing Slack Admin Settings

2. 点击搜索栏,然后键入hubot以在市场中搜索Hubot并选择Hubot

现在,点击下面所示的添加到Slack按钮,将Hubot添加到您的Slack工作区。

Searching Hubot and Adding it to Slack Workspace

3. 最后,填写有关您的Bot的一些常规信息,例如名称(deployerhubot)和图标。请注意API令牌,您稍后将在Hubot Deployer中使用它来激活您之前创建的Hubot项目中的Bot。

Setting up Bot Information and Taking Note of the API Token

测试GitHub Actions Workflow与Slack集成

现在您已经在Slack Workspace上安装了Hubot,让我们通过监听和发送消息到频道来测试机器人。但首先,您必须激活机器人。

1. 在项目的根目录中运行以下命令以激活Slack的Bot(--adapter slack),来自您Hubot repo的(./bin/hubot)。确保用您之前记下的API令牌替换$token

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

2. 运行以下命令邀请(/invite)Bot(botusername)到您的Slack频道。将botusername替换为您在“将Hubot添加到您的Slack Workspace”部分的第三步中注册的Bot的名称。

/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 Actions工作流

现在您已经激活了Slack Bot,是时候从Slack启动GitHub Actions工作流了!

您需要灵活性,可以将给定分支部署到给定服务器,例如从给定分支拉取代码。当有人在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 POST请求
      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将api部署到开发环境消息,您将看到类似的响应,如下所示。

工作流文件可以根据各种GitHub事件触发,例如推送代码到特定分支,创建标签,创建拉取请求,请求某些URL等等。

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

结论

在本教程中,您已经了解了GitHub工作流,从使用代码手动触发Slack响应到构建聊天机器人。您还了解到,在Slack中拥有聊天机器人可以通过调用GitHub操作工作流来自动执行任务。

您会进一步提升这些新知识吗?也许添加一个提醒机器人或者制作交互式消息

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