gitee-webhook 测试

This commit is contained in:
cuizhibin 2025-06-25 10:31:06 +08:00
parent 52d2a2f486
commit 5f77193e57
2 changed files with 161 additions and 0 deletions

View File

@ -0,0 +1,157 @@
package com.dite.znpt.web.controller;
import org.apache.commons.codec.binary.Hex;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
@RestController
public class DeployController {
@Value("${deploy.secret}")
private String secret;
@Value("${deploy.app-dir}")
private String appDir;
private Process deploymentProcess;
@PostMapping("/gitee-webhook")
public ResponseEntity<String> handleWebhook(
@RequestHeader(value = "X-Gitee-Token", required = false) String signature,
@RequestBody String payload) {
// 验证签名
if (signature == null || !signature.equals(calculateSignature(payload))) {
return ResponseEntity.status(401).body("无效签名");
}
// 安全启动部署
startDeployment();
return ResponseEntity.ok("部署流程已启动");
}
@GetMapping("/deployment-status")
public ResponseEntity<String> getDeploymentStatus() {
try {
Path statusFile = Path.of(appDir, "deployment-status.txt");
if (!Files.exists(statusFile)) {
return ResponseEntity.ok("尚未开始部署");
}
String statusContent = Files.readString(statusFile);
return ResponseEntity.ok(statusContent);
} catch (Exception e) {
return ResponseEntity.status(500).body("状态读取错误: " + e.getMessage());
}
}
@GetMapping("/deployment-log")
public ResponseEntity<String> getDeploymentLog(
@RequestParam(defaultValue = "20") int lines) {
try {
Path logFile = Path.of(appDir, "deploy.log");
if (!Files.exists(logFile)) {
return ResponseEntity.ok("无可用日志");
}
String logContent;
if (lines > 0) {
logContent = tail(logFile, lines);
} else {
logContent = Files.readString(logFile);
}
return ResponseEntity.ok("<pre>" + logContent + "</pre>");
} catch (Exception e) {
return ResponseEntity.status(500).body("日志读取错误: " + e.getMessage());
}
}
private synchronized void startDeployment() {
// 防止重复部署
if (deploymentProcess != null && deploymentProcess.isAlive()) {
return;
}
try {
// 清理旧状态
Files.deleteIfExists(Path.of(appDir, "deployment-status.txt"));
// 启动部署脚本
ProcessBuilder builder = new ProcessBuilder("./deploy.sh");
builder.directory(new File(appDir));
builder.redirectErrorStream(true);
deploymentProcess = builder.start();
// 启动日志监控线程
new Thread(() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(deploymentProcess.getInputStream()))) {
while (deploymentProcess.isAlive()) {
String line = reader.readLine();
if (line != null) {
System.out.println("[DEPLOY] " + line);
}
}
int exitCode = deploymentProcess.waitFor();
System.out.println("部署进程结束,状态码: " + exitCode);
deploymentProcess = null;
} catch (Exception e) {
System.err.println("部署日志读取错误: " + e.getMessage());
}
}).start();
} catch (Exception e) {
System.err.println("启动部署脚本失败: " + e.getMessage());
try {
Files.writeString(Path.of(appDir, "deployment-status.txt"),
"START_FAILED - " + e.getMessage());
} catch (Exception ex) {
// 忽略
}
}
}
private String tail(Path path, int lines) throws IOException {
ProcessBuilder builder = new ProcessBuilder("tail", "-n", String.valueOf(lines), path.toString());
Process process = builder.start();
StringBuilder output = new StringBuilder();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
}
return output.toString();
}
private String calculateSignature(String payload) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] signatureBytes = digest.digest(
(payload + secret).getBytes(StandardCharsets.UTF_8)
);
return Hex.encodeHexString(signatureBytes);
} catch (Exception e) {
throw new RuntimeException("签名生成失败", e);
}
}
}

View File

@ -137,3 +137,7 @@ upload:
# 此处仅定义总的父路径,细节定义到 FilePathEnum
save-path: D:\Upload\
# 部署配置
deploy:
secret: cRc5888KAo4TxRS4y5iv35GM
app-dir: /home/dtyx/znpt-backend