mirror of https://github.com/certd/certd
perf: 支持企业微信群聊机器人通知
parent
5450246f06
commit
b805a29259
|
@ -3,13 +3,14 @@ import { RunHistory, RunnableCollection } from "./run-history.js";
|
||||||
import { AbstractTaskPlugin, PluginDefine, pluginRegistry, TaskInstanceContext, UserInfo } from "../plugin/index.js";
|
import { AbstractTaskPlugin, PluginDefine, pluginRegistry, TaskInstanceContext, UserInfo } from "../plugin/index.js";
|
||||||
import { ContextFactory, IContext } from "./context.js";
|
import { ContextFactory, IContext } from "./context.js";
|
||||||
import { IStorage } from "./storage.js";
|
import { IStorage } from "./storage.js";
|
||||||
import { createAxiosService, hashUtils, HttpRequestConfig, ILogger, logger, utils } from "@certd/basic";
|
import { createAxiosService, hashUtils, HttpRequestConfig, ILogger, logger, utils } from "@Certd/basic";
|
||||||
import { IAccessService } from "../access/index.js";
|
import { IAccessService } from "../access/index.js";
|
||||||
import { RegistryItem } from "../registry/index.js";
|
import { RegistryItem } from "../registry/index.js";
|
||||||
import { Decorator } from "../decorator/index.js";
|
import { Decorator } from "../decorator/index.js";
|
||||||
import { ICnameProxyService, IEmailService, IPluginConfigService } from "../service/index.js";
|
import { ICnameProxyService, IEmailService, IPluginConfigService, IUrlService } from "../service/index.js";
|
||||||
import { FileStore } from "./file-store.js";
|
import { FileStore } from "./file-store.js";
|
||||||
import { cloneDeep, forEach, merge } from "lodash-es";
|
import { cloneDeep, forEach, merge } from "lodash-es";
|
||||||
|
import { INotificationService, NotificationBody, NotificationContext, notificationRegistry } from "../notification/index.js";
|
||||||
|
|
||||||
export type ExecutorOptions = {
|
export type ExecutorOptions = {
|
||||||
pipeline: Pipeline;
|
pipeline: Pipeline;
|
||||||
|
@ -17,10 +18,13 @@ export type ExecutorOptions = {
|
||||||
onChanged: (history: RunHistory) => Promise<void>;
|
onChanged: (history: RunHistory) => Promise<void>;
|
||||||
accessService: IAccessService;
|
accessService: IAccessService;
|
||||||
emailService: IEmailService;
|
emailService: IEmailService;
|
||||||
|
notificationService: INotificationService;
|
||||||
cnameProxyService: ICnameProxyService;
|
cnameProxyService: ICnameProxyService;
|
||||||
pluginConfigService: IPluginConfigService;
|
pluginConfigService: IPluginConfigService;
|
||||||
|
urlService: IUrlService;
|
||||||
fileRootDir?: string;
|
fileRootDir?: string;
|
||||||
user: UserInfo;
|
user: UserInfo;
|
||||||
|
baseURL?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Executor {
|
export class Executor {
|
||||||
|
@ -357,20 +361,22 @@ export class Executor {
|
||||||
if (!this.pipeline.notifications) {
|
if (!this.pipeline.notifications) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const url = await this.options.urlService.getPipelineDetailUrl(this.pipeline.id, this.runtime.id);
|
||||||
let subject = "";
|
let subject = "";
|
||||||
let content = "";
|
let content = "";
|
||||||
|
const errorMessage = error?.message;
|
||||||
if (when === "start") {
|
if (when === "start") {
|
||||||
subject = `【CertD】开始执行,【${this.pipeline.id}】${this.pipeline.title}`;
|
subject = `【Certd】开始执行,【${this.pipeline.id}】${this.pipeline.title}`;
|
||||||
content = `buildId:${this.runtime.id}`;
|
content = `buildId:${this.runtime.id}\n查看详情:${url}`;
|
||||||
} else if (when === "success") {
|
} else if (when === "success") {
|
||||||
subject = `【CertD】执行成功,【${this.pipeline.id}】${this.pipeline.title}`;
|
subject = `【Certd】执行成功,【${this.pipeline.id}】${this.pipeline.title}`;
|
||||||
content = `buildId:${this.runtime.id}`;
|
content = `buildId:${this.runtime.id}\n查看详情:${url}`;
|
||||||
} else if (when === "turnToSuccess") {
|
} else if (when === "turnToSuccess") {
|
||||||
subject = `【CertD】执行成功(错误转成功),【${this.pipeline.id}】${this.pipeline.title}`;
|
subject = `【Certd】执行成功(失败转成功),【${this.pipeline.id}】${this.pipeline.title}`;
|
||||||
content = `buildId:${this.runtime.id}`;
|
content = `buildId:${this.runtime.id}\n查看详情:${url}`;
|
||||||
} else if (when === "error") {
|
} else if (when === "error") {
|
||||||
subject = `【CertD】执行失败,【${this.pipeline.id}】${this.pipeline.title}`;
|
subject = `【Certd】执行失败,【${this.pipeline.id}】${this.pipeline.title}`;
|
||||||
content = `buildId:${this.runtime.id}\nerror:${error.message}`;
|
content = `buildId:${this.runtime.id}\n查看详情:${url}\nerror:${error.message}`;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -390,6 +396,39 @@ export class Executor {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error("send email error", e);
|
logger.error("send email error", e);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
//构建notification插件,发送通知
|
||||||
|
const notifyConfig = await this.options.notificationService.getById(notification.notificationId);
|
||||||
|
const notificationPlugin = notificationRegistry.get(notifyConfig.type);
|
||||||
|
const notificationCls: any = notificationPlugin.target;
|
||||||
|
const notificationSender = new notificationCls();
|
||||||
|
const notificationCtx: NotificationContext = {
|
||||||
|
http: utils.http,
|
||||||
|
logger,
|
||||||
|
utils,
|
||||||
|
emailService: this.options.emailService,
|
||||||
|
};
|
||||||
|
//设置参数
|
||||||
|
merge(notificationSender, notifyConfig.setting);
|
||||||
|
notificationSender.setCtx(notificationCtx);
|
||||||
|
await notificationSender.onInstance();
|
||||||
|
const body: NotificationBody = {
|
||||||
|
title: subject,
|
||||||
|
content,
|
||||||
|
userId: this.pipeline.userId,
|
||||||
|
pipeline: this.pipeline,
|
||||||
|
result: this.lastRuntime.pipeline.status,
|
||||||
|
pipelineId: this.pipeline.id,
|
||||||
|
historyId: this.runtime.id,
|
||||||
|
errorMessage,
|
||||||
|
url,
|
||||||
|
};
|
||||||
|
//发送通知
|
||||||
|
await notificationSender.send(body);
|
||||||
|
} catch (e) {
|
||||||
|
logger.error("send notification error", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ export function NewRunHistory(obj: any) {
|
||||||
return history;
|
return history;
|
||||||
}
|
}
|
||||||
export class RunHistory {
|
export class RunHistory {
|
||||||
id!: string;
|
id!: any;
|
||||||
pipeline!: Pipeline;
|
pipeline!: Pipeline;
|
||||||
logs: {
|
logs: {
|
||||||
[runnableId: string]: string[];
|
[runnableId: string]: string[];
|
||||||
|
|
|
@ -62,7 +62,7 @@ export type FileItem = {
|
||||||
path: string;
|
path: string;
|
||||||
};
|
};
|
||||||
export type Runnable = {
|
export type Runnable = {
|
||||||
id: string;
|
id: any;
|
||||||
title: string;
|
title: string;
|
||||||
strategy?: RunnableStrategy;
|
strategy?: RunnableStrategy;
|
||||||
runnableType?: string; // pipeline, stage, task , step
|
runnableType?: string; // pipeline, stage, task , step
|
||||||
|
@ -83,6 +83,9 @@ export type Notification = {
|
||||||
type: NotificationType;
|
type: NotificationType;
|
||||||
when: NotificationWhen[];
|
when: NotificationWhen[];
|
||||||
options: EmailOptions;
|
options: EmailOptions;
|
||||||
|
notificationId: number;
|
||||||
|
title: string;
|
||||||
|
subType: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Pipeline = Runnable & {
|
export type Pipeline = Runnable & {
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
import { PluginRequestHandleReq } from "../plugin";
|
import { PluginRequestHandleReq } from "../plugin";
|
||||||
import { Registrable } from "../registry/index.js";
|
import { Registrable } from "../registry/index.js";
|
||||||
import { FormItemProps } from "../dt/index.js";
|
import { FormItemProps, HistoryResult, Pipeline } from "../dt/index.js";
|
||||||
import { HttpClient, ILogger, utils } from "@certd/basic";
|
import { HttpClient, ILogger, utils } from "@certd/basic";
|
||||||
import * as _ from "lodash-es";
|
import * as _ from "lodash-es";
|
||||||
import { IEmailService } from "../service";
|
import { IEmailService } from "../service/index.js";
|
||||||
|
|
||||||
export type NotificationBody = {
|
export type NotificationBody = {
|
||||||
userId: number;
|
userId: number;
|
||||||
title: string;
|
title: string;
|
||||||
content: string;
|
content: string;
|
||||||
|
pipeline: Pipeline;
|
||||||
pipelineId: number;
|
pipelineId: number;
|
||||||
|
result?: HistoryResult;
|
||||||
historyId: number;
|
historyId: number;
|
||||||
url: string;
|
errorMessage?: string;
|
||||||
extra?: any;
|
url?: string;
|
||||||
options?: any;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NotificationRequestHandleReqInput<T = any> = {
|
export type NotificationRequestHandleReqInput<T = any> = {
|
||||||
|
@ -34,11 +35,21 @@ export type NotificationDefine = Registrable & {
|
||||||
[key: string]: NotificationInputDefine;
|
[key: string]: NotificationInputDefine;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type NotificationInstanceConfig = {
|
||||||
|
id: number;
|
||||||
|
type: string;
|
||||||
|
userId: number;
|
||||||
|
setting: {
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export interface INotificationService {
|
export interface INotificationService {
|
||||||
send(body: NotificationBody): Promise<void>;
|
getById(id: number): Promise<NotificationInstanceConfig>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface INotification extends INotificationService {
|
export interface INotification {
|
||||||
ctx: NotificationContext;
|
ctx: NotificationContext;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +66,9 @@ export abstract class BaseNotification implements INotification {
|
||||||
http!: HttpClient;
|
http!: HttpClient;
|
||||||
logger!: ILogger;
|
logger!: ILogger;
|
||||||
abstract send(body: NotificationBody): Promise<void>;
|
abstract send(body: NotificationBody): Promise<void>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
async onInstance() {}
|
||||||
setCtx(ctx: NotificationContext) {
|
setCtx(ctx: NotificationContext) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.http = ctx.http;
|
this.http = ctx.http;
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import { Decorator } from "../decorator/index.js";
|
import { Decorator } from "../decorator/index.js";
|
||||||
import * as _ from "lodash-es";
|
import * as _ from "lodash-es";
|
||||||
import { notificationRegistry } from "./registry.js";
|
import { notificationRegistry } from "./registry.js";
|
||||||
import { http, logger, utils } from "@certd/basic";
|
|
||||||
import { NotificationContext, NotificationDefine, NotificationInputDefine } from "./api.js";
|
import { NotificationContext, NotificationDefine, NotificationInputDefine } from "./api.js";
|
||||||
|
|
||||||
// 提供一个唯一 key
|
// 提供一个唯一 key
|
||||||
|
@ -39,7 +38,7 @@ export function NotificationInput(input?: NotificationInputDefine): PropertyDeco
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function newNotification(type: string, input: any, ctx?: NotificationContext) {
|
export function newNotification(type: string, input: any, ctx: NotificationContext) {
|
||||||
const register = notificationRegistry.get(type);
|
const register = notificationRegistry.get(type);
|
||||||
if (register == null) {
|
if (register == null) {
|
||||||
throw new Error(`notification ${type} not found`);
|
throw new Error(`notification ${type} not found`);
|
||||||
|
@ -50,11 +49,7 @@ export function newNotification(type: string, input: any, ctx?: NotificationCont
|
||||||
access[key] = input[key];
|
access[key] = input[key];
|
||||||
}
|
}
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
ctx = {
|
throw new Error("ctx is required");
|
||||||
http,
|
|
||||||
logger,
|
|
||||||
utils,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
access.ctx = ctx;
|
access.ctx = ctx;
|
||||||
return access;
|
return access;
|
||||||
|
|
|
@ -19,7 +19,7 @@ export type OnRegisterContext<T> = {
|
||||||
value: RegistryItem<T>;
|
value: RegistryItem<T>;
|
||||||
};
|
};
|
||||||
export type OnRegister<T> = (ctx: OnRegisterContext<T>) => void;
|
export type OnRegister<T> = (ctx: OnRegisterContext<T>) => void;
|
||||||
export class Registry<T> {
|
export class Registry<T = any> {
|
||||||
type = "";
|
type = "";
|
||||||
storage: {
|
storage: {
|
||||||
[key: string]: RegistryItem<T>;
|
[key: string]: RegistryItem<T>;
|
||||||
|
@ -89,7 +89,7 @@ export class Registry<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createRegistry<T>(type: string, onRegister?: OnRegister<T>) {
|
export function createRegistry<T>(type: string, onRegister?: OnRegister<T>): Registry<T> {
|
||||||
const pipelineregistrycacheKey = "PIPELINE_REGISTRY_CACHE";
|
const pipelineregistrycacheKey = "PIPELINE_REGISTRY_CACHE";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let cached: any = global[pipelineregistrycacheKey];
|
let cached: any = global[pipelineregistrycacheKey];
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
export * from "./email.js";
|
export * from "./email.js";
|
||||||
export * from "./cname.js";
|
export * from "./cname.js";
|
||||||
export * from "./config.js";
|
export * from "./config.js";
|
||||||
|
export * from "./url.js";
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface IUrlService {
|
||||||
|
getPipelineDetailUrl(pipelineId: number, historyId: number): Promise<string>;
|
||||||
|
}
|
|
@ -6,7 +6,6 @@ import JSZip from "jszip";
|
||||||
import { CertConverter } from "./convert.js";
|
import { CertConverter } from "./convert.js";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { pick } from "lodash-es";
|
import { pick } from "lodash-es";
|
||||||
import { HttpClient } from "@certd/basic";
|
|
||||||
|
|
||||||
export { CertReader };
|
export { CertReader };
|
||||||
export type { CertInfo };
|
export type { CertInfo };
|
||||||
|
|
|
@ -41,7 +41,7 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
|
||||||
}
|
}
|
||||||
//字段配置赋值
|
//字段配置赋值
|
||||||
columnsRef.value[key] = column;
|
columnsRef.value[key] = column;
|
||||||
console.log("form", columnsRef.value);
|
console.log("form", columnsRef.value, form);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
title: "类型",
|
title: "通知类型",
|
||||||
type: "dict-select",
|
type: "dict-select",
|
||||||
dict: notificationTypeDictRef,
|
dict: notificationTypeDictRef,
|
||||||
search: {
|
search: {
|
||||||
|
@ -100,7 +100,7 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
|
||||||
return option.value.toLowerCase().indexOf(input) >= 0 || option.label.toLowerCase().indexOf(input) >= 0;
|
return option.value.toLowerCase().indexOf(input) >= 0 || option.label.toLowerCase().indexOf(input) >= 0;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rules: [{ required: true, message: "请选择类型" }],
|
rules: [{ required: true, message: "请选择通知类型" }],
|
||||||
valueChange: {
|
valueChange: {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
async handle({ value, mode, form, immediate }) {
|
async handle({ value, mode, form, immediate }) {
|
||||||
|
@ -110,6 +110,7 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
|
||||||
const define = await api.GetProviderDefine(value);
|
const define = await api.GetProviderDefine(value);
|
||||||
currentDefine.value = define;
|
currentDefine.value = define;
|
||||||
console.log("define", define);
|
console.log("define", define);
|
||||||
|
debugger;
|
||||||
if (!immediate) {
|
if (!immediate) {
|
||||||
form.body = {};
|
form.body = {};
|
||||||
}
|
}
|
||||||
|
@ -123,9 +124,6 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
|
||||||
}
|
}
|
||||||
return define.desc;
|
return define.desc;
|
||||||
})
|
})
|
||||||
},
|
|
||||||
addForm: {
|
|
||||||
value: typeRef
|
|
||||||
}
|
}
|
||||||
} as ColumnCompositionProps,
|
} as ColumnCompositionProps,
|
||||||
setting: {
|
setting: {
|
||||||
|
|
|
@ -23,6 +23,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
|
|
||||||
const addRequest = async (req: AddReq) => {
|
const addRequest = async (req: AddReq) => {
|
||||||
const { form } = req;
|
const { form } = req;
|
||||||
|
debugger;
|
||||||
const res = await api.AddObj(form);
|
const res = await api.AddObj(form);
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,6 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
const editRequest = async (req: EditReq) => {
|
const editRequest = async (req: EditReq) => {
|
||||||
const { form, row } = req;
|
const { form, row } = req;
|
||||||
form.id = row.id;
|
form.id = row.id;
|
||||||
form.type = props.type;
|
|
||||||
const res = await context.api.UpdateObj(form);
|
const res = await context.api.UpdateObj(form);
|
||||||
lastResRef.value = res;
|
lastResRef.value = res;
|
||||||
return res;
|
return res;
|
||||||
|
@ -25,7 +24,6 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
|
|
||||||
const addRequest = async (req: AddReq) => {
|
const addRequest = async (req: AddReq) => {
|
||||||
const { form } = req;
|
const { form } = req;
|
||||||
form.type = props.type;
|
|
||||||
const res = await context.api.AddObj(form);
|
const res = await context.api.AddObj(form);
|
||||||
lastResRef.value = res;
|
lastResRef.value = res;
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -68,7 +68,7 @@ const pipelineOptions: PipelineOptions = {
|
||||||
const pipelineOptionsRef: Ref<PipelineOptions> = ref(pipelineOptions);
|
const pipelineOptionsRef: Ref<PipelineOptions> = ref(pipelineOptions);
|
||||||
|
|
||||||
const editMode = ref(false);
|
const editMode = ref(false);
|
||||||
if (route.query.editMode !== "false") {
|
if (route.query.editMode === "true") {
|
||||||
editMode.value = true;
|
editMode.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ export class NotificationEntity {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
@Column({ name: 'user_id', comment: 'UserId' })
|
@Column({ name: 'user_id', comment: 'UserId' })
|
||||||
userId: string;
|
userId: number;
|
||||||
|
|
||||||
@Column({ name: 'type', comment: '通知类型' })
|
@Column({ name: 'type', comment: '通知类型' })
|
||||||
type: string;
|
type: string;
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { INotificationService } from '@certd/pipeline';
|
||||||
|
|
||||||
|
export class NotificationGetter implements INotificationService {
|
||||||
|
userId: number;
|
||||||
|
getter: <T>(id: any, userId?: number) => Promise<T>;
|
||||||
|
constructor(userId: number, getter: (id: any, userId: number) => Promise<any>) {
|
||||||
|
this.userId = userId;
|
||||||
|
this.getter = getter;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getById<T = any>(id: any) {
|
||||||
|
return await this.getter<T>(id, this.userId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ import { BaseService, ValidateException } from '@certd/lib-server';
|
||||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { NotificationEntity } from '../entity/notification.js';
|
import { NotificationEntity } from '../entity/notification.js';
|
||||||
import { notificationRegistry } from '@certd/pipeline';
|
import { NotificationInstanceConfig, notificationRegistry } from '@certd/pipeline';
|
||||||
|
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Singleton)
|
||||||
|
@ -35,4 +35,29 @@ export class NotificationService extends BaseService<NotificationEntity> {
|
||||||
getDefineByType(type: string) {
|
getDefineByType(type: string) {
|
||||||
return notificationRegistry.getDefine(type);
|
return notificationRegistry.getDefine(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getById(id: number, userId: number): Promise<NotificationInstanceConfig> {
|
||||||
|
if (!id) {
|
||||||
|
throw new ValidateException('id不能为空');
|
||||||
|
}
|
||||||
|
if (!userId) {
|
||||||
|
throw new ValidateException('userId不能为空');
|
||||||
|
}
|
||||||
|
const res = await this.repository.findOne({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!res) {
|
||||||
|
throw new ValidateException('通知配置不存在');
|
||||||
|
}
|
||||||
|
const setting = JSON.parse(res.setting);
|
||||||
|
return {
|
||||||
|
id: res.id,
|
||||||
|
type: res.type,
|
||||||
|
userId: res.userId,
|
||||||
|
setting,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@ import dayjs from 'dayjs';
|
||||||
import { DbAdapter } from '../../db/index.js';
|
import { DbAdapter } from '../../db/index.js';
|
||||||
import { isPlus } from '@certd/plus-core';
|
import { isPlus } from '@certd/plus-core';
|
||||||
import { logger } from '@certd/basic';
|
import { logger } from '@certd/basic';
|
||||||
|
import { UrlService } from './url-service.js';
|
||||||
|
import { NotificationService } from './notification-service.js';
|
||||||
|
import { NotificationGetter } from './notification-getter.js';
|
||||||
|
|
||||||
const runningTasks: Map<string | number, Executor> = new Map();
|
const runningTasks: Map<string | number, Executor> = new Map();
|
||||||
const freeCount = 10;
|
const freeCount = 10;
|
||||||
|
@ -63,6 +66,12 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
@Config('certd')
|
@Config('certd')
|
||||||
private certdConfig: any;
|
private certdConfig: any;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
urlService: UrlService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
notificationService: NotificationService;
|
||||||
|
|
||||||
@Inject()
|
@Inject()
|
||||||
dbAdapter: DbAdapter;
|
dbAdapter: DbAdapter;
|
||||||
|
|
||||||
|
@ -384,6 +393,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
};
|
};
|
||||||
const accessGetter = new AccessGetter(userId, this.accessService.getById.bind(this.accessService));
|
const accessGetter = new AccessGetter(userId, this.accessService.getById.bind(this.accessService));
|
||||||
const cnameProxyService = new CnameProxyService(userId, this.cnameRecordService.getWithAccessByDomain.bind(this.cnameRecordService));
|
const cnameProxyService = new CnameProxyService(userId, this.cnameRecordService.getWithAccessByDomain.bind(this.cnameRecordService));
|
||||||
|
const notificationGetter = new NotificationGetter(userId, this.notificationService.getById.bind(this.notificationService));
|
||||||
const executor = new Executor({
|
const executor = new Executor({
|
||||||
user,
|
user,
|
||||||
pipeline,
|
pipeline,
|
||||||
|
@ -393,6 +403,8 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
pluginConfigService: this.pluginConfigGetter,
|
pluginConfigService: this.pluginConfigGetter,
|
||||||
storage: new DbStorage(userId, this.storageService),
|
storage: new DbStorage(userId, this.storageService),
|
||||||
emailService: this.emailService,
|
emailService: this.emailService,
|
||||||
|
urlService: this.urlService,
|
||||||
|
notificationService: notificationGetter,
|
||||||
fileRootDir: this.certdConfig.fileRootDir,
|
fileRootDir: this.certdConfig.fileRootDir,
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { IUrlService } from '@certd/pipeline';
|
||||||
|
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||||
|
import { SysInstallInfo, SysSettingsService } from '@certd/lib-server';
|
||||||
|
|
||||||
|
@Provide()
|
||||||
|
@Scope(ScopeEnum.Singleton)
|
||||||
|
export class UrlService implements IUrlService {
|
||||||
|
@Inject()
|
||||||
|
sysSettingsService: SysSettingsService;
|
||||||
|
|
||||||
|
async getPipelineDetailUrl(pipelineId: number, historyId: number): Promise<string> {
|
||||||
|
const installInfo = await this.sysSettingsService.getSetting<SysInstallInfo>(SysInstallInfo);
|
||||||
|
let baseUrl = 'http://127.0.0.1:7001';
|
||||||
|
if (installInfo.bindUrl) {
|
||||||
|
baseUrl = installInfo.bindUrl;
|
||||||
|
}
|
||||||
|
return `${baseUrl}#/certd/pipeline/detail?id=${pipelineId}&historyId=${historyId}`;
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,9 +42,10 @@ export class QywxNotification extends BaseNotification {
|
||||||
|
|
||||||
await this.http.request({
|
await this.http.request({
|
||||||
url: this.webhook,
|
url: this.webhook,
|
||||||
|
method: 'POST',
|
||||||
data: {
|
data: {
|
||||||
msgtype: 'markdown',
|
msgtype: 'markdown',
|
||||||
text: {
|
markdown: {
|
||||||
content: `# ${body.title}\n\n${body.content}\n[查看详情](${body.url})`,
|
content: `# ${body.title}\n\n${body.content}\n[查看详情](${body.url})`,
|
||||||
mentioned_list: this.mentionedList,
|
mentioned_list: this.mentionedList,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue