Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ func getJobVariableKey(currentJobName, serviceName, moduleName, key string, getA
return resp
}

func renderScriptedVariableOptions(serviceName, moduleName, script, callFunction string, userInput map[string]string) ([]string, error) {
// Render Scripted Variable Options
func RenderScriptedVariableOptions(serviceName, moduleName, script, callFunction string, userInput map[string]string) ([]string, error) {
if script == "" || callFunction == "" {
return []string{}, nil
}
Expand All @@ -60,12 +61,13 @@ func renderScriptedVariableOptions(serviceName, moduleName, script, callFunction
}
t.Option("missingkey=error")

renderInput := make(map[string]string, len(userInput))
for key, val := range userInput {
userInput[key] = "`" + val + "`"
renderInput[key] = "`" + val + "`"
}

var realCallFunc bytes.Buffer
err = t.Execute(&realCallFunc, userInput)
err = t.Execute(&realCallFunc, renderInput)
if err != nil {
return nil, fmt.Errorf("渲染调用函数失败, 错误: %v", err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1076,7 +1076,7 @@ func (j BuildJobController) RenderDynamicVariableOptions(key string, option *Ren
// Find the KeyVal with the given key
for _, kv := range targetBuild.KeyVals {
if kv.Key == key {
resp, err := renderScriptedVariableOptions(option.ServiceName, option.ServiceModule, kv.Script, kv.CallFunction, option.Values)
resp, err := RenderScriptedVariableOptions(option.ServiceName, option.ServiceModule, kv.Script, kv.CallFunction, option.Values)
if err != nil {
err = fmt.Errorf("Failed to render kv for key: %s, error: %s", key, err)
return nil, err
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ func (j FreestyleJobController) GetUsedRepos() ([]*types.Repository, error) {
func (j FreestyleJobController) RenderDynamicVariableOptions(key string, option *RenderDynamicVariableValue) ([]string, error) {
for _, kv := range j.jobSpec.Envs {
if kv.Key == key {
resp, err := renderScriptedVariableOptions(option.ServiceName, option.ServiceModule, kv.Script, kv.CallFunction, option.Values)
resp, err := RenderScriptedVariableOptions(option.ServiceName, option.ServiceModule, kv.Script, kv.CallFunction, option.Values)
if err != nil {
err = fmt.Errorf("Failed to render kv for key: %s, error: %s", key, err)
return nil, err
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ func (j PluginJobController) GetUsedRepos() ([]*types.Repository, error) {
func (j PluginJobController) RenderDynamicVariableOptions(key string, option *RenderDynamicVariableValue) ([]string, error) {
for _, kv := range j.jobSpec.Plugin.Inputs {
if kv.Name == key {
resp, err := renderScriptedVariableOptions(option.ServiceName, option.ServiceModule, kv.Script, kv.CallFunction, option.Values)
resp, err := RenderScriptedVariableOptions(option.ServiceName, option.ServiceModule, kv.Script, kv.CallFunction, option.Values)
if err != nil {
err = fmt.Errorf("Failed to render kv for key: %s, error: %s", key, err)
return nil, err
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,101 @@ func (w *Workflow) getWorkflowDefaultParams(taskID int64, creator, account, uid
return resp, nil
}

// sanitizeDynamicVariableKey sanitizes the dynamic variable key by replacing special characters with underscores.
func sanitizeDynamicVariableKey(key string) string {
key = strings.ReplaceAll(key, "-", "_")
key = strings.ReplaceAll(key, ".", "_")
return key
}

// GetWorkflowParamReferableVariables returns the workflow param referable variables.
func (w *Workflow) GetWorkflowParamReferableVariables(taskID int64, creator, account, uid string, releasePlan *commonmodels.ReleasePlanRef) ([]*commonmodels.KeyVal, error) {
globalParams, err := w.getWorkflowDefaultParams(taskID, creator, account, uid, releasePlan)
if err != nil {
return nil, fmt.Errorf("get workflow default params error: %v", err)
}

resp := make([]*commonmodels.KeyVal, 0, len(globalParams))
for _, param := range globalParams {
if param.ParamsType == "repo" || param.ParamsType == "file" {
continue
}

resp = append(resp, &commonmodels.KeyVal{
Key: param.Name,
Value: param.GetValue(),
Type: "string",
IsCredential: param.IsCredential,
})
}

return resp, nil
}

func (w *Workflow) getWorkflowParamDynamicValueMap(taskID int64, creator, account, uid string, releasePlan *commonmodels.ReleasePlanRef) (map[string]string, error) {
globalParams, err := w.GetWorkflowParamReferableVariables(taskID, creator, account, uid, releasePlan)
if err != nil {
return nil, err
}

resp := make(map[string]string, len(globalParams))
for _, param := range globalParams {
if param.Value == "" {
continue
}
resp[sanitizeDynamicVariableKey(param.Key)] = param.Value
}

return resp, nil
}

// RenderWorkflowDynamicParams renders the workflow dynamic params.
func (w *Workflow) RenderWorkflowDynamicParams(taskID int64, creator, account, uid string, releasePlan *commonmodels.ReleasePlanRef) error {
valueMap, err := w.getWorkflowParamDynamicValueMap(taskID, creator, account, uid, releasePlan)
if err != nil {
return fmt.Errorf("get workflow param dynamic value map error: %v", err)
}

for _, param := range w.Params {
if param.ParamsType == "repo" || param.ParamsType == "file" || param.Script == "" || param.CallFunction == "" {
continue
}

resp, err := jobctrl.RenderScriptedVariableOptions("", "", param.Script, param.CallFunction, valueMap)
if err != nil {
return fmt.Errorf("render workflow param %s dynamic options error: %v", param.Name, err)
}

param.ChoiceOption = resp
if param.GetValue() != "" {
valueMap[sanitizeDynamicVariableKey(strings.Join([]string{"workflow", "params", param.Name}, "."))] = param.GetValue()
}
}

return nil
}

func (w *Workflow) GetWorkflowParamDynamicValues(taskID int64, creator, account, uid string, key string, releasePlan *commonmodels.ReleasePlanRef) ([]string, error) {
valueMap, err := w.getWorkflowParamDynamicValueMap(taskID, creator, account, uid, releasePlan)
if err != nil {
return nil, fmt.Errorf("get workflow param dynamic value map error: %v", err)
}

for _, param := range w.Params {
if param.Name != key && strings.Join([]string{"workflow", "params", param.Name}, ".") != key {
continue
}

resp, err := jobctrl.RenderScriptedVariableOptions("", "", param.Script, param.CallFunction, valueMap)
if err != nil {
return nil, fmt.Errorf("render workflow param %s dynamic options error: %v", param.Name, err)
}
return resp, nil
}

return nil, fmt.Errorf("workflow param %s not found", key)
}

func (w *Workflow) Validate(isExecution bool) error {
if w.Project == "" {
err := fmt.Errorf("project should not be empty")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1578,6 +1578,8 @@ type Param struct {
Repo *types.Repository `bson:"repo" json:"repo" yaml:"repo,omitempty"`
ChoiceOption []string `bson:"choice_option,omitempty" json:"choice_option,omitempty" yaml:"choice_option,omitempty"`
ChoiceValue []string `bson:"choice_value,omitempty" json:"choice_value,omitempty" yaml:"choice_value,omitempty"`
Script string `bson:"script,omitempty" json:"script,omitempty" yaml:"script,omitempty"`
CallFunction string `bson:"call_function,omitempty" json:"call_function,omitempty" yaml:"call_function,omitempty"`
Default string `bson:"default" json:"default" yaml:"default"`
IsCredential bool `bson:"is_credential" json:"is_credential" yaml:"is_credential"`
Source config.ParamSourceType `bson:"source,omitempty" json:"source,omitempty" yaml:"source,omitempty"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ type DistributeImageJobSpec struct {
DistributeTarget []*step.DistributeTaskTarget `bson:"distribute_target" json:"distribute_target"`
}

// GetWorkflowV4Preset returns the workflow preset.
func GetWorkflowV4Preset(encryptedKey, workflowName, uid, username, ticketID string, log *zap.SugaredLogger) (*commonmodels.WorkflowV4, error) {
workflow, err := commonrepo.NewWorkflowV4Coll().Find(workflowName)
if err != nil {
Expand All @@ -270,6 +271,12 @@ func GetWorkflowV4Preset(encryptedKey, workflowName, uid, username, ticketID str
return nil, e.ErrPresetWorkflow.AddDesc(err.Error())
}

// Render workflow dynamic params
if err := workflowCtrl.RenderWorkflowDynamicParams(0, username, username, uid, nil); err != nil {
log.Errorf("failed to render workflow dynamic params for workflow: %s, the error is: %v", workflowName, err)
return nil, e.ErrPresetWorkflow.AddDesc(err.Error())
}

if err := ensureWorkflowV4Resp(encryptedKey, workflow, log); err != nil {
return workflow, err
}
Expand All @@ -281,6 +288,22 @@ func GetAvailableWorkflowV4DynamicVariable(ctx *internalhandler.Context, workflo
resp := make([]string, 0)

workflowCtrl := workflowController.CreateWorkflowController(workflow)

if jobName == "" {
variables, err := workflowCtrl.GetWorkflowParamReferableVariables(0, "", "", "", nil)
if err != nil {
err = fmt.Errorf("failed to get workflow param dynamic variables, error: %v", err)
ctx.Logger.Error(err)
return nil, err
}

for _, kv := range variables {
resp = append(resp, fmt.Sprintf("{{.%s}}", kv.Key))
}

return resp, nil
}

variables, err := workflowCtrl.GetReferableVariables(jobName, workflowController.GetWorkflowVariablesOption{
GetAggregatedVariables: false,
GetRuntimeVariables: false,
Expand All @@ -305,6 +328,18 @@ func GetWorkflowV4DynamicVariableValues(ctx *internalhandler.Context, workflow *
resp := make([]string, 0)

workflowCtrl := workflowController.CreateWorkflowController(workflow)

// When jobName is empty, render dynamic options for workflow-level params instead of job inputs.
if jobName == "" {
resp, err := workflowCtrl.GetWorkflowParamDynamicValues(0, "", "", "", key, nil)
if err != nil {
err = fmt.Errorf("failed to render workflow param dynamic variables, error: %v", err)
ctx.Logger.Error(err)
return nil, err
}
return resp, nil
}

variables, err := workflowCtrl.GetReferableVariables(jobName, workflowController.GetWorkflowVariablesOption{
GetAggregatedVariables: false,
GetRuntimeVariables: false,
Expand Down
Loading