Go 自动拉取 vitepress 文档git仓库并编译部署后加载到nginx

134 阅读2分钟

Go 自动拉取 vitepress 文档仓库并编译部署后加载到nginx

基于Go 开发自动拉取 git 的 vitepress 文档并编译部署的简单脚本

  • 添加了 git 用户名密码。
  • nginx 已配置为前提。

需要使用管理员权限运行以重新加载到nginx。

其中重新加载到 nginx 的代码

cmd2 := exec.Command("/bin/sh", "-c", "nginx -s reload")

为 Linux 版本,其它操作系统需要修改为对应的脚本。

参数

  1. 参数1:vitepress 文档git仓库路径
  2. 参数2:部署目标路径
  3. 参数3:编译结果相对仓库路径(第一个字符必须为路径分割符)
  4. 参数4:git 用户名
  5. 参数5:git 用户的密码
  6. 参数6:可选项。
    值为 0 时执行定时任务,每天0点执行。
    其它情况为非定时任务,立即执行。

Linux 执行例

非定时任务:

sudo ./main /home/user/hello_vitepress /home/user/hello_doc /docs/.vitepress/dist username password

定时任务:

sudo ./main /home/user/hello_vitepress /home/user/hello_doc /docs/.vitepress/dist username password 0

完整代码

package main

import (
    "fmt"
    "github.com/go-git/go-git/v5"
    "github.com/go-git/go-git/v5/plumbing/transport/http"
    cp "github.com/otiai10/copy"
    "github.com/robfig/cron/v3"
    "log"
    "os"
    "os/exec"
)

func main() {
    s := os.Args

    pathRepo := s[1]   // F:\hello_vitepress
    pathDeploy := s[2] // E:\hello_doc
    pathBuild := s[3]  // `\docs.vitepress\dist`
    gitUserName := s[4]

    log.Println(fmt.Sprintf("仓库路径:%s", pathRepo))
    log.Println(fmt.Sprintf("部署路径:%s", pathDeploy))
    log.Println(fmt.Sprintf("编译结果相对仓库路径:%s", pathBuild))
    log.Println(fmt.Sprintf("git用户名:%s", gitUserName))

    // === 定时任务 ===
    if len(s) == 7 && s[6] == "0" {
       // 创建定时任务Cron
       c := cron.New()

       // 定时任务周期及处理函数
       Info("=== 定时任务(每天) ===")
       c.AddFunc("@daily", PullBuildDeploy)

       // 启动定时任务
       c.Start()

       ch := make(chan string)
       <-ch
       return
    }

    // === 立即执行 ===
    Info("=== 立即执行 ===")
    PullBuildDeploy()
}

func PullBuildDeploy() {
    Info("=== 定时任务开始 ===")

    s := os.Args
    pathRepo := s[1]   // F:\hello_vitepress
    pathDeploy := s[2] // E:\hello_doc
    pathBuild := s[3]  // `\docs.vitepress\dist`
    gitUserName := s[4]
    gitPassword := s[5]

    // 定位 Git 仓库
    Info("定位 Git 仓库")
    r, err := git.PlainOpen(pathRepo)
    CheckIfError(err)

    // 获取仓库工作目录
    Info("获取仓库工作目录")
    w, err := r.Worktree()
    CheckIfError(err)

    // 拉取当前分支
    Info("拉取当前分支(git pull)")
    err = w.Pull(&git.PullOptions{
       Auth: &http.BasicAuth{
          Username: gitUserName,
          Password: gitPassword,
       },
       RemoteName: "origin",
    })
    if err != nil {
       log.Println(err)
    }

    // 编译前端
    Info("添加前端依赖(yarn)")
    cmd := exec.Command("yarn")
    cmd.Dir = pathRepo
    out, err := cmd.Output()
    if err != nil {
       log.Println(err)
    }

    // 编译前端
    Info("编译前端(yarn build)")
    cmd = exec.Command("yarn", "build")
    cmd.Dir = pathRepo
    out, err = cmd.Output()
    if err != nil {
       log.Println(err)
    }

    Info("编译信息")
    log.Println(string(out))

    // 复制到目标目录
    Info("复制到目标目录")
    err = cp.Copy(fmt.Sprintf(`%s%s`, pathRepo, pathBuild), pathDeploy)
    if err != nil {
       log.Println(err)
    }

    // nginx 重新加载
    Info("nginx 重新加载")
    cmd.Dir = pathRepo
    cmd2 := exec.Command("/bin/sh", "-c", "nginx -s reload")
    _, err2 := cmd2.Output()
    if err2 != nil {
       log.Println(err2)
    }

    Info("=== 任务完成 ===")
}

func CheckIfError(err error) {
    if err == nil {
       return
    }

    log.Printf("\x1b[31;1m%s\x1b[0m\n", fmt.Sprintf("error: %s", err))
    os.Exit(1)
}

func Info(format string, args ...interface{}) {
    log.Printf("\x1b[34;1m%s\x1b[0m\n", fmt.Sprintf(format, args...))
}