// createVersionItems populates and stores all the tasks and builds for a version according to // the given project config. func createVersionItems(v *version.Version, ref *model.ProjectRef, project *model.Project) error { for _, buildvariant := range project.BuildVariants { if buildvariant.Disabled { continue } buildId, err := model.CreateBuildFromVersion(project, v, buildvariant.Name, false, nil) if err != nil { return err } lastActivated, err := version.FindOne(version.ByLastVariantActivation(ref.Identifier, buildvariant.Name)) if err != nil { evergreen.Logger.Logf(slogger.ERROR, "Error getting activation time for bv %v", buildvariant.Name) return err } var lastActivation *time.Time if lastActivated != nil { for _, buildStatus := range lastActivated.BuildVariants { if buildStatus.BuildVariant == buildvariant.Name && buildStatus.Activated { lastActivation = &buildStatus.ActivateAt break } } } var activateAt time.Time var activated bool if lastActivation == nil { // if we don't have a last activation time then activate now. activateAt = time.Now() activated = true } else { activateAt = lastActivation.Add(time.Minute * time.Duration(ref.GetBatchTime(&buildvariant))) evergreen.Logger.Logf(slogger.INFO, "Going to activate bv %v for project %v, version %v at %v", buildvariant.Name, ref.Identifier, v.Id, activateAt) } v.BuildIds = append(v.BuildIds, buildId) v.BuildVariants = append(v.BuildVariants, version.BuildStatus{ BuildVariant: buildvariant.Name, Activated: activated, ActivateAt: activateAt, BuildId: buildId, }) } if err := v.Insert(); err != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error inserting version %v: %v", v.Id, err) for _, buildStatus := range v.BuildVariants { if buildErr := model.DeleteBuild(buildStatus.BuildId); buildErr != nil { evergreen.Logger.Errorf(slogger.ERROR, "Error deleting build %v: %v", buildStatus.BuildId, buildErr) } } return err } return nil }
func TestPatchPluginAPI(t *testing.T) { testConfig := evergreen.TestConfig() cwd := testutil.GetDirectoryOfFile() Convey("With a running api server and installed plugin", t, func() { registry := plugin.NewSimpleRegistry() gitPlugin := &GitPlugin{} err := registry.Register(gitPlugin) testutil.HandleTestingErr(err, t, "Couldn't register patch plugin") server, err := service.CreateTestServer(testConfig, nil, plugin.APIPlugins, false) testutil.HandleTestingErr(err, t, "Couldn't set up testing server") taskConfig, _ := plugintest.CreateTestConfig(filepath.Join(cwd, "testdata", "plugin_patch.yml"), t) testCommand := GitGetProjectCommand{Directory: "dir"} _, _, err = plugintest.SetupAPITestData("testTask", filepath.Join(cwd, "testdata", "testmodule.patch"), t) testutil.HandleTestingErr(err, t, "Couldn't set up test documents") testTask, err := task.FindOne(task.ById("testTaskId")) testutil.HandleTestingErr(err, t, "Couldn't set up test patch task") sliceAppender := &evergreen.SliceAppender{[]*slogger.Log{}} logger := agentutil.NewTestLogger(sliceAppender) Convey("calls to existing tasks with patches should succeed", func() { httpCom := plugintest.TestAgentCommunicator(testTask.Id, testTask.Secret, server.URL) pluginCom := &comm.TaskJSONCommunicator{gitPlugin.Name(), httpCom} patch, err := testCommand.GetPatch(taskConfig, pluginCom, logger) So(err, ShouldBeNil) So(patch, ShouldNotBeNil) testutil.HandleTestingErr(db.Clear(version.Collection), t, "unable to clear versions collection") }) Convey("calls to non-existing tasks should fail", func() { v := version.Version{Id: ""} testutil.HandleTestingErr(v.Insert(), t, "Couldn't insert dummy version") httpCom := plugintest.TestAgentCommunicator("BAD_TASK_ID", "", server.URL) pluginCom := &comm.TaskJSONCommunicator{gitPlugin.Name(), httpCom} patch, err := testCommand.GetPatch(taskConfig, pluginCom, logger) So(err.Error(), ShouldContainSubstring, "not found") So(err, ShouldNotBeNil) So(patch, ShouldBeNil) testutil.HandleTestingErr(db.Clear(version.Collection), t, "unable to clear versions collection") }) Convey("calls to existing tasks without patches should fail", func() { noPatchTask := task.Task{Id: "noPatchTask", BuildId: "a"} testutil.HandleTestingErr(noPatchTask.Insert(), t, "Couldn't insert patch task") noPatchVersion := version.Version{Id: "noPatchVersion", BuildIds: []string{"a"}} testutil.HandleTestingErr(noPatchVersion.Insert(), t, "Couldn't insert patch version") v := version.Version{Id: ""} testutil.HandleTestingErr(v.Insert(), t, "Couldn't insert dummy version") httpCom := plugintest.TestAgentCommunicator(noPatchTask.Id, "", server.URL) pluginCom := &comm.TaskJSONCommunicator{gitPlugin.Name(), httpCom} patch, err := testCommand.GetPatch(taskConfig, pluginCom, logger) So(err, ShouldNotBeNil) So(err.Error(), ShouldContainSubstring, "no patch found for task") So(patch, ShouldBeNil) testutil.HandleTestingErr(db.Clear(version.Collection), t, "unable to clear versions collection") }) }) }
func TestBatchTimes(t *testing.T) { dropTestDB(t) Convey("When deciding whether or not to activate variants for the most recently stored version", t, func() { // We create a version with an activation time of now so that all the bvs have a last activation time of now. previouslyActivatedVersion := version.Version{ Id: "previously activated", Identifier: "testproject", BuildVariants: []version.BuildStatus{ { BuildVariant: "bv1", Activated: true, ActivateAt: time.Now(), }, { BuildVariant: "bv2", Activated: true, ActivateAt: time.Now(), }, }, RevisionOrderNumber: 0, Requester: evergreen.RepotrackerVersionRequester, } So(previouslyActivatedVersion.Insert(), ShouldBeNil) // insert distros used in testing. d := distro.Distro{Id: "test-distro-one"} So(d.Insert(), ShouldBeNil) d.Id = "test-distro-two" So(d.Insert(), ShouldBeNil) Convey("If the project's batch time has not elapsed, and no buildvariants "+ "have overriden their batch times, no variants should be activated", func() { project := createTestProject(nil, nil) revisions := []model.Revision{ *createTestRevision("foo", time.Now()), } repoTracker := RepoTracker{ testConfig, &model.ProjectRef{ Identifier: "testproject", BatchTime: 1, }, NewMockRepoPoller(project, revisions), } v, err := repoTracker.StoreRevisions(revisions) So(v, ShouldNotBeNil) So(err, ShouldBeNil) So(len(v.BuildVariants), ShouldEqual, 2) So(repoTracker.activateElapsedBuilds(v), ShouldBeNil) So(v.BuildVariants[0].Activated, ShouldBeFalse) So(v.BuildVariants[1].Activated, ShouldBeFalse) }) Convey("If the project's batch time has elapsed, and no buildvariants "+ "have overridden their batch times, all variants should be activated", func() { project := createTestProject(nil, nil) revisions := []model.Revision{ *createTestRevision("bar", time.Now().Add(time.Duration(-6*time.Minute))), } repoTracker := RepoTracker{ testConfig, &model.ProjectRef{ Identifier: "testproject", BatchTime: 0, }, NewMockRepoPoller(project, revisions), } version, err := repoTracker.StoreRevisions(revisions) So(version, ShouldNotBeNil) So(err, ShouldBeNil) So(repoTracker.activateElapsedBuilds(version), ShouldBeNil) bv1, found := findStatus(version, "bv1") So(found, ShouldBeTrue) So(bv1.Activated, ShouldBeTrue) bv2, found := findStatus(version, "bv2") So(found, ShouldBeTrue) So(bv2.Activated, ShouldBeTrue) }) Convey("If the project's batch time has elapsed, but both variants "+ "have overridden their batch times (which have not elapsed)"+ ", no variants should be activated", func() { // need to assign pointer vals twoforty := 240 onetwenty := 120 project := createTestProject(&twoforty, &onetwenty) revisions := []model.Revision{ *createTestRevision("baz", time.Now()), } repoTracker := RepoTracker{ testConfig, &model.ProjectRef{ Identifier: "testproject", BatchTime: 60, }, NewMockRepoPoller(project, revisions), } version, err := repoTracker.StoreRevisions(revisions) So(version, ShouldNotBeNil) So(err, ShouldBeNil) So(repoTracker.activateElapsedBuilds(version), ShouldBeNil) bv1, found := findStatus(version, "bv1") So(found, ShouldBeTrue) So(bv1.Activated, ShouldBeFalse) bv2, found := findStatus(version, "bv2") So(found, ShouldBeTrue) So(bv2.Activated, ShouldBeFalse) }) Convey("If the project's batch time has not elapsed, but one variant "+ "has overridden their batch times to be shorter"+ ", that variant should be activated", func() { zero := 0 project := createTestProject(&zero, nil) revisions := []model.Revision{ *createTestRevision("garply", time.Now()), } repoTracker := RepoTracker{ testConfig, &model.ProjectRef{ Identifier: "testproject", BatchTime: 60, }, NewMockRepoPoller(project, revisions), } version, err := repoTracker.StoreRevisions(revisions) So(version, ShouldNotBeNil) So(err, ShouldBeNil) So(repoTracker.activateElapsedBuilds(version), ShouldBeNil) bv1, found := findStatus(version, "bv1") So(found, ShouldBeTrue) So(bv1.Activated, ShouldBeTrue) bv2, found := findStatus(version, "bv2") So(found, ShouldBeTrue) So(bv2, ShouldNotBeNil) So(bv2.Activated, ShouldBeFalse) }) Reset(func() { dropTestDB(t) }) }) }