feat: support configuring repeatable deploy in deployment

This commit is contained in:
Fu Diwei 2025-01-19 06:02:49 +08:00
parent c71d14cafa
commit 5b613bcf84
9 changed files with 52 additions and 14 deletions

View File

@ -76,7 +76,7 @@ type WorkflowNodeConfigForDeploy struct {
Provider string `json:"provider"` // 主机提供商
ProviderAccessId string `json:"providerAccessId"` // 主机提供商授权记录 ID
ProviderConfig map[string]any `json:"providerConfig"` // 主机提供商额外配置
SkipOnLastSucceeded bool `json:"skipOnLastSucceeded"` // TODO: 上次部署成功时是否跳过
SkipOnLastSucceeded bool `json:"skipOnLastSucceeded"` // 上次部署成功时是否跳过
}
type WorkflowNodeConfigForNotify struct {

View File

@ -136,5 +136,5 @@ func (a *applyNode) checkCanSkip(ctx context.Context, lastOutput *domain.Workflo
}
}
return false, "无历史申请记录"
return false, ""
}

View File

@ -99,7 +99,6 @@ func (d *deployNode) Run(ctx context.Context) error {
}
func (d *deployNode) checkCanSkip(ctx context.Context, lastOutput *domain.WorkflowOutput) (skip bool, reason string) {
// TODO: 可控制是否强制部署
if lastOutput != nil && lastOutput.Succeeded {
// 比较和上次部署时的关键配置(即影响证书部署的)参数是否一致
currentNodeConfig := d.node.GetConfigForDeploy()
@ -111,8 +110,10 @@ func (d *deployNode) checkCanSkip(ctx context.Context, lastOutput *domain.Workfl
return false, "配置项变化:主机提供商参数"
}
if currentNodeConfig.SkipOnLastSucceeded {
return true, "已部署过证书"
}
}
return false, "无历史部署记录"
return false, ""
}

View File

@ -391,11 +391,11 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
label={t("workflow_node.apply.form.skip_before_expiry_days.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.skip_before_expiry_days.tooltip") }}></span>}
>
<Flex align="center" gap={8}>
<Flex align="center" gap={8} wrap="wrap">
<div>{t("workflow_node.apply.form.skip_before_expiry_days.prefix")}</div>
<Form.Item name="skipBeforeExpiryDays" noStyle rules={[formRule]}>
<InputNumber
className="flex-1"
className="w-36"
min={1}
max={60}
placeholder={t("workflow_node.apply.form.skip_before_expiry_days.placeholder")}

View File

@ -1,7 +1,7 @@
import { forwardRef, memo, useEffect, useImperativeHandle, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { PlusOutlined as PlusOutlinedIcon, QuestionCircleOutlined as QuestionCircleOutlinedIcon } from "@ant-design/icons";
import { Button, Divider, Form, type FormInstance, Select, Tooltip, Typography } from "antd";
import { Button, Divider, Flex, Form, type FormInstance, Select, Switch, Tooltip, Typography } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
@ -65,7 +65,9 @@ export type DeployNodeConfigFormInstance = {
};
const initFormModel = (): DeployNodeConfigFormFieldValues => {
return {};
return {
skipOnLastSucceeded: true,
};
};
const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNodeConfigFormProps>(
@ -91,6 +93,7 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
.nonempty(t("workflow_node.deploy.form.provider_access.placeholder"))
.refine(() => !!formInst.getFieldValue("provider"), t("workflow_node.deploy.form.provider.placeholder")),
providerConfig: z.any(),
skipOnLastSucceeded: z.boolean(),
});
const formRule = createSchemaFieldRule(formSchema);
const { form: formInst, formProps } = useAntdForm({
@ -340,6 +343,27 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
{nestedFormEl}
</Show>
<Divider className="my-1">
<Typography.Text className="text-xs font-normal" type="secondary">
{t("workflow_node.deploy.form.strategy_config.label")}
</Typography.Text>
</Divider>
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
<Form.Item label={t("workflow_node.deploy.form.skip_on_last_succeeded.label")}>
<Flex align="center" gap={8} wrap="wrap">
<div>{t("workflow_node.deploy.form.skip_on_last_succeeded.prefix")}</div>
<Form.Item name="skipOnLastSucceeded" noStyle rules={[formRule]}>
<Switch
checkedChildren={t("workflow_node.deploy.form.skip_on_last_succeeded.enabled.on")}
unCheckedChildren={t("workflow_node.deploy.form.skip_on_last_succeeded.enabled.off")}
/>
</Form.Item>
<div>{t("workflow_node.deploy.form.skip_on_last_succeeded.suffix")}</div>
</Flex>
</Form.Item>
</Form>
</Form.Provider>
);
}

View File

@ -119,6 +119,7 @@ export type WorkflowNodeConfigForDeploy = {
provider: string;
providerAccessId: string;
providerConfig: Record<string, unknown>;
skipOnLastSucceeded: boolean;
};
export type WorkflowNodeConfigForNotify = {

View File

@ -67,8 +67,8 @@
"workflow_node.apply.form.strategy_config.label": "Strategy settings",
"workflow_node.apply.form.skip_before_expiry_days.label": "Renewal interval",
"workflow_node.apply.form.skip_before_expiry_days.placeholder": "Please enter renewal interval",
"workflow_node.apply.form.skip_before_expiry_days.prefix": "Skip when the certificate expiration time exceeds",
"workflow_node.apply.form.skip_before_expiry_days.suffix": "",
"workflow_node.apply.form.skip_before_expiry_days.prefix": "If the certificate expiration time exceeds",
"workflow_node.apply.form.skip_before_expiry_days.suffix": ", skip to re-apply.",
"workflow_node.apply.form.skip_before_expiry_days.unit": "days",
"workflow_node.apply.form.skip_before_expiry_days.tooltip": "Be careful not to exceed the validity period limit of the CA, otherwise the certificate may never be renewed.",
@ -359,6 +359,12 @@
"workflow_node.deploy.form.webhook_data.guide": "Tips: The Webhook data should be a key-value pair in JSON format. The values in JSON support template variables, which will be replaced by actual values when sent to the Webhook URL. <br><br>Supported variables: <br><strong>${DOMAIN}</strong>: The primary domain of the certificate (<i>CommonName</i>).<br><strong>${DOMAINS}</strong>: The domain list of the certificate (<i>SubjectAltNames</i>).<br><strong>${CERTIFICATE}</strong>: The PEM format content of the certificate file.<br><strong>${PRIVATE_KEY}</strong>: The PEM format content of the private key file.",
"workflow_node.deploy.form.webhook_data.errmsg.json_invalid": "Please enter a valiod JSON string",
"workflow_node.deploy.form.webhook_data_preset.button": "Use preset template",
"workflow_node.deploy.form.strategy_config.label": "Strategy settings",
"workflow_node.deploy.form.skip_on_last_succeeded.label": "Repeated deployment",
"workflow_node.deploy.form.skip_on_last_succeeded.prefix": "If the last deployment was successful, ",
"workflow_node.deploy.form.skip_on_last_succeeded.suffix": " to re-deploy.",
"workflow_node.deploy.form.skip_on_last_succeeded.enabled.on": "skip",
"workflow_node.deploy.form.skip_on_last_succeeded.enabled.off": "not skip",
"workflow_node.notify.label": "Notification",
"workflow_node.notify.form.subject.label": "Subject",

View File

@ -25,7 +25,7 @@
"settings.notification.template.form.message.extra": "支持的变量(${COUNT}: 即将过期张数;${DOMAINS}: 域名列表)",
"settings.notification.channels.card.title": "通知渠道",
"settings.notification.channel.enabled.on": "启用",
"settings.notification.channel.enabled.off": "未启用",
"settings.notification.channel.enabled.off": "用",
"settings.notification.push_test.button": "推送测试消息",
"settings.notification.push_test.pushed": "已推送",
"settings.notification.channel.form.bark_server_url.label": "服务器地址",

View File

@ -67,8 +67,8 @@
"workflow_node.apply.form.strategy_config.label": "执行策略",
"workflow_node.apply.form.skip_before_expiry_days.label": "续期间隔",
"workflow_node.apply.form.skip_before_expiry_days.placeholder": "请输入续期间隔",
"workflow_node.apply.form.skip_before_expiry_days.prefix": "当距上次申请的证书到期时间前",
"workflow_node.apply.form.skip_before_expiry_days.suffix": "时跳过执行",
"workflow_node.apply.form.skip_before_expiry_days.prefix": "当上次签发的证书到期时间超过",
"workflow_node.apply.form.skip_before_expiry_days.suffix": "时,跳过重新申请。",
"workflow_node.apply.form.skip_before_expiry_days.unit": "天",
"workflow_node.apply.form.skip_before_expiry_days.tooltip": "注意不要超过 CA 的证书有效期限制,否则证书可能永远不会续期。",
@ -359,6 +359,12 @@
"workflow_node.deploy.form.webhook_data.guide": "小贴士:回调数据是一个 JSON 格式的键值对。其中值支持模板变量,将在被发送到指定的 Webhook URL 时被替换为实际值;其他内容将保持原样。<br><br>支持的变量:<br><strong>${DOMAIN}</strong>:证书的主域名(即 <i>CommonName</i><br><strong>${DOMAINS}</strong>:证书的多域名列表(即 <i>SubjectAltNames</i><br><strong>${CERTIFICATE}</strong>:证书文件 PEM 格式内容<br><strong>${PRIVATE_KEY}</strong>:私钥文件 PEM 格式内容",
"workflow_node.deploy.form.webhook_data.errmsg.json_invalid": "请输入有效的 JSON 格式字符串",
"workflow_node.deploy.form.webhook_data_preset.button": "使用预设模板",
"workflow_node.deploy.form.strategy_config.label": "执行策略",
"workflow_node.deploy.form.skip_on_last_succeeded.label": "重复部署",
"workflow_node.deploy.form.skip_on_last_succeeded.prefix": "当上次部署已成功时",
"workflow_node.deploy.form.skip_on_last_succeeded.suffix": "重新部署。",
"workflow_node.deploy.form.skip_on_last_succeeded.enabled.on": "跳过",
"workflow_node.deploy.form.skip_on_last_succeeded.enabled.off": "不跳过",
"workflow_node.notify.label": "通知",
"workflow_node.notify.form.subject.label": "通知主题",