梦想博客

Github使用Webhook功能实现自动更新

· 1131 words · 3 minutes to read
Categories: github
Tags: github

随着公司的项目越来越多,测试版和正式版之间容易混淆,主要是前端是个粗心的小白(你说是吧?陈某惠),经常测试正式版无法正确的区分,导致运营中会出现各种各样的问题,为了解决此问题,突然想到了曾几何时micoya大佬透露的一些姿势,正好今天闲来无事准备来试试

配置 🔗

首先打开github,找到你的项目,点击Settings


然后新建一个webhook,填写您的api地址和密钥


Which events would you like to trigger this webhook?

选择Let me select individual events.

然后下拉选择

Pushes(Git push to a repository.)

完毕后点击 Add webhook

至此,完成了对github的webhook的配置

api接收 🔗

上述配置完成后,编写一个webapi来实现接收github的通知

[HttpPost]
[Route("/api/pull")]
 public async Task<IActionResult> Post()
 {
     using var reader = new StreamReader(Request.Body);
     var payload = await reader.ReadToEndAsync();

     // 验证 GitHub 密钥
     var signatureWithPrefix = Request.Headers["X-Hub-Signature-256"].ToString();
     var computedSignature = ComputeSha256Hash(_gitHubSecret, payload);
     if (!signatureWithPrefix.EndsWith(computedSignature))
     {
         return Unauthorized("Invalid signature");
     }

     // 解析 JSON 数据
     var jsonDocument = JsonDocument.Parse(payload);
     var refBranch = jsonDocument.RootElement.GetProperty("ref").GetString();
     if (string.IsNullOrEmpty(refBranch))
     {
         return Ok("no ref");
     }

     //分支名称
     var branche = refBranch.Split('/').Last();
     //仓库名
     var repositoryName = jsonDocument.RootElement.GetProperty("repository").GetProperty("name").GetString();
     //克隆地址
     var cloneUrl = jsonDocument.RootElement.GetProperty("repository").GetProperty("clone_url").GetString();
     //私有化仓库需要在这里插入git账号和token,https:// 这里是8个长度
     cloneUrl = cloneUrl.Insert(8, $"{_gitHubAccount}:{_gitHubToken}@");
     //提交的消息
     var commitMsg = jsonDocument.RootElement.GetProperty("head_commit").GetProperty("message").GetString();

     //仅在测试版中开放
     if (branche == "develop" || branche == "dev")
     {
         //创建文件夹
         var path = $"/var/webapi/temp/{repositoryName}";

         //目录存在则拉取更新
         if (Directory.Exists(path))
         {
             //直接拉取更新
             await RunCommand("git", $"pull origin {branche}", path);
         }
         else
         {
             //不存在则创建文件夹直接clone
             await RunCommand("mkdir", $"-p {path}");
             //拉取命令
             var gitPullResult = await RunCommand("git", $"clone {cloneUrl} {path}");
         }

         //切换分支
         var gitCheckoutResult = await RunCommand("git", $"switch {branche}", path);

         // 运行 NPM 构建
         var npmInstallResult = await RunCommand("npm", "install", path);
         var npmBuildResult = await RunCommand("npm", "run build", path);

         //删除原文件
         await RunCommand("rm", "-r /var/webapi/GaoXinCashShop");
         //编译后的文件覆盖
         await RunCommand("mv", $"{path}/dist /var/webapi/GaoXinCashShop");

         return Ok("Dev branch updated and built.");
     }
     return Ok("Push not on 'dev' branch, no action taken.");
 }


private static string ComputeSha256Hash(string secret, string payload)
{
    using var hmacSha256 = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
    var hash = hmacSha256.ComputeHash(Encoding.UTF8.GetBytes(payload));
    var builder = new StringBuilder();
    foreach (var b in hash)
    {
        builder.AppendFormat("{0:x2}", b);
    }
    return builder.ToString();
}

private async Task<string> RunCommand(string command, string arguments, string workingDirectory = null)
{
    using var process = new Process
    {
        StartInfo = new ProcessStartInfo
        {
            FileName = command,
            Arguments = arguments,
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true,
            WorkingDirectory = workingDirectory ?? Directory.GetCurrentDirectory()
        }
    };

    process.Start();
    var result = await process.StandardOutput.ReadToEndAsync();
    process.WaitForExit();

    return result;
}

上述代码需要自行修改,可以做多个项目的接收以及字典的配置

上述代码所展示的为vue2项目通过推送develop分支到github后自动实现git clone和npm构建以及覆盖更新的操作

如上代码仅供参考,推荐采用消息队列执行,否则github的推送会超时

请注意,上述代码由于采用执行的UseShellExecute为false,所以无法执行一些操作,例如包含*的,所以如果要执行一些复杂操作,要么采用UseShellExecute为true(会导致无法读取响应结果),要么自己编写代码完成

配合企业微信 🔗

git clone和npm构建完成后我们无法实时收到消息,为了解决此问题可以参考使用企业微信的群机器人推送功能

当git clone操作完成和npm编译操作完成后,可以实时推送消息到企业微信群中,这样更方便处理


提示 🔗

  • 请自备一些工具,否则git无法clone
  • 请自备一些工具,否则npm下载plugin会失败

什么?你不知道工具是什么?那还是别玩了!


Categories