50 lines
1.7 KiB
TypeScript
50 lines
1.7 KiB
TypeScript
import { BadRequestException, Injectable, ServiceUnavailableException } from '@nestjs/common';
|
||
|
||
@Injectable()
|
||
export class AdminDeployService {
|
||
async triggerDeploy() {
|
||
const url = (process.env.DEPLOY_WEBHOOK_URL || 'http://127.0.0.1:8095/deploy').trim();
|
||
const secret = (process.env.DEPLOY_WEBHOOK_SECRET || '').trim();
|
||
if (!secret) {
|
||
throw new ServiceUnavailableException('未配置 DEPLOY_WEBHOOK_SECRET,无法触发发布');
|
||
}
|
||
|
||
let res: Response;
|
||
try {
|
||
res = await fetch(url, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-Deploy-Token': secret,
|
||
},
|
||
body: JSON.stringify({ source: 'admin' }),
|
||
});
|
||
} catch (err) {
|
||
throw new ServiceUnavailableException(
|
||
`无法连接部署 webhook:${err instanceof Error ? err.message : 'network error'}`,
|
||
);
|
||
}
|
||
|
||
const text = await res.text();
|
||
let data: { ok?: boolean; accepted?: boolean; started?: boolean; message?: string; skipped?: boolean } = {};
|
||
try {
|
||
data = text ? (JSON.parse(text) as typeof data) : {};
|
||
} catch {
|
||
throw new ServiceUnavailableException(`部署 webhook 返回非 JSON(HTTP ${res.status})`);
|
||
}
|
||
|
||
if (res.status === 403) {
|
||
throw new BadRequestException(data.message || '部署 webhook 鉴权失败');
|
||
}
|
||
if (!res.ok && res.status !== 202) {
|
||
throw new ServiceUnavailableException(data.message || `部署 webhook 失败(HTTP ${res.status})`);
|
||
}
|
||
|
||
return {
|
||
accepted: true,
|
||
started: data.started !== false && !data.skipped,
|
||
message: data.message || (data.started === false ? 'deploy debounced' : 'deploy started'),
|
||
};
|
||
}
|
||
}
|