Skip to content

Commit f520ac9

Browse files
committed
添加通过 Webhook 自动同步文档功能
1 parent 4b247e1 commit f520ac9

File tree

9 files changed

+131
-18
lines changed

9 files changed

+131
-18
lines changed

Gopkg.lock

Lines changed: 0 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,18 @@ server {
272272
}
273273
```
274274

275-
## 后记
275+
## 配置 github 钩子
276276

277-
到这里就基本配置完成了,现在只是初步完成,还有部分功能未完善,根据实际的使用再慢慢完善,欢迎 star 支持下。
277+
`https://github.com/BroQiang/blog-docs` 项目中添加一个 Webhooks, 配置下面内容:
278+
279+
- Payload URL: `https://broqiang.com/webhook`
280+
281+
- Content type: 选择 `application/json`
282+
283+
- Secret: 自定义一个密钥,要和 `config.toml` 中的 secret 的值保持一直
284+
285+
钩子生效后, blog-docs 再 push 的时候 mdblog 就可以自动更新文档并显示了。
286+
287+
## 更新日志
288+
289+
### 2019-04-28 添加 github 钩子,自动同步 blog-docs 的文档

app/config/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ type Config struct {
5151

5252
// 百度统计 的 key
5353
Tongji string
54+
55+
// Github 钩子中配置的 Secret
56+
Secret string
5457
}
5558

5659
// Log 是日志相关的配置

app/http/controllers/public.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
package controllers
22

33
import (
4+
"crypto/hmac"
5+
"crypto/sha1"
6+
"encoding/hex"
47
"io/ioutil"
8+
"os/exec"
59
"path/filepath"
610
"strings"
711

12+
"github.com/broqiang/mdblog/app/mylog"
13+
814
"github.com/broqiang/mdblog/app/config"
915
"github.com/broqiang/mdblog/app/mdfile"
1016
"github.com/gin-gonic/gin"
@@ -67,3 +73,69 @@ func mergeH(c *gin.Context, h gin.H) gin.H {
6773
func ToKeywords(works ...string) string {
6874
return strings.Join(works, ",")
6975
}
76+
77+
// Webhook github 钩子
78+
func Webhook(c *gin.Context) {
79+
singn := c.GetHeader("X-Hub-Signature")
80+
body, err := ioutil.ReadAll(c.Request.Body)
81+
if err != nil {
82+
mylog.LogErr.Printf("github hook %v", err)
83+
return
84+
}
85+
86+
if !checkSecret(singn, body) {
87+
mylog.Error("github hook check secret failure.")
88+
return
89+
}
90+
91+
pullDocs()
92+
93+
// 从新初始化博客列表的内容
94+
mdfile.Model.Reload()
95+
}
96+
97+
// 向 github 发起 pull 请求,更新文档
98+
func pullDocs() {
99+
// 获取文档保存的路径
100+
docPath := filepath.Join(config.Root, config.Cfg.MarkdownDir)
101+
// 执行 git pull
102+
cmd := exec.Command("git", "pull")
103+
// 切换到命令要执行的目录
104+
cmd.Dir = docPath
105+
106+
// 执行,并返回结果
107+
res, err := cmd.Output()
108+
109+
if err == nil {
110+
mylog.Infof("git pull success. \n%s", res)
111+
} else {
112+
mylog.Errorf("git pull failure, %v", err)
113+
}
114+
115+
}
116+
117+
// 检测 github 传过来的 key
118+
func checkSecret(singn string, body []byte) bool {
119+
if len(singn) != 45 || !strings.HasPrefix(singn, "sha1=") {
120+
return false
121+
}
122+
123+
// github 中对应的加密串, 从配置文件去获取
124+
secret := []byte(config.Cfg.Secret)
125+
126+
// 通过加密串和 body 计算签名
127+
mac := hmac.New(sha1.New, secret)
128+
mac.Write(body)
129+
mKey := mac.Sum(nil)
130+
131+
// Hex 解码
132+
singnature := make([]byte, 20)
133+
hex.Decode(singnature, []byte(singn[5:]))
134+
135+
// 比较签名是否一直
136+
if hmac.Equal(singnature, mKey) {
137+
return true
138+
}
139+
140+
return false
141+
}

app/mdfile/list.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type List interface {
2424
ArticleByPath(string) (Article, error)
2525
ArticlesByCategory(string) Articles
2626
ArticlesByTag(string) Articles
27+
Reload()
2728
}
2829

2930
// Categories 是文章分类的切片(数组)

app/mdfile/listmap.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ type ListMap struct {
1313
Tags Tags
1414
}
1515

16+
// Reload 重新加载文档
17+
func (list *ListMap) Reload() {
18+
Model = new()
19+
}
20+
1621
// CategoriesAll 获取所有的分类列表
1722
func (list *ListMap) CategoriesAll() Categories {
1823

app/mylog/logger.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package mylog
22

33
import (
4+
"fmt"
45
"log"
56
"os"
67
"path"
@@ -153,3 +154,23 @@ func (lw *LogWriter) newFile() *os.File {
153154

154155
return file
155156
}
157+
158+
// Info 打印 info 信息
159+
func Info(vals ...interface{}) {
160+
LogInfo.Output(2, fmt.Sprintln(vals...))
161+
}
162+
163+
// Infof 指定格式的 info 日志
164+
func Infof(format string, vals ...interface{}) {
165+
LogInfo.Output(2, fmt.Sprintf(format, vals...))
166+
}
167+
168+
// Error 错误日志
169+
func Error(vals ...interface{}) {
170+
LogErr.Output(2, fmt.Sprintln(vals...))
171+
}
172+
173+
// Errorf 指定格式的错误日志
174+
func Errorf(format string, vals ...interface{}) {
175+
LogErr.Output(2, fmt.Sprintf(format, vals...))
176+
}

app/routes/web.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,23 @@ import (
99
// New 初始化路由
1010
func New(e *gin.Engine) {
1111
// 注册全局的中间件
12-
e.Use(gin.Logger(), midderware.Recovery, midderware.Sites, midderware.Navigation)
12+
e.Use(gin.Logger(), midderware.Recovery)
1313

14-
// 出现错误的页面
15-
e.GET("/errors", midderware.Errors)
16-
17-
// 404 页面
18-
e.NoRoute(midderware.NotFound)
14+
e.POST("/webhook", controllers.Webhook)
1915

2016
// 前台页面组,添加右侧标签的中间件
21-
front := e.Group("/", midderware.Tags)
17+
front := e.Group("/", midderware.Sites, midderware.Navigation, midderware.Tags)
2218
{
19+
// 出现错误的页面
20+
e.GET("/errors", midderware.Errors)
21+
22+
// 404 页面
23+
e.NoRoute(midderware.NotFound)
24+
25+
// 首页
2326
front.GET("/", controllers.Home)
27+
// about 页
28+
2429
front.GET("/about", controllers.About)
2530

2631
// 博客文章详情

config/config.example.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ icp = "需要填入你自己的备案号"
2525
# 百度统计的 key ,如果不使用的话,不配置或使用空字符串即可
2626
tongji = ""
2727

28+
# github 钩子中配置的 Secret, 要和钩子的配置保持一致
29+
secret = "broqiang.com"
30+
2831
# 日志相关的配置
2932
[log]
3033
# 日志保存位置,默认是应用根目录下生成日志文件

0 commit comments

Comments
 (0)