mirror of https://github.com/certd/certd
parent
8c152371a1
commit
6f6606d76d
|
@ -3,8 +3,13 @@
|
|||
"private": true,
|
||||
"version": "0.3.0",
|
||||
"main": "./src/index.ts",
|
||||
"module": "./dist/pipeline.mjs",
|
||||
"types": "./dist/es/index.d.ts",
|
||||
"module": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"publishConfig": {
|
||||
"main": "./dist/pipeline.umd.js",
|
||||
"module": "./dist/pipeline.mjs",
|
||||
"types": "./dist/d/index.d.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
|
@ -39,6 +44,7 @@
|
|||
"@types/node-forge": "^1.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
||||
"@typescript-eslint/parser": "^5.38.1",
|
||||
"@rollup/plugin-typescript": "^11.0.0",
|
||||
"chai": "^4.3.6",
|
||||
"eslint": "^8.24.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
|
|
|
@ -39,6 +39,8 @@ export class Executor {
|
|||
await this.runWithHistory(this.pipeline, "pipeline", async () => {
|
||||
await this.runStages();
|
||||
});
|
||||
} catch (e) {
|
||||
this.logger.error("pipeline 执行失败", e);
|
||||
} finally {
|
||||
this.logger.info(`pipeline.${this.pipeline.id} end`);
|
||||
}
|
||||
|
@ -54,12 +56,13 @@ export class Executor {
|
|||
if (runnable.strategy?.runStrategy === RunStrategy.SkipWhenSucceed) {
|
||||
//如果是成功后跳过策略
|
||||
const lastResult = await this.pipelineContext.getObj(contextKey);
|
||||
const lastInput = await this.pipelineContext.getObj(inputKey);
|
||||
const lastInput = await this.pipelineContext.get(inputKey);
|
||||
let inputChanged = false;
|
||||
//TODO 参数不变
|
||||
if (runnableType === "step") {
|
||||
const step = runnable as Step;
|
||||
const input = JSON.stringify(step.input);
|
||||
await this.pipelineContext.set(inputKey, input);
|
||||
if (input != null && lastInput !== input) {
|
||||
inputChanged = true;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
"lib": ["ESNext", "DOM"],
|
||||
"skipLibCheck": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true
|
||||
"emitDecoratorMetadata": true,
|
||||
"outDir": "./dist/ts"
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue","test/**/*.ts"],
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { defineConfig } from "vite";
|
||||
import typescript from "@rollup/plugin-typescript";
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [],
|
||||
|
@ -8,13 +9,23 @@ export default defineConfig({
|
|||
name: "pipeline",
|
||||
},
|
||||
rollupOptions: {
|
||||
plugins: [
|
||||
typescript({
|
||||
target: "esnext",
|
||||
rootDir: "src",
|
||||
declaration: true,
|
||||
declarationDir: "dist/d",
|
||||
exclude: ["./node_modules/**", "./src/**/*.vue"],
|
||||
allowSyntheticDefaultImports: true,
|
||||
}),
|
||||
],
|
||||
external: ["vue", "lodash", "dayjs", "@fast-crud/fast-crud"],
|
||||
output: {
|
||||
// Provide global variables to use in the UMD build
|
||||
// for externalized deps
|
||||
globals: {
|
||||
vue: "Vue",
|
||||
"lodash": "_",
|
||||
lodash: "_",
|
||||
dayjs: "dayjs",
|
||||
"@fast-crud/fast-crud": "FastCrud",
|
||||
},
|
|
@ -1,4 +1,3 @@
|
|||
// src/decorator/memoryCache.decorator.ts
|
||||
import { dnsProviderRegistry } from "./registry";
|
||||
import { DnsProviderDefine } from "./api";
|
||||
import { Decorator, AUTOWIRE_KEY } from "@certd/pipeline";
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { Registry } from "@certd/pipeline";
|
||||
|
||||
// @ts-ignore
|
||||
export const dnsProviderRegistry = new Registry();
|
||||
|
|
|
@ -5,7 +5,11 @@ import { Challenge } from "@certd/acme-client/types/rfc8555";
|
|||
import { Logger } from "log4js";
|
||||
import { IContext } from "@certd/pipeline/src/core/context";
|
||||
import { IDnsProvider } from "../../dns-provider";
|
||||
|
||||
export type CertInfo = {
|
||||
crt: string;
|
||||
key: string;
|
||||
csr: string;
|
||||
};
|
||||
export class AcmeService {
|
||||
userContext: IContext;
|
||||
logger: Logger;
|
||||
|
@ -166,7 +170,7 @@ export class AcmeService {
|
|||
},
|
||||
});
|
||||
|
||||
const cert = {
|
||||
const cert: CertInfo = {
|
||||
crt: crt.toString(),
|
||||
key: key.toString(),
|
||||
csr: csr.toString(),
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
import { CertInfo } from "./acme";
|
||||
import fs from "fs";
|
||||
import os from "os";
|
||||
import forge from "node-forge";
|
||||
import path from "path";
|
||||
export class CertReader implements CertInfo {
|
||||
crt: string;
|
||||
key: string;
|
||||
csr: string;
|
||||
|
||||
detail: any;
|
||||
expires: number;
|
||||
constructor(certInfo: CertInfo) {
|
||||
this.crt = certInfo.crt;
|
||||
this.key = certInfo.key;
|
||||
this.csr = certInfo.csr;
|
||||
|
||||
const { detail, expires } = this.getCrtDetail(this.crt);
|
||||
this.detail = detail;
|
||||
this.expires = expires.getTime();
|
||||
}
|
||||
|
||||
toCertInfo(): CertInfo {
|
||||
return {
|
||||
crt: this.crt,
|
||||
key: this.key,
|
||||
csr: this.csr,
|
||||
};
|
||||
}
|
||||
|
||||
getCrtDetail(crt: string) {
|
||||
const pki = forge.pki;
|
||||
const detail = pki.certificateFromPem(crt.toString());
|
||||
const expires = detail.validity.notAfter;
|
||||
return { detail, expires };
|
||||
}
|
||||
|
||||
saveToFile(type: "crt" | "key", filepath?: string) {
|
||||
if (filepath == null) {
|
||||
//写入临时目录
|
||||
filepath = path.join(os.tmpdir(), "/certd/tmp/", Math.floor(Math.random() * 1000000) + "", `cert.${type}`);
|
||||
}
|
||||
|
||||
const dir = path.dirname(filepath);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
|
||||
fs.writeFileSync(filepath, this[type]);
|
||||
return filepath;
|
||||
}
|
||||
}
|
|
@ -1,46 +1,15 @@
|
|||
import { Autowire, HttpClient, IAccessService, IContext, IsTaskPlugin, ITaskPlugin, RunStrategy, TaskInput, TaskOutput } from "@certd/pipeline";
|
||||
import forge from "node-forge";
|
||||
import dayjs from "dayjs";
|
||||
import { AcmeService } from "./acme";
|
||||
import { AcmeService, CertInfo } from "./acme";
|
||||
import _ from "lodash";
|
||||
import { Logger } from "log4js";
|
||||
import { Decorator } from "@certd/pipeline/src/decorator";
|
||||
import { DnsProviderDefine, dnsProviderRegistry } from "../../dns-provider";
|
||||
import fs from "fs";
|
||||
import os from "os";
|
||||
export class CertInfo {
|
||||
crt: string;
|
||||
key: string;
|
||||
csr: string;
|
||||
import { CertReader } from "./cert-reader";
|
||||
|
||||
detail: any;
|
||||
expires: number;
|
||||
constructor(opts: { crt: string; key: string; csr: string }) {
|
||||
this.crt = opts.crt;
|
||||
this.key = opts.key;
|
||||
this.csr = opts.csr;
|
||||
export { CertReader };
|
||||
export type { CertInfo };
|
||||
|
||||
const { detail, expires } = this.getCrtDetail(this.crt);
|
||||
this.detail = detail;
|
||||
this.expires = expires.getTime();
|
||||
}
|
||||
|
||||
getCrtDetail(crt: string) {
|
||||
const pki = forge.pki;
|
||||
const detail = pki.certificateFromPem(crt.toString());
|
||||
const expires = detail.validity.notAfter;
|
||||
return { detail, expires };
|
||||
}
|
||||
|
||||
saveToFile(type: "crt" | "key", path?: string) {
|
||||
if (path == null) {
|
||||
//写入临时目录
|
||||
path = `${os.tmpdir()}/certd/tmp/${Math.floor(Math.random() * 1000000)}/cert.${type}`;
|
||||
}
|
||||
fs.writeFileSync(path, this[type]);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
@IsTaskPlugin({
|
||||
name: "CertApply",
|
||||
title: "证书申请",
|
||||
|
@ -166,10 +135,14 @@ export class CertApplyPlugin implements ITaskPlugin {
|
|||
return this.output(oldCert);
|
||||
}
|
||||
const cert = await this.doCertApply();
|
||||
return this.output(cert);
|
||||
if (cert != null) {
|
||||
this.output(cert.toCertInfo());
|
||||
} else {
|
||||
throw new Error("申请证书失败");
|
||||
}
|
||||
}
|
||||
|
||||
output(cert: any) {
|
||||
output(cert: CertInfo) {
|
||||
this.cert = cert;
|
||||
}
|
||||
|
||||
|
@ -187,12 +160,12 @@ export class CertApplyPlugin implements ITaskPlugin {
|
|||
const oldInputStr = await this.pipelineContext.getObj(inputCacheKey);
|
||||
await this.pipelineContext.setObj(inputCacheKey, this.domains);
|
||||
const oldInput = JSON.stringify(oldInputStr);
|
||||
const thisInput = JSON.stringify(this.cert);
|
||||
const thisInput = JSON.stringify(this.domains);
|
||||
if (oldInput !== thisInput) {
|
||||
inputChanged = true;
|
||||
}
|
||||
|
||||
let oldCert;
|
||||
let oldCert: CertReader | undefined = undefined;
|
||||
try {
|
||||
oldCert = await this.readCurrentCert();
|
||||
} catch (e) {
|
||||
|
@ -257,10 +230,7 @@ export class CertApplyPlugin implements ITaskPlugin {
|
|||
await this.writeCert(cert);
|
||||
const ret = await this.readCurrentCert();
|
||||
|
||||
return {
|
||||
...ret,
|
||||
isNew: true,
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
formatCert(pem: string) {
|
||||
|
@ -271,7 +241,7 @@ export class CertApplyPlugin implements ITaskPlugin {
|
|||
}
|
||||
|
||||
async writeCert(cert: { crt: string; key: string; csr: string }) {
|
||||
const newCert = {
|
||||
const newCert: CertInfo = {
|
||||
crt: this.formatCert(cert.crt),
|
||||
key: this.formatCert(cert.key),
|
||||
csr: this.formatCert(cert.csr),
|
||||
|
@ -282,12 +252,12 @@ export class CertApplyPlugin implements ITaskPlugin {
|
|||
await this.pipelineContext.set("cert.csr", newCert.csr);
|
||||
}
|
||||
|
||||
async readCurrentCert() {
|
||||
const cert: any = await this.pipelineContext.getObj("cert");
|
||||
async readCurrentCert(): Promise<CertReader | undefined> {
|
||||
const cert: CertInfo = await this.pipelineContext.getObj("cert");
|
||||
if (cert == null) {
|
||||
return undefined;
|
||||
}
|
||||
return new CertInfo(cert);
|
||||
return new CertReader(cert);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
export * from "./cert-plugin";
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": true,
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "commonjs",
|
||||
|
|
|
@ -42,6 +42,10 @@ export class SshAccess implements IAccess {
|
|||
@AccessInput({
|
||||
title: "密钥",
|
||||
helper: "密钥或密码必填一项",
|
||||
component: {
|
||||
name: "a-textarea",
|
||||
vModel: "value",
|
||||
},
|
||||
})
|
||||
privateKey!: string;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { Autowire, IAccessService, IsTaskPlugin, ILogger, RunStrategy, TaskInput, ITaskPlugin } from "@certd/pipeline";
|
||||
import { Autowire, IAccessService, ILogger, IsTaskPlugin, ITaskPlugin, RunStrategy, TaskInput } from "@certd/pipeline";
|
||||
import { SshClient } from "../../lib/ssh";
|
||||
import { CertInfo } from "@certd/plugin-cert";
|
||||
|
||||
@IsTaskPlugin({
|
||||
name: "hostShellExecute",
|
||||
|
@ -24,15 +23,6 @@ export class HostShellExecutePlugin implements ITaskPlugin {
|
|||
required: true,
|
||||
})
|
||||
accessId!: string;
|
||||
@TaskInput({
|
||||
title: "域名证书",
|
||||
helper: "请选择前置任务输出的域名证书",
|
||||
component: {
|
||||
name: "pi-output-selector",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
cert!: CertInfo;
|
||||
@TaskInput({
|
||||
title: "shell脚本命令",
|
||||
component: {
|
||||
|
@ -51,7 +41,7 @@ export class HostShellExecutePlugin implements ITaskPlugin {
|
|||
async onInstance() {}
|
||||
async execute(): Promise<void> {
|
||||
const { script, accessId } = this;
|
||||
const connectConf = this.accessService.getById(accessId);
|
||||
const connectConf = await this.accessService.getById(accessId);
|
||||
const sshClient = new SshClient(this.logger);
|
||||
const ret = await sshClient.exec({
|
||||
connectConf,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Autowire, IAccessService, IsTaskPlugin, ITaskPlugin, ILogger, RunStrategy, TaskInput, TaskOutput } from "@certd/pipeline";
|
||||
import { SshClient } from "../../lib/ssh";
|
||||
import { CertInfo } from "@certd/plugin-cert";
|
||||
import { CertInfo, CertReader } from "@certd/plugin-cert";
|
||||
import * as fs from "fs";
|
||||
|
||||
@IsTaskPlugin({
|
||||
|
@ -67,11 +67,12 @@ export class UploadCertToHostPlugin implements ITaskPlugin {
|
|||
async onInstance() {}
|
||||
async execute(): Promise<void> {
|
||||
const { crtPath, keyPath, cert, accessId, sudo } = this;
|
||||
const connectConf = this.accessService.getById(accessId);
|
||||
const certReader = new CertReader(cert);
|
||||
const connectConf = await this.accessService.getById(accessId);
|
||||
const sshClient = new SshClient(this.logger);
|
||||
|
||||
const saveCrtPath = cert.saveToFile("crt");
|
||||
const saveKeyPath = cert.saveToFile("key");
|
||||
const saveCrtPath = certReader.saveToFile("crt");
|
||||
const saveKeyPath = certReader.saveToFile("key");
|
||||
|
||||
await sshClient.uploadFiles({
|
||||
connectConf,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": true,
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "commonjs",
|
||||
|
|
|
@ -73,7 +73,7 @@ export class HuaweiDnsProvider implements IDnsProvider {
|
|||
if (records && records.length > 0) {
|
||||
for (const record of records) {
|
||||
await this.removeRecord({
|
||||
record: records[0],
|
||||
record,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// @ts-ignore
|
||||
import signer from "./signer";
|
||||
import https from "https";
|
||||
import { HuaweiAccess } from "../access";
|
||||
import { axios } from "@certd/acme-client";
|
||||
import { logger } from "@certd/pipeline";
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": true,
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "commonjs",
|
||||
|
|
|
@ -20,11 +20,14 @@
|
|||
"author": "Greper",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "workspace:^0.3.0",
|
||||
"@certd/pipeline": "workspace:^0.3.0",
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
"@ant-design/icons-vue": "^6.0.1",
|
||||
"@fast-crud/fast-crud": "^1.9.2",
|
||||
"@fast-crud/fast-extends": "^1.9.2",
|
||||
"@fast-crud/ui-antdv": "^1.9.2",
|
||||
"@fast-crud/fast-crud": "^1.13.8",
|
||||
"@fast-crud/fast-extends": "^1.13.8",
|
||||
"@fast-crud/ui-antdv": "^1.13.8",
|
||||
"@fast-crud/ui-interface": "^1.13.8",
|
||||
"@iconify/iconify": "^3.0.1",
|
||||
"@iconify/json": "^2.1.151",
|
||||
"@purge-icons/generated": "^0.9.0",
|
||||
|
|
|
@ -1,25 +1,31 @@
|
|||
// @ts-ignore
|
||||
import * as api from "/@/views/certd/access/api";
|
||||
import { ref } from "vue";
|
||||
import { getCommonColumnDefine } from "/@/views/certd/access/common";
|
||||
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
|
||||
export default function ({ expose, props, ctx }) {
|
||||
const { crudBinding } = expose;
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const { crudBinding } = crudExpose;
|
||||
const { props, ctx } = context;
|
||||
const lastResRef = ref();
|
||||
const pageRequest = async (query) => {
|
||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||
return await api.GetList(query);
|
||||
};
|
||||
const editRequest = async ({ form, row }) => {
|
||||
const editRequest = async (req: EditReq) => {
|
||||
const { form, row } = req;
|
||||
form.id = row.id;
|
||||
form.type = props.type;
|
||||
const res = await api.UpdateObj(form);
|
||||
lastResRef.value = res;
|
||||
return res;
|
||||
};
|
||||
const delRequest = async ({ row }) => {
|
||||
const delRequest = async (req: DelReq) => {
|
||||
const { row } = req;
|
||||
return await api.DelObj(row.id);
|
||||
};
|
||||
|
||||
const addRequest = async ({ form }) => {
|
||||
const addRequest = async (req: AddReq) => {
|
||||
const { form } = req;
|
||||
form.type = props.type;
|
||||
const res = await api.AddObj(form);
|
||||
lastResRef.value = res;
|
||||
|
@ -27,24 +33,15 @@ export default function ({ expose, props, ctx }) {
|
|||
};
|
||||
|
||||
const selectedRowKey = ref([props.modelValue]);
|
||||
// watch(
|
||||
// () => {
|
||||
// return props.modelValue;
|
||||
// },
|
||||
// (value) => {
|
||||
// selectedRowKey.value = [value];
|
||||
// },
|
||||
// {
|
||||
// immediate: true
|
||||
// }
|
||||
// );
|
||||
const onSelectChange = (changed) => {
|
||||
|
||||
const onSelectChange = (changed: any) => {
|
||||
selectedRowKey.value = changed;
|
||||
ctx.emit("update:modelValue", changed[0]);
|
||||
};
|
||||
|
||||
const typeRef = ref("aliyun");
|
||||
const commonColumnsDefine = getCommonColumnDefine(crudBinding, typeRef);
|
||||
context.typeRef = typeRef;
|
||||
const commonColumnsDefine = getCommonColumnDefine(crudExpose, typeRef);
|
||||
commonColumnsDefine.type.form.component.disabled = true;
|
||||
return {
|
||||
typeRef,
|
||||
|
@ -75,7 +72,7 @@ export default function ({ expose, props, ctx }) {
|
|||
selectedRowKeys: selectedRowKey,
|
||||
onChange: onSelectChange
|
||||
},
|
||||
customRow: (record) => {
|
||||
customRow: (record: any) => {
|
||||
return {
|
||||
onClick: () => {
|
||||
onSelectChange([record.id]);
|
|
@ -4,9 +4,9 @@
|
|||
</fs-page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, onMounted, ref, watch } from "vue";
|
||||
import { useCrud, useExpose } from "@fast-crud/fast-crud";
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, watch } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "./crud";
|
||||
|
||||
export default defineComponent({
|
||||
|
@ -20,22 +20,14 @@ export default defineComponent({
|
|||
},
|
||||
emits: ["update:modelValue"],
|
||||
setup(props, ctx) {
|
||||
// crud组件的ref
|
||||
const crudRef = ref();
|
||||
// crud 配置的ref
|
||||
const crudBinding = ref();
|
||||
// 暴露的方法
|
||||
const { expose } = useExpose({ crudRef, crudBinding });
|
||||
// 你的crud配置
|
||||
const { crudOptions, typeRef } = createCrudOptions({ expose, props, ctx });
|
||||
// 初始化crud配置
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
|
||||
const { resetCrudOptions } = useCrud({ expose, crudOptions });
|
||||
const context: any = { props, ctx };
|
||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context });
|
||||
|
||||
// 你可以调用此方法,重新初始化crud配置
|
||||
function onTypeChanged(value) {
|
||||
typeRef.value = value;
|
||||
expose.setSearchFormData({ form: { type: value }, mergeForm: true });
|
||||
expose.doRefresh();
|
||||
function onTypeChanged(value: any) {
|
||||
context.typeRef.value = value;
|
||||
crudExpose.setSearchFormData({ form: { type: value }, mergeForm: true });
|
||||
crudExpose.doRefresh();
|
||||
}
|
||||
watch(
|
||||
() => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { request } from "/src/api/service";
|
||||
const apiPrefix = "/pi/access";
|
||||
export function GetList(query) {
|
||||
export function GetList(query: any) {
|
||||
return request({
|
||||
url: apiPrefix + "/page",
|
||||
method: "post",
|
||||
|
@ -8,7 +8,7 @@ export function GetList(query) {
|
|||
});
|
||||
}
|
||||
|
||||
export function AddObj(obj) {
|
||||
export function AddObj(obj: any) {
|
||||
return request({
|
||||
url: apiPrefix + "/add",
|
||||
method: "post",
|
||||
|
@ -16,7 +16,7 @@ export function AddObj(obj) {
|
|||
});
|
||||
}
|
||||
|
||||
export function UpdateObj(obj) {
|
||||
export function UpdateObj(obj: any) {
|
||||
return request({
|
||||
url: apiPrefix + "/update",
|
||||
method: "post",
|
||||
|
@ -24,7 +24,7 @@ export function UpdateObj(obj) {
|
|||
});
|
||||
}
|
||||
|
||||
export function DelObj(id) {
|
||||
export function DelObj(id: number) {
|
||||
return request({
|
||||
url: apiPrefix + "/delete",
|
||||
method: "post",
|
||||
|
@ -32,7 +32,7 @@ export function DelObj(id) {
|
|||
});
|
||||
}
|
||||
|
||||
export function GetObj(id) {
|
||||
export function GetObj(id: number) {
|
||||
return request({
|
||||
url: apiPrefix + "/info",
|
||||
method: "post",
|
||||
|
@ -40,7 +40,7 @@ export function GetObj(id) {
|
|||
});
|
||||
}
|
||||
|
||||
export function GetProviderDefine(type) {
|
||||
export function GetProviderDefine(type: string) {
|
||||
return request({
|
||||
url: apiPrefix + "/define",
|
||||
method: "post",
|
|
@ -1,8 +1,11 @@
|
|||
import { dict } from "@fast-crud/fast-crud";
|
||||
import { ColumnCompositionProps, dict } from "@fast-crud/fast-crud";
|
||||
// @ts-ignore
|
||||
import * as api from "./api";
|
||||
// @ts-ignore
|
||||
import _ from "lodash";
|
||||
import { toRef } from "vue";
|
||||
|
||||
export function getCommonColumnDefine(crudBinding, typeRef) {
|
||||
export function getCommonColumnDefine(crudExpose: any, typeRef: any) {
|
||||
const AccessTypeDictRef = dict({
|
||||
url: "/pi/access/accessTypeDict"
|
||||
});
|
||||
|
@ -13,22 +16,24 @@ export function getCommonColumnDefine(crudBinding, typeRef) {
|
|||
}
|
||||
};
|
||||
|
||||
function buildDefineFields(define, mode) {
|
||||
const columns = crudBinding.value[mode + "Form"].columns;
|
||||
for (const key in columns) {
|
||||
function buildDefineFields(define: any) {
|
||||
const formWrapperRef = crudExpose.getFormWrapperRef();
|
||||
const columnsRef = toRef(formWrapperRef.formOptions, "columns");
|
||||
|
||||
for (const key in columnsRef.value) {
|
||||
if (key.indexOf(".") >= 0) {
|
||||
delete columns[key];
|
||||
delete columnsRef.value[key];
|
||||
}
|
||||
}
|
||||
console.log('crudBinding.value[mode + "Form"].columns', columns);
|
||||
_.forEach(define.input, (value, mapKey) => {
|
||||
console.log('crudBinding.value[mode + "Form"].columns', columnsRef.value);
|
||||
_.forEach(define.input, (value: any, mapKey: any) => {
|
||||
const key = "access." + mapKey;
|
||||
const field = {
|
||||
...value,
|
||||
key
|
||||
};
|
||||
columns[key] = _.merge({ title: key }, defaultPluginConfig, field);
|
||||
console.log("form", crudBinding.value[mode + "Form"]);
|
||||
columnsRef.value[key] = _.merge({ title: key }, defaultPluginConfig, field);
|
||||
console.log("form", columnsRef.value);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -53,14 +58,14 @@ export function getCommonColumnDefine(crudBinding, typeRef) {
|
|||
}
|
||||
const define = await api.GetProviderDefine(value);
|
||||
console.log("define", define);
|
||||
buildDefineFields(define, mode);
|
||||
buildDefineFields(define);
|
||||
}
|
||||
}
|
||||
},
|
||||
addForm: {
|
||||
value: typeRef
|
||||
}
|
||||
},
|
||||
} as ColumnCompositionProps,
|
||||
setting: {
|
||||
column: { show: false },
|
||||
form: {
|
||||
|
@ -80,6 +85,6 @@ export function getCommonColumnDefine(crudBinding, typeRef) {
|
|||
form.setting = JSON.stringify(setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
} as ColumnCompositionProps
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,27 +1,34 @@
|
|||
// @ts-ignore
|
||||
import * as api from "./api";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { ref } from "vue";
|
||||
import { getCommonColumnDefine } from "/@/views/certd/access/common";
|
||||
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
|
||||
export default function ({ expose }) {
|
||||
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const { t } = useI18n();
|
||||
const pageRequest = async (query) => {
|
||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||
return await api.GetList(query);
|
||||
};
|
||||
const editRequest = async ({ form, row }) => {
|
||||
const editRequest = async (req: EditReq) => {
|
||||
const { form, row } = req;
|
||||
form.id = row.id;
|
||||
return await api.UpdateObj(form);
|
||||
const res = await api.UpdateObj(form);
|
||||
return res;
|
||||
};
|
||||
const delRequest = async ({ row }) => {
|
||||
const delRequest = async (req: DelReq) => {
|
||||
const { row } = req;
|
||||
return await api.DelObj(row.id);
|
||||
};
|
||||
|
||||
const addRequest = async ({ form }) => {
|
||||
return await api.AddObj(form);
|
||||
const addRequest = async (req: AddReq) => {
|
||||
const { form } = req;
|
||||
const res = await api.AddObj(form);
|
||||
return res;
|
||||
};
|
||||
|
||||
const typeRef = ref();
|
||||
const { crudBinding } = expose;
|
||||
const commonColumnsDefine = getCommonColumnDefine(crudBinding, typeRef);
|
||||
const commonColumnsDefine = getCommonColumnDefine(crudExpose, typeRef);
|
||||
return {
|
||||
crudOptions: {
|
||||
request: {
|
||||
|
|
|
@ -8,31 +8,18 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, onMounted } from "vue";
|
||||
import { useCrud } from "@fast-crud/fast-crud";
|
||||
import { defineComponent, onMounted } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "./crud";
|
||||
import { useExpose } from "@fast-crud/fast-crud";
|
||||
import { message } from "ant-design-vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "CertdAccess",
|
||||
setup() {
|
||||
// crud组件的ref
|
||||
const crudRef = ref();
|
||||
// crud 配置的ref
|
||||
const crudBinding = ref();
|
||||
// 暴露的方法
|
||||
const { expose } = useExpose({ crudRef, crudBinding });
|
||||
// 你的crud配置
|
||||
const { crudOptions } = createCrudOptions({ expose });
|
||||
// 初始化crud配置
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
|
||||
const { resetCrudOptions } = useCrud({ expose, crudOptions });
|
||||
// 你可以调用此方法,重新初始化crud配置
|
||||
// resetCrudOptions(options)
|
||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} });
|
||||
|
||||
// 页面打开后获取列表数据
|
||||
onMounted(() => {
|
||||
expose.doRefresh();
|
||||
crudExpose.doRefresh();
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<fs-page class="fs-pipeline-detail">
|
||||
<pipeline-edit v-model:edit-mode="editMode" :pipeline-id="pipelineId" :options="pipelineOptions"></pipeline-edit>
|
||||
<pipeline-edit v-model:edit-mode="editMode" :pipeline-id="pipelineId" :options="pipelineOptionsRef"></pipeline-edit>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
|
@ -11,8 +11,7 @@ import * as pluginApi from "./api.plugin";
|
|||
import * as historyApi from "./api.history";
|
||||
import * as api from "./api";
|
||||
import { useRoute } from "vue-router";
|
||||
import { Pipeline, PipelineDetail, PipelineOptions, RunHistory } from "/@/views/certd/pipeline/pipeline/type";
|
||||
import { PluginDefine } from "@certd/pipeline";
|
||||
import { PipelineDetail, PipelineOptions, RunHistory, Pipeline } from "/@/views/certd/pipeline/pipeline/type";
|
||||
|
||||
export default defineComponent({
|
||||
name: "PipelineDetail",
|
||||
|
@ -21,51 +20,47 @@ export default defineComponent({
|
|||
const route = useRoute();
|
||||
const pipelineId = ref(route.query.id);
|
||||
|
||||
const getPipelineDetail = async ({ pipelineId }) => {
|
||||
const detail = await api.GetDetail(pipelineId);
|
||||
return {
|
||||
pipeline: {
|
||||
id: detail.pipeline.id,
|
||||
stages: [],
|
||||
triggers: [],
|
||||
...JSON.parse(detail.pipeline.content || "{}")
|
||||
}
|
||||
} as PipelineDetail;
|
||||
const pipelineOptions: PipelineOptions = {
|
||||
async getPipelineDetail({ pipelineId }) {
|
||||
const detail = await api.GetDetail(pipelineId);
|
||||
return {
|
||||
pipeline: {
|
||||
id: detail.pipeline.id,
|
||||
stages: [],
|
||||
triggers: [],
|
||||
...JSON.parse(detail.pipeline.content || "{}")
|
||||
}
|
||||
} as PipelineDetail;
|
||||
},
|
||||
|
||||
async getHistoryList({ pipelineId }) {
|
||||
const list: RunHistory[] = await historyApi.GetList({ pipelineId });
|
||||
return list;
|
||||
},
|
||||
|
||||
async getHistoryDetail({ historyId }): Promise<RunHistory> {
|
||||
const detail = await historyApi.GetDetail({ id: historyId });
|
||||
return detail;
|
||||
},
|
||||
|
||||
async getPlugins() {
|
||||
const plugins = await pluginApi.GetList({});
|
||||
return plugins as any[];
|
||||
},
|
||||
|
||||
async doSave(pipelineConfig: any) {
|
||||
await api.Save({
|
||||
id: pipelineConfig.id,
|
||||
content: JSON.stringify(pipelineConfig)
|
||||
});
|
||||
},
|
||||
async doTrigger(options: { pipelineId: number }) {
|
||||
const { pipelineId } = options;
|
||||
await api.Trigger(pipelineId);
|
||||
}
|
||||
};
|
||||
|
||||
const getHistoryList = async ({ pipelineId }) => {
|
||||
const list: RunHistory[] = await historyApi.GetList({ pipelineId });
|
||||
return list;
|
||||
};
|
||||
|
||||
const getHistoryDetail = async ({ historyId }): Promise<RunHistory> => {
|
||||
const detail = await historyApi.GetDetail({ id: historyId });
|
||||
return detail;
|
||||
};
|
||||
|
||||
const getPlugins = async () => {
|
||||
const plugins = await pluginApi.GetList({});
|
||||
return plugins as PluginDefine[];
|
||||
};
|
||||
|
||||
async function doSave(pipelineConfig: Pipeline) {
|
||||
await api.Save({
|
||||
id: pipelineConfig.id,
|
||||
content: JSON.stringify(pipelineConfig)
|
||||
});
|
||||
}
|
||||
async function doTrigger({ pipelineId }) {
|
||||
await api.Trigger(pipelineId);
|
||||
}
|
||||
|
||||
const pipelineOptions: Ref<PipelineOptions> = ref({
|
||||
doTrigger,
|
||||
doSave,
|
||||
getPlugins,
|
||||
getHistoryList,
|
||||
getHistoryDetail,
|
||||
getPipelineDetail
|
||||
});
|
||||
const pipelineOptionsRef: Ref<PipelineOptions> = ref(pipelineOptions);
|
||||
|
||||
const editMode = ref(false);
|
||||
if (route.query.editMode !== "false") {
|
||||
|
@ -73,7 +68,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
return {
|
||||
pipelineOptions,
|
||||
pipelineOptionsRef,
|
||||
pipelineId,
|
||||
editMode
|
||||
};
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
import { PluginDefine, Pipeline } from "@certd/pipeline/src";
|
||||
export * from "@certd/pipeline/src";
|
||||
export type PipelineDetail = {
|
||||
pipeline: Pipeline;
|
||||
};
|
||||
|
||||
export type RunHistory = {
|
||||
id: any;
|
||||
pipeline: Pipeline;
|
||||
logs?: {
|
||||
[id: string]: string[];
|
||||
};
|
||||
};
|
||||
|
||||
export type PipelineOptions = {
|
||||
doTrigger(options: { pipelineId }): Promise<void>;
|
||||
doSave(pipelineConfig: PipelineDefile): Promise<void>;
|
||||
getPipelineDetail(query: { pipelineId }): Promise<PipelineDetail>;
|
||||
getHistoryList(query: { pipelineId }): Promise<RunHistory[]>;
|
||||
getHistoryDetail(query: { historyId }): Promise<RunHistory>;
|
||||
getPlugins(): Promise<PluginDefine[]>;
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
import { Pipeline } from "@certd/pipeline";
|
||||
export * from "@certd/pipeline";
|
||||
export type PipelineDetail = {
|
||||
pipeline: Pipeline;
|
||||
};
|
||||
|
||||
export type RunHistory = {
|
||||
id: any;
|
||||
pipeline: Pipeline;
|
||||
logs?: {
|
||||
[id: string]: string[];
|
||||
};
|
||||
};
|
||||
|
||||
export type PipelineOptions = {
|
||||
doTrigger(options: { pipelineId: number }): Promise<void>;
|
||||
doSave(pipelineConfig: Pipeline): Promise<void>;
|
||||
getPipelineDetail(query: { pipelineId: number }): Promise<PipelineDetail>;
|
||||
getHistoryList(query: { pipelineId: number }): Promise<RunHistory[]>;
|
||||
getHistoryDetail(query: { historyId: number }): Promise<RunHistory>;
|
||||
getPlugins(): Promise<Pipeline[]>;
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
CREATE TABLE "pi_history" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "user_id" integer NOT NULL, "pipeline_id" integer NOT NULL, "pipeline" varchar(40960), "status" varchar(20), "end_time" datetime, "create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP), "update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP))
|
||||
|
||||
CREATE TABLE "pi_history_log" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "user_id" integer NOT NULL, "pipeline_id" integer NOT NULL, "history_id" integer NOT NULL, "node_id" varchar(100), "logs" varchar(40960), "create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP), "update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP))
|
||||
|
||||
CREATE TABLE "pi_pipeline" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "user_id" integer NOT NULL, "title" integer NOT NULL, "content" varchar(40960) NOT NULL, "keep_history_count" integer, "remark" varchar(100), "status" varchar(100), "disabled" boolean DEFAULT (0), "last_history_time" integer, "create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP), "update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP))
|
||||
|
||||
CREATE TABLE "pi_storage" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "user_id" integer NOT NULL, "scope" varchar NOT NULL, "namespace" varchar NOT NULL, "key" varchar(100), "value" varchar(40960), "create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP), "update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP))
|
|
@ -24,6 +24,7 @@
|
|||
"@alicloud/pop-core": "^1.7.12",
|
||||
"@certd/pipeline": "workspace:^0.3.0",
|
||||
"@certd/plugin-all": "workspace:^0.3.0",
|
||||
"@certd/plugin-cert": "workspace:^0.3.0",
|
||||
"@koa/cors": "^3.4.3",
|
||||
"@midwayjs/bootstrap": "^3.9.1",
|
||||
"@midwayjs/cache": "^3.9.0",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { ALL, Body, Post, Query } from "@midwayjs/decorator";
|
||||
import { BaseController } from "./base-controller";
|
||||
import { ALL, Body, Post, Query } from '@midwayjs/decorator';
|
||||
import { BaseController } from './base-controller';
|
||||
|
||||
export abstract class CrudController extends BaseController {
|
||||
abstract getService();
|
||||
export abstract class CrudController<T> extends BaseController {
|
||||
abstract getService<T>();
|
||||
|
||||
@Post('/page')
|
||||
async page(
|
||||
|
@ -62,4 +62,3 @@ export abstract class CrudController extends BaseController {
|
|||
return this.ok(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,11 +33,7 @@ export default {
|
|||
logging: true,
|
||||
|
||||
// 配置实体模型 或者 entities: '/entity',
|
||||
entities: [
|
||||
'**/modules/*/entity/*.ts',
|
||||
FlywayHistory,
|
||||
UserEntity,
|
||||
],
|
||||
entities: ['**/modules/*/entity/*.ts', FlywayHistory, UserEntity],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -6,20 +6,19 @@ import { Configuration, App } from '@midwayjs/decorator';
|
|||
import * as koa from '@midwayjs/koa';
|
||||
import * as orm from '@midwayjs/typeorm';
|
||||
import * as cache from '@midwayjs/cache';
|
||||
import * as cors from '@koa/cors';
|
||||
import cors from '@koa/cors';
|
||||
import { join } from 'path';
|
||||
import * as flyway from 'midway-flyway-js';
|
||||
import {ReportMiddleware} from "./middleware/report";
|
||||
import {GlobalExceptionMiddleware} from "./middleware/global-exception";
|
||||
import {PreviewMiddleware} from "./middleware/preview";
|
||||
import {AuthorityMiddleware} from "./middleware/authority";
|
||||
|
||||
import { ReportMiddleware } from './middleware/report';
|
||||
import { GlobalExceptionMiddleware } from './middleware/global-exception';
|
||||
import { PreviewMiddleware } from './middleware/preview';
|
||||
import { AuthorityMiddleware } from './middleware/authority';
|
||||
|
||||
import * as pipeline from './plugins/pipeline';
|
||||
import * as cron from './plugins/cron';
|
||||
|
||||
@Configuration({
|
||||
imports: [koa, orm, cache, flyway, validateComp,pipeline, cron],
|
||||
imports: [koa, orm, cache, flyway, validateComp, pipeline, cron],
|
||||
importConfigs: [
|
||||
{
|
||||
default: defaultConfig,
|
||||
|
|
|
@ -60,4 +60,3 @@ export class PermissionController extends CrudController<PermissionService> {
|
|||
return this.ok(tree);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import { InjectEntityModel } from '@midwayjs/typeorm';
|
|||
import { Repository } from 'typeorm';
|
||||
import { UserEntity } from '../entity/user';
|
||||
import * as _ from 'lodash';
|
||||
import * as md5 from 'md5';
|
||||
import md5 from 'md5';
|
||||
import { CommonException } from '../../../basic/exception/common-exception';
|
||||
import { BaseService } from '../../../basic/base-service';
|
||||
import { logger } from '../../../utils/logger';
|
||||
|
@ -36,7 +36,7 @@ export class UserService extends BaseService<UserEntity> {
|
|||
const info = await this.repository.findOne({
|
||||
where: {
|
||||
id: this.ctx.user.id,
|
||||
}
|
||||
},
|
||||
});
|
||||
delete info.password;
|
||||
return info;
|
||||
|
@ -48,9 +48,9 @@ export class UserService extends BaseService<UserEntity> {
|
|||
*/
|
||||
async add(param) {
|
||||
const exists = await this.repository.findOne({
|
||||
where:{
|
||||
where: {
|
||||
username: param.username,
|
||||
}
|
||||
},
|
||||
});
|
||||
if (!_.isEmpty(exists)) {
|
||||
throw new CommonException('用户名已经存在');
|
||||
|
@ -74,7 +74,7 @@ export class UserService extends BaseService<UserEntity> {
|
|||
throw new CommonException('id不能为空');
|
||||
}
|
||||
const userInfo = await this.repository.findOne({
|
||||
where:{ id: param.id }
|
||||
where: { id: param.id },
|
||||
});
|
||||
if (!userInfo) {
|
||||
throw new CommonException('用户不存在');
|
||||
|
@ -92,7 +92,7 @@ export class UserService extends BaseService<UserEntity> {
|
|||
|
||||
async findOne(param) {
|
||||
return this.repository.findOne({
|
||||
where:param
|
||||
where: param,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import { AccessService } from '../service/access-service';
|
|||
*/
|
||||
@Provide()
|
||||
@Controller('/api/pi/access')
|
||||
export class AccessController extends CrudController {
|
||||
export class AccessController extends CrudController<AccessService> {
|
||||
@Inject()
|
||||
service: AccessService;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import { HistoryLogEntity } from '../entity/history-log';
|
|||
*/
|
||||
@Provide()
|
||||
@Controller('/api/pi/history')
|
||||
export class HistoryController extends CrudController {
|
||||
export class HistoryController extends CrudController<HistoryService> {
|
||||
@Inject()
|
||||
service: HistoryService;
|
||||
@Inject()
|
||||
|
|
|
@ -16,7 +16,7 @@ import { PipelineEntity } from '../entity/pipeline';
|
|||
*/
|
||||
@Provide()
|
||||
@Controller('/api/pi/pipeline')
|
||||
export class PipelineController extends CrudController {
|
||||
export class PipelineController extends CrudController<PipelineService> {
|
||||
@Inject()
|
||||
service: PipelineService;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Provide, Scope, ScopeEnum } from "@midwayjs/decorator";
|
||||
import { Provide, Scope, ScopeEnum } from '@midwayjs/decorator';
|
||||
import { dnsProviderRegistry } from '@certd/plugin-cert';
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
|
|
|
@ -139,9 +139,9 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||
if (cron == null) {
|
||||
return;
|
||||
}
|
||||
if(cron.startsWith("*")){
|
||||
cron = "0"+ cron.substring(1,cron.length)
|
||||
return
|
||||
if (cron.startsWith('*')) {
|
||||
cron = '0' + cron.substring(1, cron.length);
|
||||
return;
|
||||
}
|
||||
this.cron.register({
|
||||
name: this.buildCronKey(pipelineId, trigger.id),
|
||||
|
@ -168,7 +168,17 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||
|
||||
const onChanged = async (history: RunHistory) => {
|
||||
//保存执行历史
|
||||
await this.saveHistory(history);
|
||||
try {
|
||||
await this.saveHistory(history);
|
||||
} catch (e) {
|
||||
const pipelineEntity = new PipelineEntity();
|
||||
pipelineEntity.id = parseInt(history.pipeline.id);
|
||||
pipelineEntity.status = 'error';
|
||||
pipelineEntity.lastHistoryTime = history.pipeline.status.startTime;
|
||||
await this.update(pipelineEntity);
|
||||
logger.error('保存执行历史失败:', e);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
const userId = entity.userId;
|
||||
|
@ -228,6 +238,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||
entity.id = parseInt(history.id);
|
||||
entity.userId = history.pipeline.userId;
|
||||
entity.pipeline = JSON.stringify(history.pipeline);
|
||||
entity.pipelineId = parseInt(history.pipeline.id);
|
||||
await this.historyService.save(entity);
|
||||
|
||||
const logEntity: HistoryLogEntity = new HistoryLogEntity();
|
||||
|
|
Loading…
Reference in New Issue