Skip to content

Commit

Permalink
添加通过 Webhook 自动同步文档功能
Browse files Browse the repository at this point in the history
  • Loading branch information
broqiang committed Apr 27, 2019
1 parent 4b247e1 commit f520ac9
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 18 deletions.
9 changes: 0 additions & 9 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,18 @@ server {
}
```

## 后记
## 配置 github 钩子

到这里就基本配置完成了,现在只是初步完成,还有部分功能未完善,根据实际的使用再慢慢完善,欢迎 star 支持下。
`https://github.com/BroQiang/blog-docs` 项目中添加一个 Webhooks, 配置下面内容:

- Payload URL: `https://broqiang.com/webhook`

- Content type: 选择 `application/json`

- Secret: 自定义一个密钥,要和 `config.toml` 中的 secret 的值保持一直

钩子生效后, blog-docs 再 push 的时候 mdblog 就可以自动更新文档并显示了。

## 更新日志

### 2019-04-28 添加 github 钩子,自动同步 blog-docs 的文档
3 changes: 3 additions & 0 deletions app/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ type Config struct {

// 百度统计 的 key
Tongji string

// Github 钩子中配置的 Secret
Secret string
}

// Log 是日志相关的配置
Expand Down
72 changes: 72 additions & 0 deletions app/http/controllers/public.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package controllers

import (
"crypto/hmac"
"crypto/sha1"
"encoding/hex"
"io/ioutil"
"os/exec"
"path/filepath"
"strings"

"github.com/broqiang/mdblog/app/mylog"

"github.com/broqiang/mdblog/app/config"
"github.com/broqiang/mdblog/app/mdfile"
"github.com/gin-gonic/gin"
Expand Down Expand Up @@ -67,3 +73,69 @@ func mergeH(c *gin.Context, h gin.H) gin.H {
func ToKeywords(works ...string) string {
return strings.Join(works, ",")
}

// Webhook github 钩子
func Webhook(c *gin.Context) {
singn := c.GetHeader("X-Hub-Signature")
body, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
mylog.LogErr.Printf("github hook %v", err)
return
}

if !checkSecret(singn, body) {
mylog.Error("github hook check secret failure.")
return
}

pullDocs()

// 从新初始化博客列表的内容
mdfile.Model.Reload()
}

// 向 github 发起 pull 请求,更新文档
func pullDocs() {
// 获取文档保存的路径
docPath := filepath.Join(config.Root, config.Cfg.MarkdownDir)
// 执行 git pull
cmd := exec.Command("git", "pull")
// 切换到命令要执行的目录
cmd.Dir = docPath

// 执行,并返回结果
res, err := cmd.Output()

if err == nil {
mylog.Infof("git pull success. \n%s", res)
} else {
mylog.Errorf("git pull failure, %v", err)
}

}

// 检测 github 传过来的 key
func checkSecret(singn string, body []byte) bool {
if len(singn) != 45 || !strings.HasPrefix(singn, "sha1=") {
return false
}

// github 中对应的加密串, 从配置文件去获取
secret := []byte(config.Cfg.Secret)

// 通过加密串和 body 计算签名
mac := hmac.New(sha1.New, secret)
mac.Write(body)
mKey := mac.Sum(nil)

// Hex 解码
singnature := make([]byte, 20)
hex.Decode(singnature, []byte(singn[5:]))

// 比较签名是否一直
if hmac.Equal(singnature, mKey) {
return true
}

return false
}
1 change: 1 addition & 0 deletions app/mdfile/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type List interface {
ArticleByPath(string) (Article, error)
ArticlesByCategory(string) Articles
ArticlesByTag(string) Articles
Reload()
}

// Categories 是文章分类的切片(数组)
Expand Down
5 changes: 5 additions & 0 deletions app/mdfile/listmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ type ListMap struct {
Tags Tags
}

// Reload 重新加载文档
func (list *ListMap) Reload() {
Model = new()
}

// CategoriesAll 获取所有的分类列表
func (list *ListMap) CategoriesAll() Categories {

Expand Down
21 changes: 21 additions & 0 deletions app/mylog/logger.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mylog

import (
"fmt"
"log"
"os"
"path"
Expand Down Expand Up @@ -153,3 +154,23 @@ func (lw *LogWriter) newFile() *os.File {

return file
}

// Info 打印 info 信息
func Info(vals ...interface{}) {
LogInfo.Output(2, fmt.Sprintln(vals...))
}

// Infof 指定格式的 info 日志
func Infof(format string, vals ...interface{}) {
LogInfo.Output(2, fmt.Sprintf(format, vals...))
}

// Error 错误日志
func Error(vals ...interface{}) {
LogErr.Output(2, fmt.Sprintln(vals...))
}

// Errorf 指定格式的错误日志
func Errorf(format string, vals ...interface{}) {
LogErr.Output(2, fmt.Sprintf(format, vals...))
}
19 changes: 12 additions & 7 deletions app/routes/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,23 @@ import (
// New 初始化路由
func New(e *gin.Engine) {
// 注册全局的中间件
e.Use(gin.Logger(), midderware.Recovery, midderware.Sites, midderware.Navigation)
e.Use(gin.Logger(), midderware.Recovery)

// 出现错误的页面
e.GET("/errors", midderware.Errors)

// 404 页面
e.NoRoute(midderware.NotFound)
e.POST("/webhook", controllers.Webhook)

// 前台页面组,添加右侧标签的中间件
front := e.Group("/", midderware.Tags)
front := e.Group("/", midderware.Sites, midderware.Navigation, midderware.Tags)
{
// 出现错误的页面
e.GET("/errors", midderware.Errors)

// 404 页面
e.NoRoute(midderware.NotFound)

// 首页
front.GET("/", controllers.Home)
// about 页

front.GET("/about", controllers.About)

// 博客文章详情
Expand Down
3 changes: 3 additions & 0 deletions config/config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ icp = "需要填入你自己的备案号"
# 百度统计的 key ,如果不使用的话,不配置或使用空字符串即可
tongji = ""

# github 钩子中配置的 Secret, 要和钩子的配置保持一致
secret = "broqiang.com"

# 日志相关的配置
[log]
# 日志保存位置,默认是应用根目录下生成日志文件
Expand Down

0 comments on commit f520ac9

Please sign in to comment.