From aa18e052c3535f759d3dd8a376070cd84bee8321 Mon Sep 17 00:00:00 2001 From: Dheeraj Date: Tue, 29 Oct 2024 14:52:13 +0530 Subject: [PATCH] feat(STONEINTG-1065): let users rerun ALL tests * Before this commit, a user can only rerun one test at a time by adding the "run" label on snapshot with the name of ITS they want to rerun. * After this commit, a user can add the value of "all" in the "run" label of snapshot to automatically rerun ALL the tests easily. Signed-off-by: Dheeraj --- .../controller/snapshot/snapshot_adapter.go | 101 +++++++++++------- 1 file changed, 64 insertions(+), 37 deletions(-) diff --git a/internal/controller/snapshot/snapshot_adapter.go b/internal/controller/snapshot/snapshot_adapter.go index 8f8c89d0d..31297e720 100644 --- a/internal/controller/snapshot/snapshot_adapter.go +++ b/internal/controller/snapshot/snapshot_adapter.go @@ -92,55 +92,86 @@ func scenariosNamesToList(integrationTestScenarios *[]v1beta2.IntegrationTestSce // EnsureRerunPipelineRunsExist is responsible for recreating integration test pipelines triggered by users func (a *Adapter) EnsureRerunPipelineRunsExist() (controller.OperationResult, error) { + var integrationTestScenarios = &[]v1beta2.IntegrationTestScenario{} + var testStatuses *intgteststat.SnapshotIntegrationTestStatuses + var err error + skipScenarioRerunCount := 0 - scenarioName, ok := gitops.GetIntegrationTestRunLabelValue(a.snapshot) + rerunLabelValue, ok := gitops.GetIntegrationTestRunLabelValue(a.snapshot) if !ok { // no test rerun triggered return controller.ContinueProcessing() } - integrationTestScenario, err := a.loader.GetScenario(a.context, a.client, scenarioName, a.application.Namespace) - if err != nil { - if clienterrors.IsNotFound(err) { - a.logger.Error(err, "scenario for integration test re-run not found", "scenario", scenarioName) - // scenario doesn't exist just remove label and continue - if err = gitops.RemoveIntegrationTestRerunLabel(a.context, a.client, a.snapshot); err != nil { - return controller.RequeueWithError(err) + if rerunLabelValue == "all" { + allIntegrationTestScenarios, err := a.loader.GetAllIntegrationTestScenariosForApplication(a.context, a.client, a.application) + if err != nil { + a.logger.Error(err, "Failed to get Integration test scenarios for the following application", + "Application.Namespace", a.application.Namespace) + } + + if allIntegrationTestScenarios != nil { + integrationTestScenarios = gitops.FilterIntegrationTestScenariosWithContext(allIntegrationTestScenarios, a.snapshot) + a.logger.Info( + fmt.Sprintf("Found %d IntegrationTestScenarios for application", len(*integrationTestScenarios)), + "Application.Name", a.application.Name, + "IntegrationTestScenarios", len(*integrationTestScenarios)) + } + } else { + integrationTestScenario, err := a.loader.GetScenario(a.context, a.client, rerunLabelValue, a.application.Namespace) + if err != nil { + if clienterrors.IsNotFound(err) { + a.logger.Error(err, "scenario for integration test re-run not found", "scenario", rerunLabelValue) + // scenario doesn't exist just remove label and continue + if err = gitops.RemoveIntegrationTestRerunLabel(a.context, a.client, a.snapshot); err != nil { + return controller.RequeueWithError(err) + } + return controller.ContinueProcessing() } - return controller.ContinueProcessing() + return controller.RequeueWithError(fmt.Errorf("failed to fetch requested scenario %s: %w", rerunLabelValue, err)) } - return controller.RequeueWithError(fmt.Errorf("failed to fetch requested scenario %s: %w", scenarioName, err)) + *integrationTestScenarios = append(*integrationTestScenarios, *integrationTestScenario) } - a.logger.Info("Re-running integration test for scenario", "scenario", scenarioName) + for _, scenarioToRerun := range *integrationTestScenarios { + scenarioToRerun := scenarioToRerun + testStatuses, err = gitops.NewSnapshotIntegrationTestStatusesFromSnapshot(a.snapshot) + if err != nil { + return controller.RequeueWithError(err) + } - testStatuses, err := gitops.NewSnapshotIntegrationTestStatusesFromSnapshot(a.snapshot) - if err != nil { - return controller.RequeueWithError(err) - } + integrationTestScenarioStatus, ok := testStatuses.GetScenarioStatus(scenarioToRerun.Name) + if ok && (integrationTestScenarioStatus.Status == intgteststat.IntegrationTestStatusInProgress || + integrationTestScenarioStatus.Status == intgteststat.IntegrationTestStatusPending) { + a.logger.Info(fmt.Sprintf("Found existing test in %s status, skipping re-run", integrationTestScenarioStatus.Status), + "integrationTestScenario.Name", scenarioToRerun.Name) + skipScenarioRerunCount++ + continue + } + testStatuses.ResetStatus(scenarioToRerun.Name) - integrationTestScenarioStatus, ok := testStatuses.GetScenarioStatus(integrationTestScenario.Name) - if ok && (integrationTestScenarioStatus.Status == intgteststat.IntegrationTestStatusInProgress || - integrationTestScenarioStatus.Status == intgteststat.IntegrationTestStatusPending) { - a.logger.Info(fmt.Sprintf("Found existing test in %s status, skipping re-run", integrationTestScenarioStatus.Status), - "integrationTestScenario.Name", integrationTestScenario.Name) - if err = gitops.RemoveIntegrationTestRerunLabel(a.context, a.client, a.snapshot); err != nil { - return controller.RequeueWithError(err) + pipelineRun, err := a.createIntegrationPipelineRun(a.application, &scenarioToRerun, a.snapshot) + if err != nil { + return a.HandlePipelineCreationError(err, &scenarioToRerun, testStatuses) + } + + testStatuses.UpdateTestStatusIfChanged( + scenarioToRerun.Name, intgteststat.IntegrationTestStatusInProgress, + fmt.Sprintf("IntegrationTestScenario pipeline '%s' has been created", pipelineRun.Name)) + if err = testStatuses.UpdateTestPipelineRunName(scenarioToRerun.Name, pipelineRun.Name); err != nil { + // it doesn't make sense to restart reconciliation here, it will be eventually updated by integrationpipeline adapter + a.logger.Error(err, "Failed to update pipelinerun name in test status") } - return controller.ContinueProcessing() } - testStatuses.ResetStatus(scenarioName) - pipelineRun, err := a.createIntegrationPipelineRun(a.application, integrationTestScenario, a.snapshot) - if err != nil { - return a.HandlePipelineCreationError(err, integrationTestScenario, testStatuses) + if err = gitops.RemoveIntegrationTestRerunLabel(a.context, a.client, a.snapshot); err != nil { + return controller.RequeueWithError(err) } - testStatuses.UpdateTestStatusIfChanged( - integrationTestScenario.Name, intgteststat.IntegrationTestStatusInProgress, - fmt.Sprintf("IntegrationTestScenario pipeline '%s' has been created", pipelineRun.Name)) - if err = testStatuses.UpdateTestPipelineRunName(integrationTestScenario.Name, pipelineRun.Name); err != nil { - // it doesn't make sense to restart reconciliation here, it will be eventually updated by integrationpipeline adapter - a.logger.Error(err, "Failed to update pipelinerun name in test status") + + if skipScenarioRerunCount == len(*integrationTestScenarios) { + a.logger.Info("All of the requested IntegrationTestScenarios are either in 'InProgress' or 'Pending' state, skipping their re-runs", + "rerunLabel.Value", rerunLabelValue) + return controller.ContinueProcessing() } if err = gitops.WriteIntegrationTestStatusesIntoSnapshot(a.context, a.snapshot, testStatuses, a.client); err != nil { @@ -152,10 +183,6 @@ func (a *Adapter) EnsureRerunPipelineRunsExist() (controller.OperationResult, er return controller.RequeueWithError(err) } - if err = gitops.RemoveIntegrationTestRerunLabel(a.context, a.client, a.snapshot); err != nil { - return controller.RequeueWithError(err) - } - return controller.ContinueProcessing() }