golang懒人开发者必备的Slack机器人插件slack-bot支持自定义命令和集成Jenkins/Jira/Bitbucket/Github
Golang懒人开发者必备的Slack机器人插件slack-bot
这个Slack机器人可以显著提升开发团队的工作效率,特别针对Jenkins、GitHub、GitLab和Jira的集成提供了开箱即用的支持。同时也支持自定义命令、宏、定时任务等项目特定功能的灵活实现。
安装指南
1. 创建并准备Slack应用
使用Manifest文件作为应用模板:
- 创建一个Slack应用(点击"Create New App")
- 选择"From an app manifest"
- 选择你的工作区
- 粘贴以下Yaml代码:
_metadata:
major_version: 1
minor_version: 1
display_information:
name: slack_bot
background_color: "#382e38"
features:
app_home:
messages_tab_enabled: true
messages_tab_read_only_enabled: false
bot_user:
display_name: bot
always_online: true
oauth_config:
scopes:
bot:
- app_mentions:read
- channels:read
- channels:history
- groups:history
- chat:write
- im:history
- im:write
- mpim:history
- reactions:read
- reactions:write
- users:read
- files:read
- pins:write
settings:
event_subscriptions:
bot_events:
- app_mention
- message.im
interactivity:
is_enabled: true
org_deploy_enabled: false
socket_mode_enabled: true
token_rotation_enabled: false
- 创建应用!
- “Basic information” → “Display Information” → 上传图片(512px+) + 设置合适的名称
- “App Home” → “Show Tabs” → 勾选"Allow users to send Slash commands and messages from the messages tab"
- “Basic Information” → “App-Level Tokens” → “Generate Token and scopes” → 使用"bot token"作为token名称,"connections:write"作为scope
- 你会看到一个以xapp-开头的App-Level Token。将其设置为config.yaml中的"slack.socket_token"
- Basic Information → “Request to install” + "Install to Workspace"继续安装
- 然后你会得到另一个token(在"Install App"标签页显示),以"xoxb-"开头。将其作为"slack.token"用在config.yaml中
- 在你的Slack客户端中,你可以在任何频道添加机器人或开始私聊
2. 准备配置
首先准备config.yaml
,可以参考config-example.yaml:
- 至少需要Slack token和socket-token
3. 运行机器人
选项1:通过go运行
- 安装go(至少1.22)
- 创建config.yaml(至少需要Slack token和socket-token)或参考config-example.yaml
go run github.com/innogames/slack-bot/v2/cmd/bot
选项2:通过Docker
- 安装Docker包括docker-compose
- 克隆此仓库或至少获取docker-compose.yaml
- 在config.yaml的"allowed_users:"部分添加你的Slack用户ID或用户名
docker-compose up
选项3:高级:计划在机器人核心上工作时
- 安装go
- 克隆/分叉此仓库
- 运行
go run cmd/bot/main.go
或make run
来运行go应用
使用方式
作为Slack用户,你只需要向机器人用户/应用发送包含要执行命令的私信。此外,你可以将机器人添加到任何频道,并通过在命令前加上@bot_name来执行机器人命令,例如@slack-bot start job DailyDeployment
注意: 你必须邀请机器人进入频道才能处理命令。
机器人命令
帮助
help
命令会打印此机器人所有可用命令的列表。使用help *command*
你可以获得单个命令的简短描述和一些示例。
Jenkins
机器人能够以简单但强大的方式启动和监控Jenkins作业。
默认情况下,在配置文件中定义"jenkins.host"之前,命令不可用且不会显示在"help"中。
启动Jenkins作业
start job
命令启动一个Jenkins作业并显示当前进度。注意: 只有配置中白名单的作业可以启动!
此外,每个作业可以有一个可配置的trigger
,这使得可以创建自定义命令来启动作业。(它是一个考虑参数名的正则表达式)
例如,"start daily deployment"可以是一个Jenkins作业的触发器。向机器人发送此文本将启动该作业。
启动作业后,机器人将显示预计的构建时间和一些操作按钮。在那里你可以直接打开日志或中止构建。
机器人还能够解析参数并使用模糊分支搜索查找分支名称。
示例:
trigger job DeployBeta
start job BackendTests TEST-123
(搜索包含TEST-123的完整分支名称,例如feature/TEST-123-added-feature-456)
Jenkins构建通知
机器人还可以为Jenkins构建创建一次性通知。这对于长时间运行的作业,开发人员正在等待结果时可能很有用。
示例:
inform me about build NightlyTests
(监视最近运行的构建)inform me about build MyJobName #423
(指定构建号)inform job MyJobName
(替代语法)
Jenkins作业通知
接收给定作业所有处理构建的Slack消息:
示例:
watch JenkinsSelfCheck
通知关于JobJenkinsSelfCheck
的任何构建unwatch JenkinsSelfCheck
Jenkins状态
禁用/启用Jenkins端作业执行的小命令。
示例:
disable job NightlyTests
(在Jenkins上禁用作业)enable job NightlyTests
Jenkins重试
当构建失败时,你可以通过以下方式重试任何构建:
示例:
retry build NightlyTests
(重试作业的最后一次构建)retry build NightlyTests #100
(重试给定的构建)
节点
jenkins nodes
列出所有可用的Jenkins节点。可以看到在线/离线状态和执行器数量。
拉取请求
如果你只是粘贴GitHub/GitLab/Bitbucket/Stash拉取请求的链接,机器人将跟踪票证的状态!
- 当开发者被添加为审查者时,它将添加一个"eyes"反应,向其他开发者显示已经有人在查看
- 当审查者批准票证时,会添加一个勾选标记
- 合并拉取请求后,它将添加一个"merge"反应
你也可以设置自定义的"approved"反应。例如,要直接查看谁或哪个组件/部门批准了拉取请求,你可以使用反应名称或直接使用Unicode字符
示例配置:
pullrequest:
reactions:
merged: custom_merge_arrow
review: 👀
custom_approve_reaction:
nerdydev: "approved_backend"
iamamobiledev: "approved_mobile"
iamamobiledev2: "approved_mobile"
额外功能: 对于Bitbucket,机器人能够提取当前构建状态(例如来自Jenkins/Bamboo等),并显示失败和正在运行的构建(火反应)作为反应(圆圈箭头反应)。当构建稳定时,构建反应会消失。
命令队列
queue
命令(别名为then
)能够将给定命令排队,直到当前运行的命令完成。
示例场景: 你有一个构建作业(可能需要几分钟)和一个依赖于构建产物的部署作业。现在你可以:
trigger job Build feature1234
用给定分支启动构建作业queue trigger job DeployBranch feature1234
queue reply Deployment is done!
其他示例:
delay 1h
then send message #backend coffee time?
要查看所有正在运行的背景命令(如Jenkins作业或PR监视器),使用此命令:
list queue
Jira
机器人能够从Jira查询信息,无论是单个票证还是一整个票证列表。
默认情况下,在配置文件中定义"jira.host"之前,命令不可用且不会显示在"help"中。
示例
jira TEST-1234
jira 1242
(打开票证,使用配置的默认jira项目)jql type=bug and status=open
(默认使用默认项目)jira "Second city"
(在默认项目中搜索票证的文本)
也可以在有状态更改的特定Jira票证时获取通知。
示例
watch ticket PROJ-12234
交互
可以创建按钮,在按下按钮时执行任何机器人操作。Slack交互
示例:
add button "Start Deployment" "trigger job LiveDeployment"
注意
- 只有白名单用户可以点击按钮
- 每个按钮只激活一次
自定义变量
配置用户特定变量以自定义机器人行为。例如,每个开发者都有自己的服务器环境。
示例: 使用此全局配置:
commands:
- name: Deploy
trigger: "deploy (?P<branch>.*)"
commands:
- deploy {{.branch}} to {{ customVariable "defaultServer" }}
每个开发者现在可以调用一次这样的命令:set variable defaultSerer foobarX.local
来注册自定义的"defaultServer"。
当现在调用deploy mater
时,它将把master
分支部署到foobarX.local
服务器。
另一个示例
这是一个使用Go模板的高级版本。
最终,命令将生成一个子命令,如:
reply <!here> demo for <https://jira.example.com/TEST-1234|TEST-1234: Example-Ticket>
这将发布链接到Slack频道。
- name: demo
trigger: "demo (?P<ticketId>\\w+-\\d+)"
commands:
- |
{{ $ticket := jiraTicket .ticketId }}
{{ if $ticket }}
reply <!here> demo for <{{ jiraTicketUrl $ticket.Key }}|{{ $ticket.Key }}: {{ $ticket.Fields.Summary }}>
{{ else }}
reply Ticket {{ .ticketId }} not found :white_frowning_face:
{{ end }}
description: Informs the current channel about a demo of a Jira ticket. It directly posts a link to the ticket
examples:
- demo XYZ-1232
用户可以定义他的默认环境一次,使用set variable serverEnvironment aws-02
。
然后deploy feature-123
将把分支部署到定义的aws-02
环境。
每个用户可以定义自己的变量。
Openai/ChatGPT/Dall-e集成
也可以使用官方OpenAI集成(GPT3.5)进行类似ChatGPT的对话!
只需在你的问题前输入"openai"或"chatgpt"以创建一个新线程,其行为类似于众所周知的ChatGPT页面。最后10条消息的内容被用作上下文。 要使其工作,必须在配置中提供有效的"openai.api_key"。
扩展配置:
openai:
api_key: "sk-123....789"
initial_system_message: "You are a Slack bot for Project XYZ, please answer shortly."
update_interval: '3s' # fewer Slack messages update during generation
model: gpt-3.5-turbo
temperature: 0.8
log_texts: true # opt in: log all input/output text to the log
当在现有线程中使用"openai XXX"命令时,先前的消息被用作进一步调用的上下文。
也可以在模板中使用该功能(如在自定义命令或定时任务中)。
{{ openai "Say some short welcome words to @Jon_Doe"}}
会打印类似 Hello Jon, welcome! How can I assist you today?
的内容
DALL-E集成
机器人还能够借助DALL-E生成图像。 只需在你的提示前加上"dalle",机器人就会根据你的文本生成图像。
测验命令
如果你需要小憩并想玩个小测验游戏,你可以通过调用此命令来实现。 不允许超过50个问题。 问题来自不同类别和难度级别,可以是多项选择或真/假问题。
命令
quiz 10
开始一个有10个问题的测验answer 1
用第一个答案回答问题
天气命令
可以设置OpenWeatherMap来获取当前位置的当前天气信息。
示例配置:
open_weather:
apikey: "612325WD623562376678"
location: "Hamburg, DE"
units: "metric"
自定义命令
每个用户都能够定义自己的命令别名。 这是一个方便的功能,可以避免每天输入相同的命令。
示例用法
list commands
只列出当前用户定义的命令add command 'myCommand' 'trigger job RestoreWorld 7
-> 然后稍后只需调用myCommand
add command 'build master' 'trigger job Deploy master ; then trigger job DeployClient master'
delete command 'build master'
- -> 然后你可以执行
myCommand
来触发这个Jenkins作业
命令
定义的"Commands"(以前称为"Macros")非常神奇,可以在yaml配置文件中定义。
它们有一个触发器(一个正则表达式)和一个将被执行的子命令列表。 它们考虑来自正则表达式的参数组 - 所以它们可以非常灵活!
一个简单的示例,用给定的分支名称同时启动两个Jenkins作业:
commands:
- name: build clients
trigger: "build clients (?P<branch>.*)"
commands:
- "reply I'll build {{ .branch }} for you"
- "trigger job BuildFrontendClient {{ .branch }}"
- "trigger job BuildMobileClient {{ .branch }}"
- "then reply done! :checkmark:"
注意: 在命令中,你可以使用go模板功能的完整集合 -> 循环/条件是可能的!
模板函数
除了通常的go模板功能外,模板范围内还提供了一堆机器人特定命令。
所有可用函数(带有参数和返回类型)的列表可以通过使用list template functions
命令生成。
注意: 这些模板函数可以在不同的命令/功能中使用:
重试
使用retry
或repeat
将重新执行你最后执行的命令。-> 当失败的Jenkins作业被修复时很有用。
延迟
一个小命令,可能与command
命令结合使用或作为Jenkins作业的钩子很有用。
示例命令:delay 10m trigger job DeployWorldwide
作为回复,你将获得一个命令来停止排队的作业(如stop timer 123456
)。因为每个人都可以发送命令,该命令可以用于宣布部署,在怀疑时,执行仍然可以被任何人停止。
回复/发送消息
reply
和send message
也是小命令,与command
或Jenkins钩子结合使用时很有用。
示例:
send message to #backend The job failed :panic:
delay 10m send message to @peter_pan I should notify you to...
随机
如果你无法在不同选项之间做出决定,这是一个简单的命令
示例
random Pizza Pasta
-> 产生"Pizza"或"Pasta"random Peter Paul Tom Jan
-> 今天谁必须负责组织食物?
配置
配置通过简单的.yaml文件管理,这些文件存储外部服务的凭据和自定义命令等。
最简单的方法是只有一个包含所有需要选项的config.yaml
文件,默认加载config.yaml
。也可以将配置拆分为多个文件。
具有多个配置文件的示例结构:
secret.yaml
包含外部服务(Slack,Jenkins)的凭据 - 可以通过puppet/ansible等管理jenkins.yaml
Jenkins作业及其参数等的配置project-X.yaml
特定团队的自定义命令project-Y.yaml
要加载多个配置文件,使用go run cmd/bot/main.go -config /path/to/config/*.yaml
,它会合并所有配置。
Slack
要运行此机器人,你需要一个Slack应用程序的"bot token"。有关如何创建具有所需令牌的适当应用程序,请参阅安装部分。
Jenkins配置
要能够启动或监视Jenkins作业,你必须首先设置主机和凭据。用户需要对作业具有读取权限,并且有权触发白名单中的作业。
jenkins:
host: https://jenkins.example.de
username: jenkinsuser
password: secret
Jenkins作业
要能够启动作业,必须在配置中定义作业及其参数。
没有参数的作业看起来非常简单:
jenkins:
jobs:
CleanupJob:
然后你可以使用trigger job CleanupJob
或start job CleanupJob
来启动作业。它还会在作业成功或失败时通知你(包括错误日志)。
接下来,一个有两个参数的作业:
jenkins:
jobs:
RunTests:
parameters:
- name: BRANCH
default: master
type: branch
- name: GROUP
default: all
此作业可以处理两个参数:
- BRANCH: VCS分支名称,"master"作为默认值
- GROUP: 可选参数,使用"all"作为默认值
如果你在配置中设置了VCS,你不必传递完整的分支名称,而是可以使用模糊搜索。
示例:
start job RunTests
将在master分支上启动"all"组start job JIRA-1224 unit
将尝试为票号找到匹配的分支。(如果没有唯一的搜索结果,则显示错误消息!)
现在是一个更复杂的例子,
更多关于golang懒人开发者必备的Slack机器人插件slack-bot支持自定义命令和集成Jenkins/Jira/Bitbucket/Github的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang懒人开发者必备的Slack机器人插件slack-bot支持自定义命令和集成Jenkins/Jira/Bitbucket/Github的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang Slack机器人插件slack-bot开发指南
作为IT专家,我将介绍如何使用Golang开发一个功能强大的Slack机器人插件,支持自定义命令和集成Jenkins、Jira、Bitbucket、Github等常用开发工具。
核心功能概述
这个slack-bot插件将提供以下功能:
- 自定义命令处理
- 与CI/CD工具(Jenkins)集成
- 项目管理(Jira)集成
- 代码仓库(Bitbucket/Github)集成
- 交互式消息响应
基础架构
package main
import (
"log"
"os"
"github.com/slack-go/slack"
"github.com/slack-go/slack/slackevents"
"github.com/slack-go/slack/socketmode"
)
type Bot struct {
api *slack.Client
client *socketmode.Client
handlers map[string]CommandHandler
}
type CommandHandler func(evt *slackevents.AppMentionEvent) error
func NewBot(token, appToken string) *Bot {
api := slack.New(
token,
slack.OptionAppLevelToken(appToken),
)
client := socketmode.New(api)
return &Bot{
api: api,
client: client,
handlers: make(map[string]CommandHandler),
}
}
func (b *Bot) RegisterCommand(command string, handler CommandHandler) {
b.handlers[command] = handler
}
func (b *Bot) Start() {
go func() {
for evt := range b.client.Events {
switch evt.Type {
case socketmode.EventTypeEventsAPI:
eventsAPIEvent, ok := evt.Data.(slackevents.EventsAPIEvent)
if !ok {
continue
}
b.client.Ack(*evt.Request)
switch eventsAPIEvent.Type {
case slackevents.CallbackEvent:
innerEvent := eventsAPIEvent.InnerEvent
switch ev := innerEvent.Data.(type) {
case *slackevents.AppMentionEvent:
b.handleMention(ev)
}
}
}
}
}()
b.client.Run()
}
func (b *Bot) handleMention(evt *slackevents.AppMentionEvent) {
// 解析命令并调用对应的handler
// ...
}
自定义命令实现
func main() {
bot := NewBot(os.Getenv("SLACK_BOT_TOKEN"), os.Getenv("SLACK_APP_TOKEN"))
// 注册自定义命令
bot.RegisterCommand("hello", func(evt *slackevents.AppMentionEvent) error {
_, _, err := bot.api.PostMessage(evt.Channel, slack.MsgOptionText("Hello there!", false))
return err
})
bot.RegisterCommand("help", func(evt *slackevents.AppMentionEvent) error {
helpText := "Available commands:\n" +
"- `hello`: Greet the bot\n" +
"- `help`: Show this help message\n" +
"- `jira <issue-id>`: Get Jira issue details\n" +
"- `jenkins <job-name>`: Trigger Jenkins job"
_, _, err := bot.api.PostMessage(evt.Channel, slack.MsgOptionText(helpText, false))
return err
})
bot.Start()
}
集成Jenkins
import (
"github.com/bndr/gojenkins"
)
type JenkinsClient struct {
client *gojenkins.Jenkins
}
func NewJenkinsClient(url, user, token string) *JenkinsClient {
jenkins := gojenkins.CreateJenkins(nil, url, user, token)
_, err := jenkins.Init()
if err != nil {
log.Fatal(err)
}
return &JenkinsClient{client: jenkins}
}
func (j *JenkinsClient) TriggerJob(jobName string, params map[string]string) (int64, error) {
queueID, err := j.client.BuildJob(jobName, params)
if err != nil {
return 0, err
}
return queueID, nil
}
// 注册Jenkins命令
bot.RegisterCommand("jenkins", func(evt *slackevents.AppMentionEvent) error {
// 解析参数
args := strings.Fields(evt.Text)
if len(args) < 2 {
return errors.New("Usage: jenkins <job-name>")
}
jobName := args[1]
jenkins := NewJenkinsClient(
os.Getenv("JENKINS_URL"),
os.Getenv("JENKINS_USER"),
os.Getenv("JENKINS_TOKEN"),
)
queueID, err := jenkins.TriggerJob(jobName, nil)
if err != nil {
_, _, postErr := bot.api.PostMessage(evt.Channel,
slack.MsgOptionText(fmt.Sprintf("Failed to trigger job: %v", err), false))
return postErr
}
_, _, postErr := bot.api.PostMessage(evt.Channel,
slack.MsgOptionText(fmt.Sprintf("Job triggered! Queue ID: %d", queueID), false))
return postErr
})
集成Jira
import (
"github.com/andygrunwald/go-jira"
)
type JiraClient struct {
client *jira.Client
}
func NewJiraClient(url, user, token string) *JiraClient {
tp := jira.BasicAuthTransport{
Username: user,
Password: token,
}
client, err := jira.NewClient(tp.Client(), url)
if err != nil {
log.Fatal(err)
}
return &JiraClient{client: client}
}
func (j *JiraClient) GetIssue(issueID string) (*jira.Issue, error) {
issue, _, err := j.client.Issue.Get(issueID, nil)
return issue, err
}
// 注册Jira命令
bot.RegisterCommand("jira", func(evt *slackevents.AppMentionEvent) error {
args := strings.Fields(evt.Text)
if len(args) < 2 {
return errors.New("Usage: jira <issue-id>")
}
issueID := args[1]
jira := NewJiraClient(
os.Getenv("JIRA_URL"),
os.Getenv("JIRA_USER"),
os.Getenv("JIRA_TOKEN"),
)
issue, err := jira.GetIssue(issueID)
if err != nil {
_, _, postErr := bot.api.PostMessage(evt.Channel,
slack.MsgOptionText(fmt.Sprintf("Failed to get issue: %v", err), false))
return postErr
}
// 创建更丰富的消息格式
attachment := slack.Attachment{
Title: fmt.Sprintf("%s: %s", issue.Key, issue.Fields.Summary),
TitleLink: fmt.Sprintf("%s/browse/%s", os.Getenv("JIRA_URL"), issue.Key),
Text: issue.Fields.Description,
Color: "#0052CC",
Fields: []slack.AttachmentField{
{
Title: "Status",
Value: issue.Fields.Status.Name,
Short: true,
},
{
Title: "Assignee",
Value: issue.Fields.Assignee.DisplayName,
Short: true,
},
},
}
_, _, postErr := bot.api.PostMessage(evt.Channel,
slack.MsgOptionAttachments(attachment))
return postErr
})
部署与配置
-
创建Slack应用并获取API令牌
-
设置环境变量:
SLACK_BOT_TOKEN=xoxb-your-bot-token SLACK_APP_TOKEN=xapp-your-app-token JENKINS_URL=https://your-jenkins.com JENKINS_USER=username JENKINS_TOKEN=api-token JIRA_URL=https://your-company.atlassian.net JIRA_USER=email@company.com JIRA_TOKEN=api-token
-
构建并运行:
go build -o slack-bot ./slack-bot
扩展建议
- 添加Bitbucket/Github集成:使用相应的Go SDK实现PR查询、代码审查等功能
- 实现交互式按钮:使用Slack的Block Kit创建更丰富的交互界面
- 添加权限控制:基于Slack用户角色限制命令访问
- 实现持久化:使用数据库存储常用查询或配置
这个slack-bot框架提供了高度可扩展的基础,开发者可以根据团队需求轻松添加更多集成和自定义命令。