diff --git a/pkg/core/deployer/providers/cloudflare-ssl/cloudflare_ssl.go b/pkg/core/deployer/providers/cloudflare-ssl/cloudflare_ssl.go index ea96549c6..b5c724323 100644 --- a/pkg/core/deployer/providers/cloudflare-ssl/cloudflare_ssl.go +++ b/pkg/core/deployer/providers/cloudflare-ssl/cloudflare_ssl.go @@ -1,7 +1,6 @@ package cloudflaressl import ( - "cmp" "context" "fmt" "log/slog" @@ -69,6 +68,11 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*Dep return nil, fmt.Errorf("config `zoneId` is required") } + deploy, err := deployRequestField(d.config.Environment) + if err != nil { + return nil, err + } + if d.config.CertificateId == "" { // 新建自定义证书 // REF: https://developers.cf.com/api/resources/custom_certificates/methods/create @@ -77,7 +81,7 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*Dep Certificate: lo.ToPtr(certPEM), PrivateKey: lo.ToPtr(privkeyPEM), BundleMethod: lo.ToPtr("ubiquitous"), - Deploy: lo.ToPtr(cmp.Or(d.config.Environment, "production")), + Deploy: deploy, } customCertificateCreateResp, err := d.sdkClient.CustomCertificateCreateWithContext(ctx, customCertificateCreateReq) d.logger.Debug("sdk request 'CustomCertificates.Create'", slog.Any("request", customCertificateCreateReq), slog.Any("response", customCertificateCreateResp)) @@ -93,7 +97,7 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*Dep Certificate: lo.ToPtr(certPEM), PrivateKey: lo.ToPtr(privkeyPEM), BundleMethod: lo.ToPtr("ubiquitous"), - Deploy: lo.ToPtr(cmp.Or(d.config.Environment, "production")), + Deploy: deploy, } customCertificateEditResp, err := d.sdkClient.CustomCertificateEditWithContext(ctx, customCertificateEditReq) d.logger.Debug("sdk request 'CustomCertificates.Edit'", slog.Any("request", customCertificateEditReq), slog.Any("response", customCertificateEditResp)) diff --git a/pkg/core/deployer/providers/cloudflare-ssl/deploy_env.go b/pkg/core/deployer/providers/cloudflare-ssl/deploy_env.go new file mode 100644 index 000000000..0ffa31b0b --- /dev/null +++ b/pkg/core/deployer/providers/cloudflare-ssl/deploy_env.go @@ -0,0 +1,20 @@ +package cloudflaressl + +import ( + "fmt" + "strings" + + "github.com/samber/lo" +) + +func deployRequestField(environment string) (*string, error) { + env := strings.ToLower(strings.TrimSpace(environment)) + switch env { + case "", "production": + return nil, nil + case "staging": + return lo.ToPtr("staging"), nil + default: + return nil, fmt.Errorf("config `environment` must be empty, \"production\", or \"staging\", got %q", environment) + } +} diff --git a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderCloudflareSSL.tsx b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderCloudflareSSL.tsx index da8bb21d6..3b3643a82 100644 --- a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderCloudflareSSL.tsx +++ b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderCloudflareSSL.tsx @@ -1,10 +1,12 @@ import { getI18n, useTranslation } from "react-i18next"; -import { AutoComplete, Form, Input } from "antd"; +import { Form, Input, Select } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; import { useFormNestedFieldsContext } from "./_context"; +const CLOUDFLARE_SSL_ENVIRONMENT_STAGING = "staging"; + const BizDeployNodeConfigFieldsProviderCloudflareSSL = () => { const { i18n, t } = useTranslation(); @@ -21,12 +23,19 @@ const BizDeployNodeConfigFieldsProviderCloudflareSSL = () => { name={[parentNamePath, "environment"]} initialValue={initialValues.environment} label={t("workflow_node.deploy.form.cloudflare_ssl_environment.label")} + extra={t("workflow_node.deploy.form.cloudflare_ssl_environment.help")} rules={[formRule]} tooltip={} + normalize={(value) => (value === "production" ? undefined : value)} > - ({ value: s }))} + options={[ + { + value: CLOUDFLARE_SSL_ENVIRONMENT_STAGING, + label: t("workflow_node.deploy.form.cloudflare_ssl_environment.option_staging"), + }, + ]} placeholder={t("workflow_node.deploy.form.cloudflare_ssl_environment.placeholder")} /> @@ -57,16 +66,20 @@ const BizDeployNodeConfigFieldsProviderCloudflareSSL = () => { const getInitialValues = (): Nullish>> => { return { - environment: "production", zoneId: "", }; }; const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType }) => { - const { t: _ } = i18n; + const { t } = i18n; return z.object({ - environment: z.string().nullish(), + environment: z + .string() + .nullish() + .refine((value) => !value || value === CLOUDFLARE_SSL_ENVIRONMENT_STAGING || value === "production", { + message: t("workflow_node.deploy.form.cloudflare_ssl_environment.errmsg_invalid"), + }), zoneId: z.string().nonempty(), certificateId: z.string().nullish(), }); diff --git a/ui/src/i18n/resources/en/nls.workflow.nodes.json b/ui/src/i18n/resources/en/nls.workflow.nodes.json index 686093859..a65e95345 100644 --- a/ui/src/i18n/resources/en/nls.workflow.nodes.json +++ b/ui/src/i18n/resources/en/nls.workflow.nodes.json @@ -1432,9 +1432,12 @@ "tooltip": "You can find it on Cdnfly dashboard." }, "cloudflare_ssl_environment": { - "label": "Cloudflare environment", - "placeholder": "Please enter Cloudflare environment", - "tooltip": "For more information, see https://developers.cloudflare.com/ssl/edge-certificates/staging-environment/" + "label": "Staging deploy (optional)", + "placeholder": "Leave empty for production (recommended)", + "help": "Leave empty for normal custom certificate upload to the production edge. Choose staging only if your Enterprise account uses the Staging Certificates beta.", + "option_staging": "staging (Enterprise Staging test)", + "errmsg_invalid": "Only empty or staging is allowed", + "tooltip": "Cloudflare API deploy field: when empty, production deployment is used and the field is omitted from the request. Staging is Enterprise-only. See Staging environment and Create custom certificate." }, "cloudflare_ssl_zone_id": { "label": "Cloudflare DNS zone ID", diff --git a/ui/src/i18n/resources/zh/nls.workflow.nodes.json b/ui/src/i18n/resources/zh/nls.workflow.nodes.json index 1ed1444a2..293bde888 100644 --- a/ui/src/i18n/resources/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/resources/zh/nls.workflow.nodes.json @@ -1431,9 +1431,12 @@ "tooltip": "请登录 Cdnfly 控制台查看" }, "cloudflare_ssl_environment": { - "label": "Cloudflare 环境", - "placeholder": "请输入 Cloudflare 环境", - "tooltip": "这是什么?请参阅 https://developers.cloudflare.com/ssl/edge-certificates/staging-environment/" + "label": "Staging 部署(可选)", + "placeholder": "留空即生产部署(推荐)", + "help": "常规上传自定义证书到生产边缘时无需填写。仅 Enterprise 账户在 Staging 环境测试证书时选择 staging。", + "option_staging": "staging(Enterprise Staging 测试)", + "errmsg_invalid": "仅支持留空或 staging", + "tooltip": "Cloudflare API 的 deploy 参数:留空时默认生产部署且不会显式传递该字段。Staging 仅面向 Enterprise 开放,请参阅 Staging 环境 与 Create custom certificate。" }, "cloudflare_ssl_zone_id": { "label": "Cloudflare DNS 区域 ID",