fix
This commit is contained in:
@@ -107,3 +107,6 @@ listener restarts and GitHub push deploy start/success/failure events, set:
|
||||
```sh
|
||||
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
|
||||
```
|
||||
|
||||
Deploy completion and failure notifications include a changed-file summary and a
|
||||
truncated patch preview for the pushed diff.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { TRUNK_TOP_CSS } from "./Tree";
|
||||
|
||||
// aaa
|
||||
interface Leaf {
|
||||
x: number;
|
||||
y: number;
|
||||
|
||||
+99
-12
@@ -74,6 +74,17 @@ function truncate(value, maxLength = 900) {
|
||||
return `${text.slice(0, maxLength - 3)}...`
|
||||
}
|
||||
|
||||
function codeBlock(value, language = '', maxLength = 1000) {
|
||||
const fence = language ? `\`\`\`${language}\n` : '```\n'
|
||||
const suffix = '\n```'
|
||||
const body = truncate(value || 'No diff returned', maxLength - fence.length - suffix.length)
|
||||
return `${fence}${body}${suffix}`
|
||||
}
|
||||
|
||||
function validGitSha(value) {
|
||||
return /^[0-9a-f]{7,40}$/i.test(String(value || ''))
|
||||
}
|
||||
|
||||
function verifySignature(rawBody, signature) {
|
||||
if (!SECRET) return true
|
||||
if (!signature || !signature.startsWith('sha256=')) return false
|
||||
@@ -119,6 +130,35 @@ function run(command, args, options = {}) {
|
||||
})
|
||||
}
|
||||
|
||||
function runCapture(command, args, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const label = [command, ...args].join(' ')
|
||||
const child = spawn(commandFor(command), args, {
|
||||
cwd: __dirname,
|
||||
env: { ...process.env, ...options.env },
|
||||
shell: process.platform === 'win32',
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
})
|
||||
let stdout = ''
|
||||
let stderr = ''
|
||||
|
||||
child.stdout.on('data', (chunk) => {
|
||||
stdout += chunk
|
||||
})
|
||||
child.stderr.on('data', (chunk) => {
|
||||
stderr += chunk
|
||||
})
|
||||
child.on('error', reject)
|
||||
child.on('exit', (code) => {
|
||||
if (code === 0) {
|
||||
resolve(stdout.trim())
|
||||
} else {
|
||||
reject(new Error(`${label} exited with ${code}: ${truncate(stderr || stdout, 500)}`))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async function ensureBuildDependencies() {
|
||||
await run('npm', ['install', '--production=false', '--include=dev', '--include=optional'], {
|
||||
env: {
|
||||
@@ -230,6 +270,44 @@ function deployFields(push) {
|
||||
return fields
|
||||
}
|
||||
|
||||
async function deployDiff(push) {
|
||||
const before = push?.before
|
||||
const after = push?.after
|
||||
|
||||
if (!validGitSha(before) || !validGitSha(after) || /^0+$/.test(before)) {
|
||||
return {
|
||||
summary: 'Diff unavailable for this push range',
|
||||
patch: push?.compare ? `Compare: ${push.compare}` : '',
|
||||
}
|
||||
}
|
||||
|
||||
const range = `${before}..${after}`
|
||||
const [nameStatus, shortStat, patch] = await Promise.all([
|
||||
runCapture('git', ['diff', '--name-status', '--find-renames', range]),
|
||||
runCapture('git', ['diff', '--shortstat', range]),
|
||||
runCapture('git', ['diff', '--find-renames', '--unified=1', range]),
|
||||
])
|
||||
|
||||
return {
|
||||
summary: [shortStat, nameStatus].filter(Boolean).join('\n'),
|
||||
patch,
|
||||
}
|
||||
}
|
||||
|
||||
function diffFields(diff) {
|
||||
if (!diff) return []
|
||||
|
||||
const fields = []
|
||||
if (diff.summary) {
|
||||
fields.push({ name: 'Diff summary', value: codeBlock(diff.summary, 'diff'), inline: false })
|
||||
}
|
||||
if (diff.patch) {
|
||||
fields.push({ name: 'Patch preview', value: codeBlock(diff.patch, 'diff'), inline: false })
|
||||
}
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
async function notifyDeployStarted(push) {
|
||||
await sendDiscordEmbed({
|
||||
title: 'GitHub push deploy started',
|
||||
@@ -239,21 +317,22 @@ async function notifyDeployStarted(push) {
|
||||
})
|
||||
}
|
||||
|
||||
async function notifyDeployCompleted(push) {
|
||||
async function notifyDeployCompleted(push, diff) {
|
||||
await sendDiscordEmbed({
|
||||
title: 'GitHub push deploy completed',
|
||||
color: 0x00f2ff,
|
||||
fields: deployFields(push),
|
||||
fields: [...deployFields(push), ...diffFields(diff)],
|
||||
timestamp: new Date().toISOString(),
|
||||
})
|
||||
}
|
||||
|
||||
async function notifyDeployFailed(push, error) {
|
||||
async function notifyDeployFailed(push, error, diff) {
|
||||
await sendDiscordEmbed({
|
||||
title: 'GitHub push deploy failed',
|
||||
color: 0xe82517,
|
||||
fields: [
|
||||
...deployFields(push),
|
||||
...diffFields(diff),
|
||||
{ name: 'Error', value: truncate(error?.message || error), inline: false },
|
||||
],
|
||||
timestamp: new Date().toISOString(),
|
||||
@@ -261,16 +340,24 @@ async function notifyDeployFailed(push, error) {
|
||||
}
|
||||
|
||||
async function deploy(push) {
|
||||
await notifyDeployStarted(push)
|
||||
await run('git', ['pull', '--ff-only'])
|
||||
await ensureBuildDependencies()
|
||||
await run('npm', ['run', 'build'])
|
||||
let diff = null
|
||||
|
||||
for (const target of RESTART_TARGETS) {
|
||||
await run('pm2', ['reload', target, '--update-env'])
|
||||
try {
|
||||
await notifyDeployStarted(push)
|
||||
await run('git', ['pull', '--ff-only'])
|
||||
diff = await deployDiff(push)
|
||||
await ensureBuildDependencies()
|
||||
await run('npm', ['run', 'build'])
|
||||
|
||||
for (const target of RESTART_TARGETS) {
|
||||
await run('pm2', ['reload', target, '--update-env'])
|
||||
}
|
||||
|
||||
await notifyDeployCompleted(push, diff)
|
||||
} catch (error) {
|
||||
error.deployDiff = diff
|
||||
throw error
|
||||
}
|
||||
|
||||
await notifyDeployCompleted(push)
|
||||
}
|
||||
|
||||
http
|
||||
@@ -313,7 +400,7 @@ http
|
||||
.then(() => console.log('GitHub push deploy completed'))
|
||||
.catch((error) => {
|
||||
console.error('GitHub push deploy failed:', error)
|
||||
notifyDeployFailed(push, error)
|
||||
notifyDeployFailed(push, error, error.deployDiff)
|
||||
})
|
||||
.finally(() => {
|
||||
deploying = false
|
||||
|
||||
Reference in New Issue
Block a user