我用 极狐 Gitlab 议题 来点菜
虽然我是一个程序员,但是我一直想开一个餐厅。希望开一个极客范儿的餐厅,大家通过 issue 来点菜。受到推特上一位大佬 Andrew Schmelyun 的影响,我在 Gitlab 上实现了该功能。
话不多说,先看看效果。
B站地址
接下来,我来介绍下是怎么实现的。
硬件列表
我这里是惠普的普通办公打印机,换成那种打印小票的热敏打印机效果更好。纸张更小,可以夹在后厨。

我这里是用 Mac 直接连接添加的网络打印机,可以通过 lp filename
直接打印文件。

发送数据给打印机
作为一个 Go 的开发者,很容易就想到用 Gin 框架起一个 http 服务。用来接受 客户的菜单请求。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
func main() {
router := gin.New()
// post请求
router.POST("/postReq", func(ctx *gin.Context) {
var req GitlabIssue
err := ctx.ShouldBindJSON(&req) // 解析req参数
if err != nil {
fmt.Println("ctx.ShouldBindJSON err: ", err)
return
}
rspMap := map[string]interface{}{ // 也可用结构体方式返回
"code": 0,
"rsp": fmt.Sprintf("welcome %v!", req.User.Name),
}
ctx.JSON(http.StatusOK, rspMap)
fmt.Printf("rsp: %+v\n", rspMap)
writeMemu(req.ObjectAttributes.Title+"\n"+req.ObjectAttributes.Description)
cmdShell()
})
router.Run(":8080") // 8080端口,底层调用的是net/http包,也是单独启协程进行监听
return
}
|
打印菜单命令,菜单保存在 memu.txt
文件中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
func cmdShell() {
cmd := exec.Command("lp","memu.txt")
stdout, err := cmd.Output()
if err != nil {
fmt.Println("error======",err.Error())
return
}
// Print the output
fmt.Println(string(stdout))
}
func writeMemu(memu string) {
f, err := os.Create("memu.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
_, err2 := f.WriteString(memu)
if err2 != nil {
log.Fatal(err2)
}
fmt.Println("done")
}
|
其中 GitlabIssue 结构体的构造可以参考 Gitlab 文档上关于 Webhook 事件的例子,来构造 议题 请求的结构体。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
type GitlabIssue struct {
ObjectKind string `json:"object_kind"`
EventType string `json:"event_type"`
User struct {
ID int `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
AvatarURL string `json:"avatar_url"`
Email string `json:"email"`
} `json:"user"`
ObjectAttributes struct {
ID int `json:"id"`
Title string `json:"title"`
AssigneeIds []int `json:"assignee_ids"`
AssigneeID int `json:"assignee_id"`
|
关于 json 怎么转结构体,可以参考该连接
go run main.go
服务就在本地的 8080 端口起来了。

链接 Gitlab
部署docker版本的 Gitlab
1
|
sudo docker run --detach --hostname gitlab.example.com --publish 8929:8929 --publish 2289:22 --name gitlab --restart always --volume $GITLAB_HOME/config:/etc/gitlab --volume $GITLAB_HOME/logs:/var/log/gitlab --volume $GITLAB_HOME/data:/var/opt/gitlab --shm-size 256m registry.gitlab.cn/omnibus/gitlab-jh:latest
|
添加 Webhooks
这个时候,发送一个 curl 请求,就可以调试打印了。但是想要从 Gitlab 议题触发,就要用到 Gitlab 的 Webhooks 。Gitlab Webhooks 使用起来也很方便。进入 设置—Webhooks,输入要请求的 URL 和出发事件。

需要允许对本地网络的请求
由于本地网络上运行非 GitLab Web 服务,则这些服务可能容易受到 Webhook 的利用。所以要允许对本地网络的请求。
- 在顶部栏上,选择 菜单 > 管理员。
- 在左侧边栏中,选择 设置 > 网络。
- 展开 出站请求 部分:

- 选择 允许来自 web hooks 和服务对本地网络的请求。
添加本地请求的许可名单
- 在顶部栏上,选择 菜单 > 管理员。
- 在左侧边栏中,选择 设置 > 网络 (
/admin/application_settings/network
) ,输入以下内容,允许本地服务
1
2
3
4
|
127.0.0.1,1:0:0:0:0:0:0:1
127.0.0.0/8 1:0:0:0:0:0:0:0/124
[1:0:0:0:0:0:0:1]:8080
127.0.0.1:8080
|
具体设置可以参考官网文档
更多 Webhooks 用法可以参考链接
内网穿透
由于服务是本地的,需要顾客点菜,所以需要其他人可以访问该网络,最简单做法就是使用 ngrok

Webhooks
网址就填写:https://e9b1-61-164-43-2.jp.ngrok.io/postReq
完整代码
完整代码已经放在了 极狐 Gitlab上了
源码地址:https://jihulab.com/zyg/Restaurant/-/tree/dev-zyg
后期规划
- 新增二维码点餐,可以扫描二维码进入 Gitlab issue 界面,填写 issue 点菜。
- 硬件小型化,打印机打算去咸鱼淘一个热敏打印机,打印纸也比较小。服务打算部署在树莓派上。
参考链接
https://aschmelyun.com/blog/i-built-a-receipt-printer-for-github-issues/
https://docs.gitlab.cn/jh/user/project/integrations/webhooks.html#configure-a-webhook-in-gitlab