mirror of
https://github.com/certd/certd.git
synced 2026-05-01 02:17:27 +08:00
perf: 支持webhook触发流水线,新增触发类型图标显示
This commit is contained in:
@@ -352,6 +352,7 @@ export default {
|
|||||||
editSchedule: "修改定时",
|
editSchedule: "修改定时",
|
||||||
timerTrigger: "定时触发",
|
timerTrigger: "定时触发",
|
||||||
schedule: "定时",
|
schedule: "定时",
|
||||||
|
webhook: "Webhook",
|
||||||
selectCron: "请选择定时Cron",
|
selectCron: "请选择定时Cron",
|
||||||
batchEditSchedule: "批量修改定时",
|
batchEditSchedule: "批量修改定时",
|
||||||
editTrigger: "编辑触发器",
|
editTrigger: "编辑触发器",
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ const pipelineOptions: PipelineOptions = {
|
|||||||
from: detail.pipeline.from,
|
from: detail.pipeline.from,
|
||||||
},
|
},
|
||||||
validTime: detail.pipeline.validTime,
|
validTime: detail.pipeline.validTime,
|
||||||
|
webhookKey: detail.pipeline.webhookKey,
|
||||||
|
id: detail.pipeline.id,
|
||||||
} as PipelineDetail;
|
} as PipelineDetail;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="title">{{ t("certd.myPipelines") }}</div>
|
<div class="title">{{ t("certd.myPipelines") }}</div>
|
||||||
</template>
|
</template>
|
||||||
<a-alert v-if="settingStore.sysPublic.notice" type="warning" show-icon>
|
<!-- <a-alert v-if="settingStore.sysPublic.notice" type="warning" show-icon>
|
||||||
<template #message>
|
<template #message>
|
||||||
{{ settingStore.sysPublic.notice }}
|
{{ settingStore.sysPublic.notice }}
|
||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert> -->
|
||||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
<div v-if="selectedRowKeys.length > 0" class="batch-actions">
|
<div v-if="selectedRowKeys.length > 0" class="batch-actions">
|
||||||
<div class="batch-actions-inner">
|
<div class="batch-actions-inner">
|
||||||
|
|||||||
+6
@@ -4,6 +4,7 @@
|
|||||||
<fs-icon v-bind="status" :color="status.iconColor || status.color" />
|
<fs-icon v-bind="status" :color="status.iconColor || status.color" />
|
||||||
</template>
|
</template>
|
||||||
<p class="flex items-center">
|
<p class="flex items-center">
|
||||||
|
<TriggerIcon class="mr-2" :trigger-type="runnable.triggerType"></TriggerIcon>
|
||||||
<fs-date-format :model-value="runnable.createTime"></fs-date-format>
|
<fs-date-format :model-value="runnable.createTime"></fs-date-format>
|
||||||
<a-tag class="ml-5" :color="status.color" :closable="status.value === 'start'" @close="cancelTask">
|
<a-tag class="ml-5" :color="status.color" :closable="status.value === 'start'" @close="cancelTask">
|
||||||
{{ status.label }}
|
{{ status.label }}
|
||||||
@@ -19,8 +20,12 @@ import { defineComponent, ref, provide, Ref, watch, computed } from "vue";
|
|||||||
import { statusUtil } from "/@/views/certd/pipeline/pipeline/utils/util.status";
|
import { statusUtil } from "/@/views/certd/pipeline/pipeline/utils/util.status";
|
||||||
import * as api from "../../api";
|
import * as api from "../../api";
|
||||||
import { Modal, notification } from "ant-design-vue";
|
import { Modal, notification } from "ant-design-vue";
|
||||||
|
import TriggerIcon from "./trigger-icon.vue";
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "PiHistoryTimelineItem",
|
name: "PiHistoryTimelineItem",
|
||||||
|
components: {
|
||||||
|
TriggerIcon,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
runnable: {
|
runnable: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -69,6 +74,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status,
|
status,
|
||||||
cancel,
|
cancel,
|
||||||
|
|||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
|
const apiPrefix = "/pi/pipeline";
|
||||||
|
|
||||||
|
export async function RefreshWebhookKey(form: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/refreshWebhookKey",
|
||||||
|
method: "post",
|
||||||
|
data: form,
|
||||||
|
});
|
||||||
|
}
|
||||||
+50
-34
@@ -13,6 +13,25 @@
|
|||||||
<template v-if="currentTrigger">
|
<template v-if="currentTrigger">
|
||||||
<pi-container>
|
<pi-container>
|
||||||
<a-form ref="triggerFormRef" class="trigger-form" :model="currentTrigger" :label-col="labelCol" :wrapper-col="wrapperCol">
|
<a-form ref="triggerFormRef" class="trigger-form" :model="currentTrigger" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||||
|
<fs-form-item
|
||||||
|
:model-value="currentTrigger.type"
|
||||||
|
:item="{
|
||||||
|
title: t('certd.type'),
|
||||||
|
key: 'type',
|
||||||
|
value: 'timer',
|
||||||
|
component: {
|
||||||
|
name: 'a-select',
|
||||||
|
vModel: 'value',
|
||||||
|
disabled: !editMode,
|
||||||
|
options: [
|
||||||
|
{ value: 'timer', label: t('certd.schedule') },
|
||||||
|
{ value: 'webhook', label: t('certd.webhook') },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
rules: [{ required: true, message: t('certd.requiredField') }],
|
||||||
|
}"
|
||||||
|
@update:model-value="typeValueChange($event)"
|
||||||
|
/>
|
||||||
<fs-form-item
|
<fs-form-item
|
||||||
v-model="currentTrigger.title"
|
v-model="currentTrigger.title"
|
||||||
:item="{
|
:item="{
|
||||||
@@ -27,36 +46,8 @@
|
|||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<fs-form-item
|
<timer-form v-if="currentTrigger.type === 'timer'" :edit-mode="editMode" />
|
||||||
v-model="currentTrigger.type"
|
<webhook-form v-if="currentTrigger.type === 'webhook'" :edit-mode="editMode" />
|
||||||
:item="{
|
|
||||||
title: t('certd.type'),
|
|
||||||
key: 'type',
|
|
||||||
value: 'timer',
|
|
||||||
component: {
|
|
||||||
name: 'a-select',
|
|
||||||
vModel: 'value',
|
|
||||||
disabled: !editMode,
|
|
||||||
options: [{ value: 'timer', label: t('certd.schedule') }],
|
|
||||||
},
|
|
||||||
rules: [{ required: true, message: t('certd.requiredField') }],
|
|
||||||
}"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<fs-form-item
|
|
||||||
v-model="currentTrigger.props.cron"
|
|
||||||
:item="{
|
|
||||||
title: t('certd.cronForm.title'),
|
|
||||||
key: 'props.cron',
|
|
||||||
component: {
|
|
||||||
disabled: !editMode,
|
|
||||||
name: 'cron-editor',
|
|
||||||
vModel: 'modelValue',
|
|
||||||
},
|
|
||||||
helper: t('certd.cronForm.helper'),
|
|
||||||
rules: [{ required: true, message: t('certd.cronForm.required') }],
|
|
||||||
}"
|
|
||||||
/>
|
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -70,13 +61,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { message, Modal } from "ant-design-vue";
|
import { Modal } from "ant-design-vue";
|
||||||
import { inject, ref } from "vue";
|
|
||||||
import * as _ from "lodash-es";
|
import * as _ from "lodash-es";
|
||||||
import { useI18n } from "/src/locales/";
|
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
|
import { ref, provide } from "vue";
|
||||||
|
import { useI18n } from "/src/locales/";
|
||||||
|
import TimerForm from "./timer-form.vue";
|
||||||
|
import WebhookForm from "./webhook-form.vue";
|
||||||
export default {
|
export default {
|
||||||
name: "PiTriggerForm",
|
name: "PiTriggerForm",
|
||||||
|
components: {
|
||||||
|
TimerForm,
|
||||||
|
WebhookForm,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
editMode: {
|
editMode: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@@ -94,6 +91,7 @@ export default {
|
|||||||
const mode = ref("add");
|
const mode = ref("add");
|
||||||
const callback = ref();
|
const callback = ref();
|
||||||
const currentTrigger = ref({ title: undefined, input: {} });
|
const currentTrigger = ref({ title: undefined, input: {} });
|
||||||
|
provide("trigger:get", () => currentTrigger);
|
||||||
const currentPlugin = ref({});
|
const currentPlugin = ref({});
|
||||||
const triggerFormRef = ref(null);
|
const triggerFormRef = ref(null);
|
||||||
const triggerDrawerVisible = ref(false);
|
const triggerDrawerVisible = ref(false);
|
||||||
@@ -125,9 +123,13 @@ export default {
|
|||||||
triggerDrawerShow();
|
triggerDrawerShow();
|
||||||
};
|
};
|
||||||
|
|
||||||
const triggerAdd = emit => {
|
const triggerAdd = (triggerType, emit) => {
|
||||||
mode.value = "add";
|
mode.value = "add";
|
||||||
const trigger = { id: nanoid(), title: t("certd.timerTrigger"), type: "timer", props: {} };
|
const trigger = { id: nanoid(), title: t("certd.timerTrigger"), type: "timer", props: {} };
|
||||||
|
if (triggerType === "webhook") {
|
||||||
|
trigger.type = "webhook";
|
||||||
|
trigger.title = "Webhook触发";
|
||||||
|
}
|
||||||
triggerOpen(trigger, emit);
|
triggerOpen(trigger, emit);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -168,6 +170,19 @@ export default {
|
|||||||
const blankFn = () => {
|
const blankFn = () => {
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function typeValueChange(value) {
|
||||||
|
if (value === "webhook") {
|
||||||
|
if (currentTrigger.value.title === "定时触发" || !currentTrigger.value.title) {
|
||||||
|
currentTrigger.value.title = "Webhook触发";
|
||||||
|
}
|
||||||
|
} else if (value === "timer") {
|
||||||
|
if (currentTrigger.value.title === "Webhook触发" || !currentTrigger.value.title) {
|
||||||
|
currentTrigger.value.title = "定时触发";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentTrigger.value.type = value;
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
triggerFormRef,
|
triggerFormRef,
|
||||||
mode,
|
mode,
|
||||||
@@ -183,6 +198,7 @@ export default {
|
|||||||
triggerDelete,
|
triggerDelete,
|
||||||
rules,
|
rules,
|
||||||
blankFn,
|
blankFn,
|
||||||
|
typeValueChange,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<fs-form-item
|
||||||
|
v-model="trigger.props.cron"
|
||||||
|
:item="{
|
||||||
|
title: t('certd.cronForm.title'),
|
||||||
|
key: 'props.cron',
|
||||||
|
component: {
|
||||||
|
disabled: !editMode,
|
||||||
|
name: 'cron-editor',
|
||||||
|
vModel: 'modelValue',
|
||||||
|
},
|
||||||
|
helper: t('certd.cronForm.helper'),
|
||||||
|
rules: [{ required: true, message: t('certd.cronForm.required') }],
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="tsx" setup>
|
||||||
|
import { inject } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "TimerForm",
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
editMode: boolean;
|
||||||
|
}>();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const triggerGetter: any = inject("trigger:get");
|
||||||
|
const trigger = triggerGetter();
|
||||||
|
</script>
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-form-item label="Webhook URL">
|
||||||
|
<div class="flex flex-col h-8 border-dashed border-2 rounded-md p-1">
|
||||||
|
<fs-copyable :model-value="webhookUrl" class="flex-1 overflow-hidden"></fs-copyable>
|
||||||
|
</div>
|
||||||
|
<a-button class="mt-2" type="primary" size="small" @click="refreshWebhookKey">重新生成</a-button>
|
||||||
|
<div class="helper">支持post和get请求</div>
|
||||||
|
</a-form-item>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="tsx" setup>
|
||||||
|
import { Modal } from "ant-design-vue";
|
||||||
|
import { computed, inject, onMounted } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import * as api from "./api";
|
||||||
|
defineOptions({
|
||||||
|
name: "WebhookForm",
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
editMode: boolean;
|
||||||
|
}>();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const pipelineDetailGetter: any = inject("pipelineDetail:get");
|
||||||
|
const webhookUrl = computed(() => {
|
||||||
|
const detailRef = pipelineDetailGetter();
|
||||||
|
return `${window.location.origin}/api/webhook/${detailRef?.value?.webhookKey}`;
|
||||||
|
});
|
||||||
|
onMounted(() => {
|
||||||
|
const detailRef = pipelineDetailGetter();
|
||||||
|
if (!detailRef.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!detailRef.value.webhookKey) {
|
||||||
|
doRefreshWebhookKey();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const refreshWebhookKey = () => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "确认重新生成Webhook URL吗?",
|
||||||
|
okText: "确认",
|
||||||
|
okType: "danger",
|
||||||
|
onOk: async () => {
|
||||||
|
await doRefreshWebhookKey();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
async function doRefreshWebhookKey() {
|
||||||
|
const detailRef = pipelineDetailGetter();
|
||||||
|
const res = await api.RefreshWebhookKey({
|
||||||
|
id: detailRef.value.id,
|
||||||
|
});
|
||||||
|
detailRef.value.webhookKey = res.webhookKey;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<template>
|
||||||
|
<fs-icon v-bind="triggerTypeIconBind" />
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "TriggerIcon",
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
triggerType: {
|
||||||
|
type: String,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const triggerTypeIconBind = computed(() => {
|
||||||
|
const triggerType = props.triggerType;
|
||||||
|
let icon = "hugeicons:tap-05:#ff9900";
|
||||||
|
let title = "手动触发";
|
||||||
|
if (triggerType === "webhook") {
|
||||||
|
icon = "mdi:link-variant:blue";
|
||||||
|
title = "Webhook 触发";
|
||||||
|
} else if (triggerType === "timer") {
|
||||||
|
icon = "mdi:schedule:green";
|
||||||
|
title = "定时器触发";
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
icon,
|
||||||
|
title,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -28,10 +28,10 @@
|
|||||||
未设置触发源,不会自动执行
|
未设置触发源,不会自动执行
|
||||||
</span>
|
</span>
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<a-tag v-if="pipelineEntity.validTime > 0 && settingStore.sysPublic.pipelineValidTimeEnabled && settingStore.isPlus" :color="pipelineEntity.validTime > Date.now() ? 'green' : 'red'">
|
<a-tag v-if="pipelineDetail.validTime > 0 && settingStore.sysPublic.pipelineValidTimeEnabled && settingStore.isPlus" :color="pipelineDetail.validTime > Date.now() ? 'green' : 'red'">
|
||||||
<span class="flex">
|
<span class="flex">
|
||||||
<fs-icon icon="ion:time-outline"></fs-icon>
|
<fs-icon icon="ion:time-outline"></fs-icon>
|
||||||
<span v-if="pipelineEntity.validTime > Date.now()"> 有效期:<FsTimeHumanize :model-value="pipelineEntity.validTime" :options="{ units: ['d'] }" format="YYYY-MM-DD"></FsTimeHumanize> </span>
|
<span v-if="pipelineDetail.validTime > Date.now()"> 有效期:<FsTimeHumanize :model-value="pipelineDetail.validTime" :options="{ units: ['d'] }" format="YYYY-MM-DD"></FsTimeHumanize> </span>
|
||||||
<span v-else> 已过期 </span>
|
<span v-else> 已过期 </span>
|
||||||
</span>
|
</span>
|
||||||
</a-tag>
|
</a-tag>
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="task">
|
<div class="task">
|
||||||
<a-button shape="round" @click="triggerEdit(trigger, index)">
|
<a-button shape="round" @click="triggerEdit(trigger, index)">
|
||||||
<fs-icon icon="ion:time"></fs-icon>
|
<TriggerIcon class="mr-2" :trigger-type="trigger.type"></TriggerIcon>
|
||||||
{{ trigger.title }}
|
{{ trigger.title }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -93,6 +93,17 @@
|
|||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="editMode" class="task-container is-add">
|
||||||
|
<div class="line line-right">
|
||||||
|
<div class="flow-line"></div>
|
||||||
|
</div>
|
||||||
|
<div class="task">
|
||||||
|
<a-button shape="round" type="dashed" @click="triggerAdd('webhook')">
|
||||||
|
<fs-icon icon="ion:add-circle-outline"></fs-icon>
|
||||||
|
触发源(Webhook)
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -126,8 +137,8 @@
|
|||||||
<a-popover title="步骤" :trigger="editMode ? 'none' : 'hover'">
|
<a-popover title="步骤" :trigger="editMode ? 'none' : 'hover'">
|
||||||
<!-- :open="true"-->
|
<!-- :open="true"-->
|
||||||
<template #content>
|
<template #content>
|
||||||
<div v-for="(item, index) of task.steps" :key="item.id" class="flex-o w-100">
|
<div v-for="(item, stepIndex) of task.steps" :key="item.id" class="flex-o w-100">
|
||||||
<span class="ellipsis flex-1 step-title" :class="{ disabled: item.disabled, deleted: item.disabled }"> {{ index + 1 }}. {{ item.title }} </span>
|
<span class="ellipsis flex-1 step-title" :class="{ disabled: item.disabled, deleted: item.disabled }"> {{ stepIndex + 1 }}. {{ item.title }} </span>
|
||||||
<pi-status-show v-if="!editMode" :status="item.status?.result"></pi-status-show>
|
<pi-status-show v-if="!editMode" :status="item.status?.result"></pi-status-show>
|
||||||
<a-tooltip title="强制重新执行此步骤">
|
<a-tooltip title="强制重新执行此步骤">
|
||||||
<fs-icon v-if="!editMode" class="pointer color-blue ml-2" style="font-size: 16px" title="强制重新执行此步骤" icon="icon-park-outline:replay-music" @click="run(item.id)"></fs-icon>
|
<fs-icon v-if="!editMode" class="pointer color-blue ml-2" style="font-size: 16px" title="强制重新执行此步骤" icon="icon-park-outline:replay-music" @click="run(item.id)"></fs-icon>
|
||||||
@@ -310,6 +321,7 @@ import { usePluginStore } from "/@/store/plugin";
|
|||||||
import { getCronNextTimes } from "/@/components/cron-editor/utils";
|
import { getCronNextTimes } from "/@/components/cron-editor/utils";
|
||||||
import { useCertViewer } from "/@/views/certd/pipeline/use";
|
import { useCertViewer } from "/@/views/certd/pipeline/use";
|
||||||
import { useI18n } from "/@/locales";
|
import { useI18n } from "/@/locales";
|
||||||
|
import TriggerIcon from "./component/trigger-icon.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "PipelineEdit",
|
name: "PipelineEdit",
|
||||||
@@ -324,6 +336,7 @@ export default defineComponent({
|
|||||||
PiNotificationForm,
|
PiNotificationForm,
|
||||||
VDraggable,
|
VDraggable,
|
||||||
TaskShortcuts,
|
TaskShortcuts,
|
||||||
|
TriggerIcon,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
pipelineId: {
|
pipelineId: {
|
||||||
@@ -351,7 +364,7 @@ export default defineComponent({
|
|||||||
//右侧选中的pipeline
|
//右侧选中的pipeline
|
||||||
const currentPipeline: Ref<any> = ref({});
|
const currentPipeline: Ref<any> = ref({});
|
||||||
const pipeline: Ref<any> = ref({});
|
const pipeline: Ref<any> = ref({});
|
||||||
const pipelineEntity: Ref<any> = ref({});
|
const pipelineDetail: Ref<any> = ref({});
|
||||||
const histories: Ref<RunHistory[]> = ref([]);
|
const histories: Ref<RunHistory[]> = ref([]);
|
||||||
|
|
||||||
const currentHistory: Ref<any> = ref({});
|
const currentHistory: Ref<any> = ref({});
|
||||||
@@ -400,7 +413,7 @@ export default defineComponent({
|
|||||||
currentPipeline.value = currentHistory.value.pipeline;
|
currentPipeline.value = currentHistory.value.pipeline;
|
||||||
};
|
};
|
||||||
|
|
||||||
async function loadHistoryList(reload = false, historyId: number) {
|
async function loadHistoryList(reload = false, historyId: number = null) {
|
||||||
if (props.editMode) {
|
if (props.editMode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -499,7 +512,7 @@ export default defineComponent({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const detail: PipelineDetail = await props.options.getPipelineDetail({ pipelineId: value });
|
const detail: PipelineDetail = await props.options.getPipelineDetail({ pipelineId: value });
|
||||||
pipelineEntity.value = detail;
|
pipelineDetail.value = detail;
|
||||||
currentPipeline.value = merge(
|
currentPipeline.value = merge(
|
||||||
{
|
{
|
||||||
title: "新管道流程",
|
title: "新管道流程",
|
||||||
@@ -523,6 +536,7 @@ export default defineComponent({
|
|||||||
};
|
};
|
||||||
fetchPlugins();
|
fetchPlugins();
|
||||||
|
|
||||||
|
provide("pipelineDetail:get", () => pipelineDetail);
|
||||||
provide("pipeline", pipeline);
|
provide("pipeline", pipeline);
|
||||||
provide("getPluginGroups", () => {
|
provide("getPluginGroups", () => {
|
||||||
return pluginStore.group;
|
return pluginStore.group;
|
||||||
@@ -631,8 +645,8 @@ export default defineComponent({
|
|||||||
|
|
||||||
function useTrigger() {
|
function useTrigger() {
|
||||||
const triggerFormRef: Ref<any> = ref(null);
|
const triggerFormRef: Ref<any> = ref(null);
|
||||||
const triggerAdd = () => {
|
const triggerAdd = (triggerType = "timer") => {
|
||||||
triggerFormRef.value.triggerAdd((type: string, value: any) => {
|
triggerFormRef.value.triggerAdd(triggerType, (type: string, value: any) => {
|
||||||
if (type === "save") {
|
if (type === "save") {
|
||||||
pipeline.value.triggers.push(value);
|
pipeline.value.triggers.push(value);
|
||||||
}
|
}
|
||||||
@@ -988,7 +1002,7 @@ export default defineComponent({
|
|||||||
nextTriggerTimes,
|
nextTriggerTimes,
|
||||||
viewCert,
|
viewCert,
|
||||||
downloadCert,
|
downloadCert,
|
||||||
pipelineEntity,
|
pipelineDetail,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { PluginGroups } from "/@/store/plugin";
|
|||||||
export type PipelineDetail = {
|
export type PipelineDetail = {
|
||||||
pipeline: Pipeline;
|
pipeline: Pipeline;
|
||||||
validTime?: number;
|
validTime?: number;
|
||||||
|
webhookKey?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RunHistory = {
|
export type RunHistory = {
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
ALTER TABLE cd_site_info ADD COLUMN ip_scan boolean DEFAULT (0);
|
ALTER TABLE cd_site_info ADD COLUMN ip_scan boolean DEFAULT (0);
|
||||||
|
|
||||||
ALTER TABLE pi_pipeline ADD COLUMN webhook_key varchar(100);
|
ALTER TABLE pi_pipeline ADD COLUMN webhook_key varchar(100);
|
||||||
|
ALTER TABLE pi_pipeline ADD COLUMN trigger_count integer DEFAULT (0);
|
||||||
|
|
||||||
|
CREATE INDEX "index_pipeline_webhook_key" ON "pi_pipeline" ("webhook_key");
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { BaseController, Constants } from '@certd/lib-server';
|
||||||
|
import { Controller, Get, Inject, Param, Post, Provide } from '@midwayjs/core';
|
||||||
|
import { PipelineService } from '../../modules/pipeline/service/pipeline-service.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Provide()
|
||||||
|
@Controller('/api/webhook/')
|
||||||
|
export class WebhookController extends BaseController {
|
||||||
|
@Inject()
|
||||||
|
pipelineService: PipelineService;
|
||||||
|
|
||||||
|
@Get('/:webhookKey', { summary: Constants.per.guest })
|
||||||
|
@Post('/:webhookKey', { summary: Constants.per.guest })
|
||||||
|
async webhook(@Param('webhookKey') webhookKey: string): Promise<any> {
|
||||||
|
await this.pipelineService.triggerByWebhook(webhookKey);
|
||||||
|
return this.ok({});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,18 +35,18 @@ export class PipelineController extends CrudController<PipelineService> {
|
|||||||
const publicSettings = await this.sysSettingsService.getPublicSettings();
|
const publicSettings = await this.sysSettingsService.getPublicSettings();
|
||||||
|
|
||||||
let onlyOther = false
|
let onlyOther = false
|
||||||
if(isAdmin){
|
if (isAdmin) {
|
||||||
if(publicSettings.managerOtherUserPipeline){
|
if (publicSettings.managerOtherUserPipeline) {
|
||||||
//管理员管理 其他用户
|
//管理员管理 其他用户
|
||||||
if( body.query.userId === -1){
|
if (body.query.userId === -1) {
|
||||||
//如果只查询其他用户
|
//如果只查询其他用户
|
||||||
onlyOther = true;
|
onlyOther = true;
|
||||||
delete body.query.userId;
|
delete body.query.userId;
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
body.query.userId = this.getUserId();
|
body.query.userId = this.getUserId();
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
body.query.userId = this.getUserId();
|
body.query.userId = this.getUserId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ export class PipelineController extends CrudController<PipelineService> {
|
|||||||
if (title) {
|
if (title) {
|
||||||
qb.andWhere('(title like :title or content like :content)', { title: `%${title}%`, content: `%${title}%` });
|
qb.andWhere('(title like :title or content like :content)', { title: `%${title}%`, content: `%${title}%` });
|
||||||
}
|
}
|
||||||
if(onlyOther){
|
if (onlyOther) {
|
||||||
qb.andWhere('user_id != :userId', { userId: this.getUserId() });
|
qb.andWhere('user_id != :userId', { userId: this.getUserId() });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -76,7 +76,7 @@ export class PipelineController extends CrudController<PipelineService> {
|
|||||||
|
|
||||||
@Post('/getSimpleByIds', { summary: Constants.per.authOnly })
|
@Post('/getSimpleByIds', { summary: Constants.per.authOnly })
|
||||||
async getSimpleById(@Body(ALL) body) {
|
async getSimpleById(@Body(ALL) body) {
|
||||||
const ret = await this.getService().getSimplePipelines(body.ids,this.getUserId() );
|
const ret = await this.getService().getSimplePipelines(body.ids, this.getUserId());
|
||||||
return this.ok(ret);
|
return this.ok(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,19 +95,19 @@ export class PipelineController extends CrudController<PipelineService> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Post('/save', { summary: Constants.per.authOnly })
|
@Post('/save', { summary: Constants.per.authOnly })
|
||||||
async save(@Body(ALL) bean: {addToMonitorEnabled: boolean, addToMonitorDomains: string} & PipelineEntity) {
|
async save(@Body(ALL) bean: { addToMonitorEnabled: boolean, addToMonitorDomains: string } & PipelineEntity) {
|
||||||
if (bean.id > 0) {
|
if (bean.id > 0) {
|
||||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id);
|
await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id);
|
||||||
} else {
|
} else {
|
||||||
bean.userId = this.getUserId();
|
bean.userId = this.getUserId();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.isAdmin()){
|
if (!this.isAdmin()) {
|
||||||
// 非管理员用户 不允许设置流水线有效期
|
// 非管理员用户 不允许设置流水线有效期
|
||||||
delete bean.validTime
|
delete bean.validTime
|
||||||
}
|
}
|
||||||
|
|
||||||
const {version} = await this.service.save(bean);
|
const { version } = await this.service.save(bean);
|
||||||
//是否增加证书监控
|
//是否增加证书监控
|
||||||
if (bean.addToMonitorEnabled && bean.addToMonitorDomains) {
|
if (bean.addToMonitorEnabled && bean.addToMonitorDomains) {
|
||||||
const sysPublicSettings = await this.sysSettingsService.getPublicSettings();
|
const sysPublicSettings = await this.sysSettingsService.getPublicSettings();
|
||||||
@@ -119,7 +119,7 @@ export class PipelineController extends CrudController<PipelineService> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.ok({id:bean.id,version:version});
|
return this.ok({ id: bean.id, version: version });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/delete', { summary: Constants.per.authOnly })
|
@Post('/delete', { summary: Constants.per.authOnly })
|
||||||
@@ -147,7 +147,7 @@ export class PipelineController extends CrudController<PipelineService> {
|
|||||||
@Post('/trigger', { summary: Constants.per.authOnly })
|
@Post('/trigger', { summary: Constants.per.authOnly })
|
||||||
async trigger(@Query('id') id: number, @Query('stepId') stepId?: string) {
|
async trigger(@Query('id') id: number, @Query('stepId') stepId?: string) {
|
||||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
|
await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
|
||||||
await this.service.trigger(id, stepId,true);
|
await this.service.trigger(id, stepId, true);
|
||||||
return this.ok({});
|
return this.ok({});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ export class PipelineController extends CrudController<PipelineService> {
|
|||||||
@Post('/batchDelete', { summary: Constants.per.authOnly })
|
@Post('/batchDelete', { summary: Constants.per.authOnly })
|
||||||
async batchDelete(@Body('ids') ids: number[]) {
|
async batchDelete(@Body('ids') ids: number[]) {
|
||||||
const isAdmin = await this.authService.isAdmin(this.ctx);
|
const isAdmin = await this.authService.isAdmin(this.ctx);
|
||||||
const userId = isAdmin ? undefined : this.getUserId() ;
|
const userId = isAdmin ? undefined : this.getUserId();
|
||||||
await this.service.batchDelete(ids, userId);
|
await this.service.batchDelete(ids, userId);
|
||||||
return this.ok({});
|
return this.ok({});
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,7 @@ export class PipelineController extends CrudController<PipelineService> {
|
|||||||
@Post('/batchUpdateGroup', { summary: Constants.per.authOnly })
|
@Post('/batchUpdateGroup', { summary: Constants.per.authOnly })
|
||||||
async batchUpdateGroup(@Body('ids') ids: number[], @Body('groupId') groupId: number) {
|
async batchUpdateGroup(@Body('ids') ids: number[], @Body('groupId') groupId: number) {
|
||||||
const isAdmin = await this.authService.isAdmin(this.ctx);
|
const isAdmin = await this.authService.isAdmin(this.ctx);
|
||||||
const userId = isAdmin ? undefined : this.getUserId() ;
|
const userId = isAdmin ? undefined : this.getUserId();
|
||||||
await this.service.batchUpdateGroup(ids, groupId, userId);
|
await this.service.batchUpdateGroup(ids, groupId, userId);
|
||||||
return this.ok({});
|
return this.ok({});
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ export class PipelineController extends CrudController<PipelineService> {
|
|||||||
@Post('/batchUpdateTrigger', { summary: Constants.per.authOnly })
|
@Post('/batchUpdateTrigger', { summary: Constants.per.authOnly })
|
||||||
async batchUpdateTrigger(@Body('ids') ids: number[], @Body('trigger') trigger: any) {
|
async batchUpdateTrigger(@Body('ids') ids: number[], @Body('trigger') trigger: any) {
|
||||||
const isAdmin = await this.authService.isAdmin(this.ctx);
|
const isAdmin = await this.authService.isAdmin(this.ctx);
|
||||||
const userId = isAdmin ? undefined : this.getUserId() ;
|
const userId = isAdmin ? undefined : this.getUserId();
|
||||||
await this.service.batchUpdateTrigger(ids, trigger, userId);
|
await this.service.batchUpdateTrigger(ids, trigger, userId);
|
||||||
return this.ok({});
|
return this.ok({});
|
||||||
}
|
}
|
||||||
@@ -194,7 +194,7 @@ export class PipelineController extends CrudController<PipelineService> {
|
|||||||
@Post('/batchUpdateNotification', { summary: Constants.per.authOnly })
|
@Post('/batchUpdateNotification', { summary: Constants.per.authOnly })
|
||||||
async batchUpdateNotification(@Body('ids') ids: number[], @Body('notification') notification: any) {
|
async batchUpdateNotification(@Body('ids') ids: number[], @Body('notification') notification: any) {
|
||||||
const isAdmin = await this.authService.isAdmin(this.ctx);
|
const isAdmin = await this.authService.isAdmin(this.ctx);
|
||||||
const userId = isAdmin ? undefined : this.getUserId() ;
|
const userId = isAdmin ? undefined : this.getUserId();
|
||||||
await this.service.batchUpdateNotifications(ids, notification, userId);
|
await this.service.batchUpdateNotifications(ids, notification, userId);
|
||||||
return this.ok({});
|
return this.ok({});
|
||||||
}
|
}
|
||||||
@@ -204,4 +204,14 @@ export class PipelineController extends CrudController<PipelineService> {
|
|||||||
await this.service.batchRerun(ids, this.getUserId(), force);
|
await this.service.batchRerun(ids, this.getUserId(), force);
|
||||||
return this.ok({});
|
return this.ok({});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('/refreshWebhookKey', { summary: Constants.per.authOnly })
|
||||||
|
async refreshWebhookKey(@Body('id') id: number) {
|
||||||
|
await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
|
||||||
|
const res = await this.service.refreshWebhookKey(id);
|
||||||
|
return this.ok({
|
||||||
|
webhookKey: res,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,12 @@ export class PipelineEntity {
|
|||||||
@Column({ comment: '类型', nullable: true, default: 'cert' })
|
@Column({ comment: '类型', nullable: true, default: 'cert' })
|
||||||
type: string;
|
type: string;
|
||||||
|
|
||||||
|
@Column({ name: 'webhook_key', comment: 'webhookkey', length: 100, nullable: true })
|
||||||
|
webhookKey: string;
|
||||||
|
|
||||||
|
@Column({ name: 'trigger_count', comment: '触发器数量', nullable: true, default: 0 })
|
||||||
|
triggerCount: number;
|
||||||
|
|
||||||
// custom: 自定义; monitor: 监控;
|
// custom: 自定义; monitor: 监控;
|
||||||
@Column({ comment: '来源', nullable: true, default: '' })
|
@Column({ comment: '来源', nullable: true, default: '' })
|
||||||
from: string;
|
from: string;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import { PluginConfigGetter } from "../../plugin/service/plugin-config-getter.js
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { DbAdapter } from "../../db/index.js";
|
import { DbAdapter } from "../../db/index.js";
|
||||||
import { isComm, isPlus } from "@certd/plus-core";
|
import { isComm, isPlus } from "@certd/plus-core";
|
||||||
import { logger } from "@certd/basic";
|
import { logger, utils } from "@certd/basic";
|
||||||
import { UrlService } from "./url-service.js";
|
import { UrlService } from "./url-service.js";
|
||||||
import { NotificationService } from "./notification-service.js";
|
import { NotificationService } from "./notification-service.js";
|
||||||
import { UserSuiteEntity, UserSuiteService } from "@certd/commercial-core";
|
import { UserSuiteEntity, UserSuiteService } from "@certd/commercial-core";
|
||||||
@@ -177,7 +177,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
if (!info.disabled) {
|
if (!info.disabled) {
|
||||||
const pipeline = JSON.parse(info.content);
|
const pipeline = JSON.parse(info.content);
|
||||||
this.registerTriggers(pipeline, false);
|
this.registerTriggers(pipeline, false);
|
||||||
}else {
|
} else {
|
||||||
this.unregisterTriggers(info);
|
this.unregisterTriggers(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,6 +214,10 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
//修改
|
//修改
|
||||||
old = await this.info(bean.id);
|
old = await this.info(bean.id);
|
||||||
}
|
}
|
||||||
|
if (!old || !old.webhookKey ) {
|
||||||
|
bean.webhookKey = await this.genWebhookKey();
|
||||||
|
}
|
||||||
|
|
||||||
const isUpdate = bean.id > 0 && old != null;
|
const isUpdate = bean.id > 0 && old != null;
|
||||||
|
|
||||||
|
|
||||||
@@ -273,6 +277,9 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
pipeline.version = 0;
|
pipeline.version = 0;
|
||||||
}
|
}
|
||||||
pipeline.version++;
|
pipeline.version++;
|
||||||
|
|
||||||
|
bean.triggerCount = pipeline.triggers?.filter((trigger) => trigger.type === "timer").length || 0;
|
||||||
|
|
||||||
bean.content = JSON.stringify(pipeline);
|
bean.content = JSON.stringify(pipeline);
|
||||||
await this.addOrUpdate(bean);
|
await this.addOrUpdate(bean);
|
||||||
await this.registerTrigger(bean);
|
await this.registerTrigger(bean);
|
||||||
@@ -816,8 +823,8 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级专业版");
|
||||||
}
|
}
|
||||||
const query :any = {}
|
const query: any = {}
|
||||||
if(userId && userId>0){
|
if (userId && userId > 0) {
|
||||||
query.userId = userId;
|
query.userId = userId;
|
||||||
}
|
}
|
||||||
await this.repository.update(
|
await this.repository.update(
|
||||||
@@ -834,8 +841,8 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级专业版");
|
||||||
}
|
}
|
||||||
const query :any = {}
|
const query: any = {}
|
||||||
if(userId && userId>0){
|
if (userId && userId > 0) {
|
||||||
query.userId = userId;
|
query.userId = userId;
|
||||||
}
|
}
|
||||||
const list = await this.find({
|
const list = await this.find({
|
||||||
@@ -851,20 +858,20 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
//清除trigger
|
//清除trigger
|
||||||
pipeline.triggers = []
|
pipeline.triggers = []
|
||||||
} else {
|
} else {
|
||||||
if(trigger.random === true){
|
if (trigger.random === true) {
|
||||||
//随机时间
|
//随机时间
|
||||||
const start = dayjs().format("YYYY-MM-DD") + " " + trigger.randomRange[0];
|
const start = dayjs().format("YYYY-MM-DD") + " " + trigger.randomRange[0];
|
||||||
let end = dayjs().format("YYYY-MM-DD") + " " + trigger.randomRange[1];
|
let end = dayjs().format("YYYY-MM-DD") + " " + trigger.randomRange[1];
|
||||||
if(trigger.randomRange[1]<trigger.randomRange[0]){
|
if (trigger.randomRange[1] < trigger.randomRange[0]) {
|
||||||
//跨天
|
//跨天
|
||||||
end = dayjs().add(1, "day").format("YYYY-MM-DD") + " " + trigger.randomRange[1];
|
end = dayjs().add(1, "day").format("YYYY-MM-DD") + " " + trigger.randomRange[1];
|
||||||
}
|
}
|
||||||
const startTime = dayjs(start).valueOf();
|
const startTime = dayjs(start).valueOf();
|
||||||
const endTime = dayjs(end).valueOf();
|
const endTime = dayjs(end).valueOf();
|
||||||
const randomTime = Math.floor(Math.random() * (endTime - startTime)) + startTime;
|
const randomTime = Math.floor(Math.random() * (endTime - startTime)) + startTime;
|
||||||
const time = dayjs(randomTime).format(" ss:mm:HH").replaceAll(":", " ").replaceAll(" 0", " ").trim();
|
const time = dayjs(randomTime).format(" ss:mm:HH").replaceAll(":", " ").replaceAll(" 0", " ").trim();
|
||||||
set(trigger,"props.cron", `${time} * * *`)
|
set(trigger, "props.cron", `${time} * * *`)
|
||||||
}
|
}
|
||||||
delete trigger.random
|
delete trigger.random
|
||||||
delete trigger.randomRange;
|
delete trigger.randomRange;
|
||||||
pipeline.triggers = [{
|
pipeline.triggers = [{
|
||||||
@@ -883,8 +890,8 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级专业版");
|
||||||
}
|
}
|
||||||
const query :any = {}
|
const query: any = {}
|
||||||
if(userId && userId>0){
|
if (userId && userId > 0) {
|
||||||
query.userId = userId;
|
query.userId = userId;
|
||||||
}
|
}
|
||||||
const list = await this.find({
|
const list = await this.find({
|
||||||
@@ -935,19 +942,19 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
ids = list.map(item => item.id);
|
ids = list.map(item => item.id);
|
||||||
|
|
||||||
//异步执行
|
//异步执行
|
||||||
this.startBatchRerun(userId,ids, force);
|
this.startBatchRerun(userId, ids, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
startBatchRerun(userId:number, ids: number[], force: boolean) {
|
startBatchRerun(userId: number, ids: number[], force: boolean) {
|
||||||
for (const id of ids) {
|
for (const id of ids) {
|
||||||
executorQueue.addTask(userId,{
|
executorQueue.addTask(userId, {
|
||||||
task: async () => {
|
task: async () => {
|
||||||
if (force) {
|
if (force) {
|
||||||
await this.run(id, null, "ALL");
|
await this.run(id, null, "ALL");
|
||||||
} else {
|
} else {
|
||||||
await this.run(id, null);
|
await this.run(id, null);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1107,4 +1114,33 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
await this.repository.update(id, { disabled });
|
await this.repository.update(id, { disabled });
|
||||||
await this.registerTriggerById(id);
|
await this.registerTriggerById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async refreshWebhookKey(id: number) {
|
||||||
|
const webhookKey = await this.genWebhookKey();
|
||||||
|
await this.repository.update(id, { webhookKey });
|
||||||
|
return webhookKey;
|
||||||
|
}
|
||||||
|
async genWebhookKey() {
|
||||||
|
return utils.id.simpleNanoId(24);
|
||||||
|
}
|
||||||
|
async triggerByWebhook(webhookKey: string) {
|
||||||
|
const pipelineEntity = await this.findOne({
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
content: true,
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
webhookKey
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!pipelineEntity) {
|
||||||
|
throw new Error("webhookKey不存在");
|
||||||
|
}
|
||||||
|
const pipeline = JSON.parse(pipelineEntity.content);
|
||||||
|
const trigger = pipeline.triggers.find((trigger: any) => trigger.type === "webhook");
|
||||||
|
if (!trigger) {
|
||||||
|
throw new Error("该流水线的webhook未启用");
|
||||||
|
}
|
||||||
|
await this.run(pipelineEntity.id, trigger.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+3
-3
@@ -4,9 +4,6 @@ settings:
|
|||||||
autoInstallPeers: true
|
autoInstallPeers: true
|
||||||
excludeLinksFromLockfile: false
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
overrides:
|
|
||||||
root: 'link:'
|
|
||||||
|
|
||||||
importers:
|
importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
@@ -870,6 +867,9 @@ importers:
|
|||||||
'@certd/basic':
|
'@certd/basic':
|
||||||
specifier: ^1.37.17
|
specifier: ^1.37.17
|
||||||
version: link:../../core/basic
|
version: link:../../core/basic
|
||||||
|
'@certd/pipeline':
|
||||||
|
specifier: ^1.37.17
|
||||||
|
version: link:../../core/pipeline
|
||||||
'@certd/plugin-lib':
|
'@certd/plugin-lib':
|
||||||
specifier: ^1.37.17
|
specifier: ^1.37.17
|
||||||
version: link:../../plugins/plugin-lib
|
version: link:../../plugins/plugin-lib
|
||||||
|
|||||||
Reference in New Issue
Block a user