Quellcode durchsuchen

1. 删除.obsidian 2.创建 Gogs Webhooks 文件夹

shizhongqi vor 1 Jahr
Ursprung
Commit
a9489a05b9
2 geänderte Dateien mit 231 neuen und 4 gelöschten Zeilen
  1. 6 4
      .obsidian/workspace.json
  2. 225 0
      Gogs Webhooks/Webhook.md

+ 6 - 4
.obsidian/workspace.json

@@ -13,12 +13,12 @@
             "state": {
               "type": "markdown",
               "state": {
-                "file": "server/熟悉项目笔记/表帐户信息与关系.md",
+                "file": "Gogs Webhooks/Webhook.md",
                 "mode": "source",
                 "source": false
               },
               "icon": "lucide-file",
-              "title": "表帐户信息与关系"
+              "title": "Webhook"
             }
           }
         ]
@@ -170,10 +170,13 @@
   },
   "active": "b86223d1b3917fe9",
   "lastOpenFiles": [
+    "Home.md",
+    "Gogs Webhooks/Webhook.md",
+    "Gogs Webhooks",
+    "server/熟悉项目笔记/表帐户信息与关系.md",
     "front_end/npm安装教程.md",
     "front_end/front_小程序.md",
     "front_end/front_前端项目简介.md",
-    "server/熟悉项目笔记/表帐户信息与关系.md",
     "server/熟悉项目笔记/熟悉前的必备知识.md",
     "server/熟悉项目笔记/批发商应用功能与接口.md",
     "server/熟悉项目笔记/README.md",
@@ -181,7 +184,6 @@
     "server/server_注册花店接口笔记.md",
     "server/server_批发商接口笔记.md",
     "server/熟悉项目笔记",
-    "Home.md",
     "server/server_项目代码架构.md",
     "server/crond.md",
     "server/帐号配置数据.md",

+ 225 - 0
Gogs Webhooks/Webhook.md

@@ -0,0 +1,225 @@
+### 步骤 1: 准备部署脚本 (deploy.sh)
+
+首先,确保你已经有一个可以正常工作的部署脚本,就像上一个回答中提到的那样。我们假设它位于 `/home/myuser/deploy.sh`。
+
+```sh
+#!/bin/bash
+# /home/myuser/deploy.sh
+
+set -e
+
+PROJECT_DIR="/usr/local/nginx/html/huahuibao"
+GIT_BRANCH="dev"
+
+echo "======== [Webhook GO] 部署开始 `date` ========"
+cd $PROJECT_DIR
+unset GIT_DIR
+/usr/local/git/bin/git reset --hard
+/usr/local/git/bin/git pull origin $GIT_BRANCH
+
+# ... 其他构建或重启命令 ...
+# 例如:
+# echo "正在重启服务..."
+# sudo systemctl restart my-app
+
+echo "======== [Webhook dev分支] 部署成功 `date` ========"
+
+```
+
+### 步骤 2: Go 语言 Webhook 监听服务代码
+
+此代码放在测试服 /root/Code/go/gogs-webhook-listener 目录下
+
+创建一个名为 `gogs-webhook-listener` 的文件夹,并在其中创建一个 `main.go` 文件。
+```Go
+package main
+
+import (
+	"crypto/hmac"
+	"crypto/sha256"
+	"encoding/hex"
+	"encoding/json"
+	"fmt"
+	"io"
+	"log"
+	"net/http"
+	"os"
+	"os/exec"
+)
+
+// --- 配置项 ---
+// 这些值可以硬编码,也可以通过环境变量或配置文件传入
+const (
+	// Webhook 监听地址和端口
+	listenAddr = "0.0.0.0:8000"
+	// Gogs Webhook 中设置的密钥,!!务必修改为你的密钥!!
+	gogsSecret = "gogs_secret_key-xhb*2025"
+	// 要执行的部署脚本路径
+	deployScriptPath = "/root/sh/gogs_deploy.sh"
+	// 只对这个分支的 push 事件做出反应
+	targetBranch = "refs/heads/dev"
+	// Webhook 访问路径
+	webhookPath = "/webhook"
+)
+
+// GogsPushPayload 定义了我们关心的 Gogs push 事件的 JSON 结构体字段
+type GogsPushPayload struct {
+	Ref string `json:"ref"` // The full git ref that was pushed. Example: "refs/heads/master".
+}
+
+func main() {
+	http.HandleFunc(webhookPath, handleWebhook)
+
+	log.Printf("Gogs Webhook 监听服务已启动,地址: http://%s%s\n", listenAddr, webhookPath)
+	if err := http.ListenAndServe(listenAddr, nil); err != nil {
+		log.Fatalf("启动 HTTP 服务失败: %v", err)
+	}
+}
+
+// handleWebhook 是处理所有进入 webhookPath 的请求的函数
+func handleWebhook(w http.ResponseWriter, r *http.Request) {
+	// 1. 检查请求方法是否为 POST
+	if r.Method != http.MethodPost {
+		log.Printf("无效的请求方法: %s", r.Method)
+		http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
+		return
+	}
+
+	// 2. 读取请求体
+	body, err := io.ReadAll(r.Body)
+	if err != nil {
+		log.Printf("读取请求体失败: %v", err)
+		http.Error(w, "Internal server error", http.StatusInternalServerError)
+		return
+	}
+	defer r.Body.Close()
+
+	// 3. 验证签名 (关键安全步骤)
+	gogsSignature := r.Header.Get("X-Gogs-Signature")
+	if !isValidSignature(body, gogsSecret, gogsSignature) {
+		log.Println("签名验证失败!请求来源可疑。")
+		http.Error(w, "Invalid signature", http.StatusUnauthorized)
+		return
+	}
+
+	// 4. 检查是否为 'push' 事件
+	if r.Header.Get("X-Gogs-Event") != "push" {
+		log.Println("接收到非 push 事件,已忽略。")
+		w.WriteHeader(http.StatusOK)
+		fmt.Fprint(w, "Not a push event, ignored.")
+		return
+	}
+
+	// 5. 解析 JSON 并检查分支
+	var payload GogsPushPayload
+	if err := json.Unmarshal(body, &payload); err != nil {
+		log.Printf("解析 JSON payload 失败: %v", err)
+		http.Error(w, "Invalid payload", http.StatusBadRequest)
+		return
+	}
+
+	if payload.Ref != targetBranch {
+		log.Printf("接收到对分支 '%s' 的 push,已忽略。目标分支为 '%s'。", payload.Ref, targetBranch)
+		w.WriteHeader(http.StatusOK)
+		fmt.Fprintf(w, "Push to branch %s ignored.", payload.Ref)
+		return
+	}
+
+	// 6. 执行部署脚本
+	log.Printf("验证通过,开始执行部署脚本: %s", deployScriptPath)
+	cmd := exec.Command("sh", deployScriptPath)
+    // 将脚本的标准输出和标准错误输出重定向到 Go 程序的日志
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+
+	if err := cmd.Run(); err != nil {
+		log.Printf("执行部署脚本失败: %v", err)
+		http.Error(w, "Deployment script execution failed", http.StatusInternalServerError)
+		return
+	}
+
+	log.Println("部署脚本执行成功。")
+	w.WriteHeader(http.StatusOK)
+	fmt.Fprint(w, "Deployment triggered successfully.")
+}
+
+// isValidSignature 验证 Gogs 的 HMAC-SHA256 签名
+func isValidSignature(body []byte, secret, signature string) bool {
+	if signature == "" {
+		return false
+	}
+	mac := hmac.New(sha256.New, []byte(secret))
+	mac.Write(body)
+	expectedMAC := hex.EncodeToString(mac.Sum(nil))
+	return hmac.Equal([]byte(signature), []byte(expectedMAC))
+}
+```
+
+
+###  步骤 3: 编译和运行
+
+代码放在测试服 /root 目录下
+
+1. **初始化 Go Module** (如果你还没有的话) 
+	在 `gogs-webhook-listener` 目录下执行:
+```Bash
+go mod init gogs-webhook-listener
+
+```
+
+2. **构建二进制文件** 这个命令会生成一个名为 `gogs-webhook-listener` 的可执行文件。
+```Bash
+go build .
+```
+
+3. **运行服务** 可以直接在前台运行进行测试:
+```Bash
+./gogs-webhook-listener
+```
+你应该会看到日志输出: `Gogs Webhook 监听服务已启动,地址: http://0.0.0.0:8000/webhook`
+
+
+### 步骤 4: 设置为后台服务 (推荐使用 Systemd)
+
+为了让这个服务在服务器上长期稳定地运行,并能开机自启,最好将它配置成一个 `systemd` 服务。
+
+1. 创建 service 文件:
+```
+vim /etc/systemd/system/gogs-webhook.service
+```
+
+2. 写入以下内容。注意修改 `User` 和 `ExecStart` 的路径。
+```
+[Unit]
+Description=Gogs Webhook Listener for Auto Deployment
+After=network.target
+
+[Service]
+Type=simple
+# 建议创建一个专门的用户来运行此服务
+User=myuser
+# ExecStart 指向你编译好的二进制文件的绝对路径
+ExecStart=/home/myuser/gogs-webhook-listener/gogs-webhook-listener
+Restart=on-failure
+RestartSec=5s
+
+[Install]
+WantedBy=multi-user.target
+```
+    
+3. 重载 `systemd` 并启动服务:
+```
+systemctl daemon-reload
+systemctl start gogs-webhook.service
+```
+
+4. 检查服务状态:
+```
+systemctl status gogs-webhook.service
+```
+	如果一切正常,它应该显示 `active (running)`。
+
+5. 设置开机自启:
+```
+systemctl enable gogs-webhook.service
+```