예제 #1
0
// NewPatchTaskIdTable constructs a new TaskIdTable (map of [variant, task display name]->[task id])
func NewPatchTaskIdTable(proj *Project, v *version.Version, patchConfig TVPairSet) TaskIdTable {
	table := TaskIdTable{}
	processedVariants := map[string]bool{}
	for _, vt := range patchConfig {
		// don't hit the same variant more than once
		if _, ok := processedVariants[vt.Variant]; ok {
			continue
		}
		processedVariants[vt.Variant] = true
		// we must track the project's variants definitions as well,
		// so that we don't create Ids for variants that don't exist.
		projBV := proj.FindBuildVariant(vt.Variant)
		taskNamesForVariant := patchConfig.TaskNames(vt.Variant)
		for _, t := range projBV.Tasks {
			// create Ids for each task that can run on the variant and is requested by the patch.
			if util.SliceContains(taskNamesForVariant, t.Name) {
				taskId := util.CleanName(
					fmt.Sprintf("%v_%v_%v_%v_%v",
						proj.Identifier, projBV.Name, t.Name, v.Revision,
						v.CreateTime.Format(build.IdTimeLayout)))
				table[TVPair{vt.Variant, t.Name}] = taskId
			}
		}
	}
	return table
}
예제 #2
0
// NewVersionFromRevision populates a new Version with metadata from a model.Revision.
// Does not populate its config or store anything in the database.
func NewVersionFromRevision(ref *model.ProjectRef, rev model.Revision) (*version.Version, error) {
	number, err := model.GetNewRevisionOrderNumber(ref.Identifier)
	if err != nil {
		return nil, err
	}
	v := &version.Version{
		Author:              rev.Author,
		AuthorEmail:         rev.AuthorEmail,
		Branch:              ref.Branch,
		CreateTime:          rev.CreateTime,
		Id:                  util.CleanName(fmt.Sprintf("%v_%v", ref.String(), rev.Revision)),
		Identifier:          ref.Identifier,
		Message:             rev.RevisionMessage,
		Owner:               ref.Owner,
		Project:             ref.Identifier,
		RemotePath:          ref.RemotePath,
		Repo:                ref.Repo,
		RepoKind:            ref.RepoKind,
		Requester:           evergreen.RepotrackerVersionRequester,
		Revision:            rev.Revision,
		Status:              evergreen.VersionCreated,
		RevisionOrderNumber: number,
	}
	return v, nil
}
예제 #3
0
// TaskIdTable builds a TaskIdTable for the given version and project
func NewTaskIdTable(p *Project, v *version.Version) TaskIdTable {
	// init the variant map
	table := TaskIdTable{}
	for _, bv := range p.BuildVariants {
		for _, t := range bv.Tasks {
			// create a unique Id for each task
			taskId := util.CleanName(
				fmt.Sprintf("%v_%v_%v_%v_%v",
					p.Identifier, bv.Name, t.Name, v.Revision, v.CreateTime.Format(build.IdTimeLayout)))
			table[TVPair{bv.Name, t.Name}] = taskId
		}
	}
	return table
}
예제 #4
0
// CreateBuildFromVersion creates a build given all of the necessary information
// from the corresponding version and project and a list of tasks.
func CreateBuildFromVersion(project *Project, v *version.Version, tt TaskIdTable,
	buildName string, activated bool, taskNames []string) (string, error) {

	evergreen.Logger.Logf(slogger.DEBUG, "Creating %v %v build, activated: %v", v.Requester, buildName, activated)

	// find the build variant for this project/build
	buildVariant := project.FindBuildVariant(buildName)
	if buildVariant == nil {
		return "", fmt.Errorf("could not find build %v in %v project file", buildName, project.Identifier)
	}

	// create a new build id
	buildId := util.CleanName(
		fmt.Sprintf("%v_%v_%v_%v",
			project.Identifier,
			buildName,
			v.Revision,
			v.CreateTime.Format(build.IdTimeLayout)))

	// create the build itself
	b := &build.Build{
		Id:                  buildId,
		CreateTime:          v.CreateTime,
		PushTime:            v.CreateTime,
		Activated:           activated,
		Project:             project.Identifier,
		Revision:            v.Revision,
		Status:              evergreen.BuildCreated,
		BuildVariant:        buildName,
		Version:             v.Id,
		DisplayName:         buildVariant.DisplayName,
		RevisionOrderNumber: v.RevisionOrderNumber,
		Requester:           v.Requester,
	}

	// get a new build number for the build
	buildNumber, err := db.GetNewBuildVariantBuildNumber(buildName)
	if err != nil {
		return "", fmt.Errorf("could not get build number for build variant"+
			" %v in %v project file", buildName, project.Identifier)
	}
	b.BuildNumber = strconv.FormatUint(buildNumber, 10)

	// create all of the necessary tasks for the build
	tasksForBuild, err := createTasksForBuild(project, buildVariant, b, v, tt, taskNames)
	if err != nil {
		return "", fmt.Errorf("error creating tasks for build %v: %v", b.Id, err)
	}

	// insert all of the build's tasks into the db
	for _, task := range tasksForBuild {
		if err := task.Insert(); err != nil {
			return "", fmt.Errorf("error inserting task %v: %v", task.Id, err)
		}
	}

	// create task caches for all of the tasks, and place them into the build
	tasks := make([]Task, 0, len(tasksForBuild))
	for _, taskP := range tasksForBuild {
		tasks = append(tasks, *taskP)
	}
	b.Tasks = CreateTasksCache(tasks)

	// insert the build
	if err := b.Insert(); err != nil {
		return "", fmt.Errorf("error inserting build %v: %v", b.Id, err)
	}

	// success!
	return b.Id, nil
}
예제 #5
0
// createTasksForBuild creates all of the necessary tasks for the build.  Returns a
// slice of all of the tasks created, as well as an error if any occurs.
// The slice of tasks will be in the same order as the project's specified tasks
// appear in the specified build variant.
func createTasksForBuild(project *Project, buildVariant *BuildVariant,
	b *build.Build, v *version.Version, taskNames []string) ([]*Task, error) {

	// the list of tasks we should create.  if tasks are passed in, then
	// use those, else use the default set
	tasksToCreate := []BuildVariantTask{}
	createAll := len(taskNames) == 0
	for _, task := range buildVariant.Tasks {
		if task.Name == evergreen.PushStage &&
			b.Requester == evergreen.PatchVersionRequester {
			continue
		}
		if createAll || util.SliceContains(taskNames, task.Name) {
			tasksToCreate = append(tasksToCreate, task)
		}
	}

	// create a map of display name -> task id for all of the tasks we are
	// going to create.  we do this ahead of time so we can access it for the
	// dependency lists.
	taskIdsByDisplayName := map[string]string{}
	for _, task := range tasksToCreate {
		taskId := util.CleanName(
			fmt.Sprintf("%v_%v_%v_%v_%v",
				project.Identifier,
				b.BuildVariant,
				task.Name,
				v.Revision,
				v.CreateTime.Format(build.IdTimeLayout)))
		taskIdsByDisplayName[task.Name] = taskId
	}

	// if any tasks already exist in the build, add them to the map
	// so they can be used as dependencies
	for _, task := range b.Tasks {
		taskIdsByDisplayName[task.DisplayName] = task.Id
	}

	// create and insert all of the actual tasks
	tasks := make([]*Task, 0, len(tasksToCreate))
	for _, task := range tasksToCreate {

		// get the task spec out of the project
		var taskSpec ProjectTask
		for _, projectTask := range project.Tasks {
			if projectTask.Name == task.Name {
				taskSpec = projectTask
				break
			}
		}

		// sanity check that the config isn't malformed
		if taskSpec.Name == "" {
			return nil, fmt.Errorf("config is malformed: variant '%v' runs "+
				"task called '%v' but no such task exists for repo %v for "+
				"version %v", buildVariant.Name, task.Name, project.Identifier,
				v.Id)
		}

		newTask := createOneTask(taskIdsByDisplayName[task.Name], task, project, buildVariant, b, v)

		// set the new task's dependencies
		if len(taskSpec.DependsOn) == 1 &&
			taskSpec.DependsOn[0].Name == AllDependencies {
			// the task depends on all of the other tasks in the build
			newTask.DependsOn = make([]string, 0, len(tasksToCreate)-1)
			for _, dep := range tasksToCreate {
				if dep.Name != newTask.DisplayName {
					newTask.DependsOn = append(newTask.DependsOn,
						taskIdsByDisplayName[dep.Name])
				}
			}

		} else {
			// the task has specific dependencies
			newTask.DependsOn = make([]string, 0, len(taskSpec.DependsOn))
			for _, dep := range taskSpec.DependsOn {
				// only add as a dependency if the dependency is being created
				if taskIdsByDisplayName[dep.Name] != "" {
					newTask.DependsOn = append(newTask.DependsOn,
						taskIdsByDisplayName[dep.Name])
				}
			}
		}

		// append the task to the list of the created tasks
		tasks = append(tasks, newTask)
	}

	// return all of the tasks created
	return tasks, nil
}