func GeneratePlanJsonV200()

in backend/server/services/blueprint_makeplan_v200.go [31:158]


func GeneratePlanJsonV200(
	projectName string,
	syncPolicy plugin.BlueprintSyncPolicy,
	sources *models.BlueprintSettings,
	metrics map[string]json.RawMessage,
	skipCollectors bool,
) (plugin.PipelinePlan, errors.Error) {
	connections := make([]*plugin.BlueprintConnectionV200, 0)
	err := errors.Convert(json.Unmarshal(sources.Connections, &connections))
	if err != nil {
		return nil, err
	}
	// make plan for data-source plugins fist. generate plan for each
	// connection, then merge them into one legitimate plan and collect the
	// scopes produced by the data-source plugins
	sourcePlans := make([]plugin.PipelinePlan, len(connections))
	scopes := make([]plugin.Scope, 0, len(connections))
	for i, connection := range connections {
		if len(connection.Scopes) == 0 && connection.Plugin != `webhook` && connection.Plugin != `jenkins` {
			// webhook needn't scopes
			// jenkins may upgrade from v100 and its scope is empty
			return nil, errors.Default.New(fmt.Sprintf("connections[%d].scopes is empty", i))
		}

		p, err := plugin.GetPlugin(connection.Plugin)
		if err != nil {
			return nil, err
		}
		if pluginBp, ok := p.(plugin.DataSourcePluginBlueprintV200); ok {
			var pluginScopes []plugin.Scope
			sourcePlans[i], pluginScopes, err = pluginBp.MakeDataSourcePipelinePlanV200(
				connection.ConnectionId,
				connection.Scopes,
				syncPolicy,
			)
			if err != nil {
				return nil, err
			}
			// collect scopes for the project. a github repository may produce
			// 2 scopes, 1 repo and 1 board
			scopes = append(scopes, pluginScopes...)
		} else {
			return nil, errors.Default.New(
				fmt.Sprintf("plugin %s does not support DataSourcePluginBlueprintV200", connection.Plugin),
			)
		}
	}

	// skip collectors
	if skipCollectors {
		for i, plan := range sourcePlans {
			for j, stage := range plan {
				for k, task := range stage {
					newSubtasks := make([]string, 0, len(task.Subtasks))
					for _, subtask := range task.Subtasks {
						if !strings.Contains(strings.ToLower(subtask), "collect") {
							newSubtasks = append(newSubtasks, subtask)
						}
					}
					task.Subtasks = newSubtasks
					sourcePlans[i][j][k] = task
				}
			}
		}

		// remove gitextractor plugin if it's not the only task
		for i, plan := range sourcePlans {
			for j, stage := range plan {
				newStage := make(plugin.PipelineStage, 0, len(stage))
				hasGitExtractor := false
				for _, task := range stage {
					if task.Plugin != "gitextractor" {
						newStage = append(newStage, task)
					} else {
						hasGitExtractor = true
					}
				}
				if !hasGitExtractor || len(newStage) > 0 {
					sourcePlans[i][j] = newStage
				}
			}
		}
	}

	// make plans for metric plugins
	metricPlans := make([]plugin.PipelinePlan, len(metrics))
	i := 0
	for metricPluginName, metricPluginOptJson := range metrics {
		p, err := plugin.GetPlugin(metricPluginName)
		if err != nil {
			return nil, err
		}
		if pluginBp, ok := p.(plugin.MetricPluginBlueprintV200); ok {
			// If we enable one metric plugin, even if it has nil option, we still process it
			if len(metricPluginOptJson) == 0 {
				metricPluginOptJson = json.RawMessage("{}")
			}
			metricPlans[i], err = pluginBp.MakeMetricPluginPipelinePlanV200(projectName, metricPluginOptJson)
			if err != nil {
				return nil, err
			}
			i++
		} else {
			return nil, errors.Default.New(
				fmt.Sprintf("plugin %s does not support MetricPluginBlueprintV200", metricPluginName),
			)
		}
	}
	var planForProjectMapping plugin.PipelinePlan
	if projectName != "" {
		p, err := plugin.GetPlugin("org")
		if err != nil {
			return nil, err
		}
		if pluginBp, ok := p.(plugin.ProjectMapper); ok {
			planForProjectMapping, err = pluginBp.MapProject(projectName, scopes)
			if err != nil {
				return nil, err
			}
		}
	}
	plan := SequencializePipelinePlans(
		planForProjectMapping,
		ParallelizePipelinePlans(sourcePlans...),
		ParallelizePipelinePlans(metricPlans...),
	)
	return plan, err
}