webadmin端增加版本号和部署功能
This commit is contained in:
@@ -52,6 +52,7 @@ export const HqOperationAction = {
|
||||
PROMO_CODE_UPDATE_STATUS: 'PROMO_CODE_UPDATE_STATUS',
|
||||
REDEEM_PENDING_COMPLETE: 'REDEEM_PENDING_COMPLETE',
|
||||
REDEEM_PENDING_REJECT: 'REDEEM_PENDING_REJECT',
|
||||
DEPLOY_TRIGGER: 'DEPLOY_TRIGGER',
|
||||
} as const;
|
||||
|
||||
export type HqOperationActionCode = (typeof HqOperationAction)[keyof typeof HqOperationAction];
|
||||
@@ -109,6 +110,7 @@ export const HQ_OPERATION_ACTION_LABELS: Record<string, string> = {
|
||||
[HqOperationAction.PROMO_CODE_UPDATE_STATUS]: '推广码启停',
|
||||
[HqOperationAction.REDEEM_PENDING_COMPLETE]: '弱网待处理单-补核销',
|
||||
[HqOperationAction.REDEEM_PENDING_REJECT]: '弱网待处理单-驳回',
|
||||
[HqOperationAction.DEPLOY_TRIGGER]: '触发系统发布',
|
||||
STORE_PAYOUT: '门店打款确认',
|
||||
};
|
||||
|
||||
|
||||
@@ -11,4 +11,9 @@ export class AdminDashboardController {
|
||||
stats() {
|
||||
return this.dashboardService.getStats();
|
||||
}
|
||||
|
||||
@Get('version')
|
||||
version() {
|
||||
return this.dashboardService.getLatestVersion();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,4 +65,20 @@ export class AdminDashboardService {
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
async getLatestVersion() {
|
||||
const row = await this.prisma.systemVersion.findFirst({
|
||||
orderBy: { deployedAt: 'desc' },
|
||||
});
|
||||
if (!row) return null;
|
||||
return {
|
||||
id: row.id.toString(),
|
||||
gitTag: row.gitTag,
|
||||
commitId: row.commitId,
|
||||
commitMessage: row.commitMessage,
|
||||
branch: row.branch,
|
||||
deployedBy: row.deployedBy,
|
||||
deployedAt: row.deployedAt.toISOString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Controller, Post, UseGuards } from '@nestjs/common';
|
||||
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
|
||||
import { SuperAdminGuard } from '../../common/guards/super-admin.guard';
|
||||
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
|
||||
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
|
||||
import { AdminDeployService } from './admin-deploy.service';
|
||||
|
||||
@Controller('admin/deploy')
|
||||
@UseGuards(HqAuthGuard, SuperAdminGuard)
|
||||
export class AdminDeployController {
|
||||
constructor(private readonly deployService: AdminDeployService) {}
|
||||
|
||||
@Post('trigger')
|
||||
@HqOperation({
|
||||
action: HqOperationAction.DEPLOY_TRIGGER,
|
||||
refType: 'DEPLOY',
|
||||
batch: true,
|
||||
})
|
||||
trigger() {
|
||||
return this.deployService.triggerDeploy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
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'),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -49,11 +49,14 @@ import { AdminWechatBindingsController } from './admin-wechat-bindings.controlle
|
||||
import { AdminWechatBindingsService } from './admin-wechat-bindings.service';
|
||||
import { AdminHqPermissionsController } from './admin-hq-permissions.controller';
|
||||
import { AdminHqPermissionsService } from './admin-hq-permissions.service';
|
||||
import { AdminDeployController } from './admin-deploy.controller';
|
||||
import { AdminDeployService } from './admin-deploy.service';
|
||||
|
||||
@Module({
|
||||
imports: [CityScopeModule, IamModule, TradeModule, BenefitModule, CommonModule, IntegrationsModule, RedeemModule],
|
||||
controllers: [
|
||||
AdminDashboardController,
|
||||
AdminDeployController,
|
||||
AdminUsersController,
|
||||
AdminOrdersController,
|
||||
AdminStoresController,
|
||||
@@ -104,6 +107,7 @@ import { AdminHqPermissionsService } from './admin-hq-permissions.service';
|
||||
AdminRedeemDebugService,
|
||||
AdminWechatBindingsService,
|
||||
AdminHqPermissionsService,
|
||||
AdminDeployService,
|
||||
SuperAdminGuard,
|
||||
],
|
||||
exports: [CityScopeModule],
|
||||
|
||||
Reference in New Issue
Block a user