diff --git a/controllers/integrationpipeline/integrationpipeline_adapter.go b/controllers/integrationpipeline/integrationpipeline_adapter.go index 755d765a0..fd9434f3e 100644 --- a/controllers/integrationpipeline/integrationpipeline_adapter.go +++ b/controllers/integrationpipeline/integrationpipeline_adapter.go @@ -212,6 +212,9 @@ func (a *Adapter) EnsureStatusReportedInSnapshot() (controller.OperationResult, return err } statuses.UpdateTestStatusIfChanged(a.pipelineRun.Labels[tekton.ScenarioNameLabel], status, detail) + if err = statuses.UpdateTestPipelineRunName(a.pipelineRun.Labels[tekton.ScenarioNameLabel], a.pipelineRun.Name); err != nil { + return err + } // don't return wrapped err for retries err = gitops.WriteIntegrationTestStatusesIntoSnapshot(snapshot, statuses, a.client, a.context) diff --git a/controllers/integrationpipeline/integrationpipeline_adapter_test.go b/controllers/integrationpipeline/integrationpipeline_adapter_test.go index 0bf35cdcb..33b19b317 100644 --- a/controllers/integrationpipeline/integrationpipeline_adapter_test.go +++ b/controllers/integrationpipeline/integrationpipeline_adapter_test.go @@ -859,7 +859,7 @@ var _ = Describe("Pipeline Adapter", Ordered, func() { }) - It("ensures test status ins snapshot is updated to failed", func() { + It("ensures test status in snapshot is updated to failed", func() { result, err := adapter.EnsureStatusReportedInSnapshot() Expect(!result.CancelRequest && err == nil).To(BeTrue()) @@ -869,6 +869,7 @@ var _ = Describe("Pipeline Adapter", Ordered, func() { detail, ok := statuses.GetScenarioStatus(integrationTestScenarioFailed.Name) Expect(ok).To(BeTrue()) Expect(detail.Status).To(Equal(gitops.IntegrationTestStatusTestFail)) + Expect(detail.TestPipelineRunName).To(Equal(integrationPipelineRunComponentFailed.Name)) }) }) diff --git a/gitops/snapshot_integration_tests_status.go b/gitops/snapshot_integration_tests_status.go index 5f45cdde3..f6fe209d6 100644 --- a/gitops/snapshot_integration_tests_status.go +++ b/gitops/snapshot_integration_tests_status.go @@ -52,6 +52,9 @@ const integrationTestStatusesSchema = `{ }, "completionTime": { "type": "string" + }, + "testPipelineRunName": { + "type": "string" } }, "required": ["scenario", "status", "lastUpdateTime"] @@ -72,6 +75,8 @@ type IntegrationTestStatusDetail struct { StartTime *time.Time `json:"startTime,omitempty"` // pointer to make omitempty work // Completion time when test failed or passed CompletionTime *time.Time `json:"completionTime,omitempty"` // pointer to make omitempty work + // TestPipelineName name of testing pipelineRun + TestPipelineRunName string `json:"testPipelineRunName,omitempty"` } // SnapshotIntegrationTestStatuses type handles details about snapshot tests @@ -144,6 +149,21 @@ func (sits *SnapshotIntegrationTestStatuses) UpdateTestStatusIfChanged(scenarioN } +// UpdatePipelineRunName updates TestPipelineRunName if changed +// scenario must already exist in statuses +func (sits *SnapshotIntegrationTestStatuses) UpdateTestPipelineRunName(scenarioName string, pipelineRunName string) error { + detail, ok := sits.GetScenarioStatus(scenarioName) + if !ok { + return fmt.Errorf("scenario name %s not found and cannot be updated", scenarioName) + } + + if detail.TestPipelineRunName != pipelineRunName { + detail.TestPipelineRunName = pipelineRunName + sits.dirty = true + } + return nil +} + // InitStatuses creates initial representation all scenarios // This function also removes scenarios which are not defined in scenarios param func (sits *SnapshotIntegrationTestStatuses) InitStatuses(scenarios *[]v1beta1.IntegrationTestScenario) { @@ -208,7 +228,8 @@ func (sits *SnapshotIntegrationTestStatuses) GetScenarioStatus(scenarioName stri // "lastUpdateTime": "2023-07-26T16:57:49+02:00", // "details": "Failed ...", // "startTime": "2023-07-26T14:57:49+02:00", -// "completionTime": "2023-07-26T16:57:49+02:00" +// "completionTime": "2023-07-26T16:57:49+02:00", +// "testPipelineRunName": "pipeline-run-feedbeef" // } // ] func (sits *SnapshotIntegrationTestStatuses) MarshalJSON() ([]byte, error) { diff --git a/gitops/snapshot_integration_tests_status_test.go b/gitops/snapshot_integration_tests_status_test.go index 2186cdfba..3c6d7252e 100644 --- a/gitops/snapshot_integration_tests_status_test.go +++ b/gitops/snapshot_integration_tests_status_test.go @@ -70,6 +70,7 @@ var _ = Describe("Snapshot integration test statuses", func() { applicationName = "application-sample" componentName = "component-sample" snapshotName = "snapshot-sample" + pipelineRunName = "pipeline-run-abcdf" ) var ( sits *gitops.SnapshotIntegrationTestStatuses @@ -221,6 +222,46 @@ var _ = Describe("Snapshot integration test statuses", func() { Expect(newDetail.LastUpdateTime).NotTo(Equal(originalLastUpdateTime)) }) + It("can update details with pipeline run name", func() { + // test detail must exist first + sits.UpdateTestStatusIfChanged(testScenarioName, gitops.IntegrationTestStatusInProgress, testDetails) + sits.ResetDirty() + + err := sits.UpdateTestPipelineRunName(testScenarioName, pipelineRunName) + Expect(err).To(BeNil()) + + detail, ok := sits.GetScenarioStatus(testScenarioName) + Expect(ok).To(BeTrue()) + Expect(detail.TestPipelineRunName).To(Equal(pipelineRunName)) + Expect(sits.IsDirty()).To(BeTrue()) + + // other data hasn't been removed + Expect(detail.ScenarioName).To(Equal(testScenarioName)) + Expect(detail.Details).To(Equal(testDetails)) + Expect(detail.Status).To(Equal(gitops.IntegrationTestStatusInProgress)) + }) + + It("doesn't update the same pipeline run name twice", func() { + // test detail must exist first + sits.UpdateTestStatusIfChanged(testScenarioName, gitops.IntegrationTestStatusInProgress, testDetails) + sits.ResetDirty() + + err := sits.UpdateTestPipelineRunName(testScenarioName, pipelineRunName) + Expect(err).To(BeNil()) + Expect(sits.IsDirty()).To(BeTrue()) + sits.ResetDirty() + + err = sits.UpdateTestPipelineRunName(testScenarioName, pipelineRunName) + Expect(err).To(BeNil()) + + Expect(sits.IsDirty()).To(BeFalse()) + }) + + It("fails to update details with pipeline run name when testScenario doesn't exist", func() { + err := sits.UpdateTestPipelineRunName(testScenarioName, pipelineRunName) + Expect(err).NotTo(BeNil()) + }) + It("Can export valid JSON without start and completion time (Pending)", func() { sits.UpdateTestStatusIfChanged(testScenarioName, gitops.IntegrationTestStatusPending, testDetails) detail, ok := sits.GetScenarioStatus(testScenarioName) @@ -321,6 +362,31 @@ var _ = Describe("Snapshot integration test statuses", func() { Expect(json.Marshal(sits)).To(MatchJSON(expected)) }) + It("Can export valid JSON with TestPipelineRunName", func() { + sits.UpdateTestStatusIfChanged(testScenarioName, gitops.IntegrationTestStatusPending, testDetails) + err := sits.UpdateTestPipelineRunName(testScenarioName, pipelineRunName) + Expect(err).To(BeNil()) + + detail, ok := sits.GetScenarioStatus(testScenarioName) + Expect(ok).To(BeTrue()) + + expectedFormatStr := `[ + { + "scenario": "%s", + "status": "Pending", + "lastUpdateTime": "%s", + "details": "%s", + "testPipelineRunName": "%s" + } + ]` + marshaledTime, err := detail.LastUpdateTime.MarshalText() + Expect(err).To(BeNil()) + expectedStr := fmt.Sprintf(expectedFormatStr, testScenarioName, marshaledTime, testDetails, pipelineRunName) + expected := []byte(expectedStr) + + Expect(json.Marshal(sits)).To(MatchJSON(expected)) + }) + When("Contains updates to status", func() { BeforeEach(func() {