diff --git a/docs/statusreport-controller.md b/docs/statusreport-controller.md
index 7a25824e2..3cd8d86aa 100644
--- a/docs/statusreport-controller.md
+++ b/docs/statusreport-controller.md
@@ -34,6 +34,7 @@ flowchart TD
%% Node definitions
ensure(Process further if: Snapshot has label
pac.test.appstudio.openshift.io/git-provider:github
defined)
get_annotation_value(Get integration test status from annotation
test.appstudio.openshift.io/status
from Snapshot)
+ get_destination_snapshot(Get destination snapshots from
component snapshot or group snapshot
to collect git provider info)
detect_git_provider{Detect git provider}
@@ -70,7 +71,8 @@ flowchart TD
%% Node connections
predicate ----> |"EnsureSnapshotTestStatusReportedToGitProvider()"|ensure
ensure --> get_annotation_value
- get_annotation_value --> detect_git_provider
+ get_annotation_value --> get_destination_snapshot
+ get_destination_snapshot --> detect_git_provider
detect_git_provider --github--> collect_commit_info_gh
detect_git_provider --gitlab--> collect_commit_info_gl
collect_commit_info_gh --> is_installation_defined
diff --git a/gitops/snapshot.go b/gitops/snapshot.go
index fedbbc556..8ddc210c9 100644
--- a/gitops/snapshot.go
+++ b/gitops/snapshot.go
@@ -936,6 +936,7 @@ func IsComponentSnapshot(snapshot *applicationapiv1alpha1.Snapshot) bool {
return metadata.HasLabelWithValue(snapshot, SnapshotTypeLabel, SnapshotComponentType)
}
+// IsGroupSnapshot returns true if snapshot label 'test.appstudio.openshift.io/type' is 'group'
func IsGroupSnapshot(snapshot *applicationapiv1alpha1.Snapshot) bool {
return metadata.HasLabelWithValue(snapshot, SnapshotTypeLabel, SnapshotGroupType)
}
diff --git a/internal/controller/statusreport/statusreport_adapter.go b/internal/controller/statusreport/statusreport_adapter.go
index 712180446..e195e088d 100644
--- a/internal/controller/statusreport/statusreport_adapter.go
+++ b/internal/controller/statusreport/statusreport_adapter.go
@@ -18,11 +18,13 @@ package statusreport
import (
"context"
+ e "errors"
"fmt"
"time"
applicationapiv1alpha1 "github.com/konflux-ci/application-api/api/v1alpha1"
"github.com/konflux-ci/operator-toolkit/controller"
+ "k8s.io/client-go/util/retry"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/konflux-ci/integration-service/api/v1beta2"
@@ -66,19 +68,14 @@ func NewAdapter(context context.Context, snapshot *applicationapiv1alpha1.Snapsh
// EnsureSnapshotTestStatusReportedToGitProvider will ensure that integration test status is reported to the git provider
// which (indirectly) triggered its execution.
+// The status is reported to git provider if it is a component snapshot
+// Or reported to git providers which trigger component snapshots included in group snapshot if it is a group snapshot
func (a *Adapter) EnsureSnapshotTestStatusReportedToGitProvider() (controller.OperationResult, error) {
- if gitops.IsSnapshotCreatedByPACPushEvent(a.snapshot) {
+ if gitops.IsSnapshotCreatedByPACPushEvent(a.snapshot) && !gitops.IsGroupSnapshot(a.snapshot) {
return controller.ContinueProcessing()
}
- reporter := a.status.GetReporter(a.snapshot)
- if reporter == nil {
- a.logger.Info("No suitable reporter found, skipping report")
- return controller.ContinueProcessing()
- }
- a.logger.Info(fmt.Sprintf("Detected reporter: %s", reporter.GetReporterName()))
-
- err := a.status.ReportSnapshotStatus(a.context, reporter, a.snapshot)
+ err := a.ReportSnapshotStatus(a.snapshot)
if err != nil {
a.logger.Error(err, "failed to report test status to git provider for snapshot",
"snapshot.Namespace", a.snapshot.Namespace, "snapshot.Name", a.snapshot.Name)
@@ -238,3 +235,137 @@ func (a *Adapter) findUntriggeredIntegrationTestFromStatus(integrationTestScenar
}
return ""
}
+
+// ReportSnapshotStatus reports status of all integration tests into Pull Requests from component snapshot or group snapshot
+func (a *Adapter) ReportSnapshotStatus(testedSnapshot *applicationapiv1alpha1.Snapshot) error {
+
+ statuses, err := gitops.NewSnapshotIntegrationTestStatusesFromSnapshot(testedSnapshot)
+ if err != nil {
+ a.logger.Error(err, "failed to get test status annotations from snapshot",
+ "snapshot.Namespace", testedSnapshot.Namespace, "snapshot.Name", testedSnapshot.Name)
+ return err
+ }
+
+ integrationTestStatusDetails := statuses.GetStatuses()
+ if len(integrationTestStatusDetails) == 0 {
+ // no tests to report, skip
+ a.logger.Info("No test result to report to GitHub, skipping",
+ "snapshot.Namespace", testedSnapshot.Namespace, "snapshot.Name", testedSnapshot.Name)
+ return nil
+ }
+
+ // get the component snapshot list that include the git provider info the report will be reported to
+ destinationSnapshots, err := a.getDestinationSnapshots(testedSnapshot)
+ if err != nil {
+ a.logger.Error(err, "failed to get component snapshots from group snapshot",
+ "snapshot.NameSpace", testedSnapshot.Namespace, "snapshot.Name", testedSnapshot.Name)
+ return fmt.Errorf("failed to get component snapshots from snapshot %s/%s", testedSnapshot.Namespace, testedSnapshot.Name)
+ }
+
+ status.MigrateSnapshotToReportStatus(testedSnapshot, integrationTestStatusDetails)
+
+ srs, err := status.NewSnapshotReportStatusFromSnapshot(testedSnapshot)
+ if err != nil {
+ a.logger.Error(err, "failed to get latest snapshot write metadata annotation for snapshot",
+ "snapshot.NameSpace", testedSnapshot.Namespace, "snapshot.Name", testedSnapshot.Name)
+ srs, _ = status.NewSnapshotReportStatus("")
+ }
+
+ // Report the integration test status to pr/commit included in the tested component snapshot
+ // or the component snapshot included in group snapshot
+ for _, destinationComponentSnapshot := range destinationSnapshots {
+ destinationComponentSnapshot := destinationComponentSnapshot
+ reporter := a.status.GetReporter(destinationComponentSnapshot)
+ if reporter == nil {
+ a.logger.Info("No suitable reporter found, skipping report")
+ continue
+ }
+ a.logger.Info(fmt.Sprintf("Detected reporter: %s", reporter.GetReporterName()))
+
+ if err := reporter.Initialize(a.context, destinationComponentSnapshot); err != nil {
+ a.logger.Error(err, "Failed to initialize reporter", "reporter", reporter.GetReporterName())
+ return fmt.Errorf("failed to initialize reporter: %w", err)
+ }
+ a.logger.Info("Reporter initialized", "reporter", reporter.GetReporterName())
+
+ err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
+ err := a.iterateIntegrationTestStatusDetailsInStatusReport(reporter, integrationTestStatusDetails, testedSnapshot, destinationComponentSnapshot, srs)
+ if err != nil {
+ return fmt.Errorf("failed to report integration test status for snapshot %s/%s: %w",
+ destinationComponentSnapshot.Namespace, destinationComponentSnapshot.Name, err)
+ }
+ if err := status.WriteSnapshotReportStatus(a.context, a.client, testedSnapshot, srs); err != nil {
+ return fmt.Errorf("failed to write snapshot report status metadata: %w", err)
+ }
+ return err
+ })
+ }
+
+ if err != nil {
+ return fmt.Errorf("issue occured during generating or updating report status: %w", err)
+ }
+
+ a.logger.Info(fmt.Sprintf("Successfully updated the %s annotation", gitops.SnapshotStatusReportAnnotation), "snapshot.Name", testedSnapshot.Name)
+
+ return nil
+}
+
+// iterates iterateIntegrationTestStatusDetails to report to destination snapshot for them
+func (a *Adapter) iterateIntegrationTestStatusDetailsInStatusReport(reporter status.ReporterInterface,
+ integrationTestStatusDetails []*intgteststat.IntegrationTestStatusDetail,
+ testedSnapshot *applicationapiv1alpha1.Snapshot,
+ destinationSnapshot *applicationapiv1alpha1.Snapshot,
+ srs *status.SnapshotReportStatus) error {
+ // set componentName to component name of component snapshot or pr group name of group snapshot when reporting status to git provider
+ componentName := ""
+ if gitops.IsGroupSnapshot(testedSnapshot) {
+ componentName = "pr group " + testedSnapshot.Annotations[gitops.PRGroupAnnotation]
+ } else if gitops.IsComponentSnapshot(testedSnapshot) {
+ componentName = testedSnapshot.Labels[gitops.SnapshotComponentLabel]
+ } else {
+ return fmt.Errorf("unsupported snapshot type: %s", testedSnapshot.Annotations[gitops.SnapshotTypeLabel])
+ }
+
+ for _, integrationTestStatusDetail := range integrationTestStatusDetails {
+ if srs.IsNewer(integrationTestStatusDetail.ScenarioName, integrationTestStatusDetail.LastUpdateTime) {
+ a.logger.Info("Integration Test contains new status updates", "scenario.Name", integrationTestStatusDetail.ScenarioName)
+ } else {
+ //integration test contains no changes
+ continue
+ }
+ testReport, reportErr := status.GenerateTestReport(a.context, a.client, *integrationTestStatusDetail, testedSnapshot, componentName)
+ if reportErr != nil {
+ if writeErr := status.WriteSnapshotReportStatus(a.context, a.client, testedSnapshot, srs); writeErr != nil { // try to write what was already written
+ return fmt.Errorf("failed to generate test report AND write snapshot report status metadata: %w", e.Join(reportErr, writeErr))
+ }
+ return fmt.Errorf("failed to generate test report: %w", reportErr)
+ }
+ if reportStatusErr := reporter.ReportStatus(a.context, *testReport); reportStatusErr != nil {
+ if writeErr := status.WriteSnapshotReportStatus(a.context, a.client, testedSnapshot, srs); writeErr != nil { // try to write what was already written
+ return fmt.Errorf("failed to report status AND write snapshot report status metadata: %w", e.Join(reportStatusErr, writeErr))
+ }
+ return fmt.Errorf("failed to update status: %w", reportStatusErr)
+ }
+ srs.SetLastUpdateTime(integrationTestStatusDetail.ScenarioName, integrationTestStatusDetail.LastUpdateTime)
+ }
+ return nil
+}
+
+// getDestinationSnapshots gets the component snapshots that include the git provider info the report will be reported to
+func (a *Adapter) getDestinationSnapshots(testedSnapshot *applicationapiv1alpha1.Snapshot) ([]*applicationapiv1alpha1.Snapshot, error) {
+ destinationSnapshots := make([]*applicationapiv1alpha1.Snapshot, 0)
+ if gitops.IsComponentSnapshot(testedSnapshot) {
+ destinationSnapshots = append(destinationSnapshots, testedSnapshot)
+ return destinationSnapshots, nil
+ } else if gitops.IsGroupSnapshot(testedSnapshot) {
+ // get component snapshots from group snapshot annotation GroupSnapshotInfoAnnotation
+ destinationSnapshots, err := status.GetComponentSnapshotsFromGroupSnapshot(a.context, a.client, testedSnapshot)
+ if err != nil {
+ a.logger.Error(err, "failed to get component snapshots included in group snapshot",
+ "snapshot.NameSpace", testedSnapshot.Namespace, "snapshot.Name", testedSnapshot.Name)
+ return nil, fmt.Errorf("failed to get component snapshots included in group snapshot %s/%s", testedSnapshot.Namespace, testedSnapshot.Name)
+ }
+ return destinationSnapshots, nil
+ }
+ return nil, fmt.Errorf("unsupported snapshot type in snapshot %s/%s", testedSnapshot.Namespace, testedSnapshot.Name)
+}
diff --git a/internal/controller/statusreport/statusreport_adapter_test.go b/internal/controller/statusreport/statusreport_adapter_test.go
index 89997d2bd..14aa6d62a 100644
--- a/internal/controller/statusreport/statusreport_adapter_test.go
+++ b/internal/controller/statusreport/statusreport_adapter_test.go
@@ -19,7 +19,10 @@ package statusreport
import (
"bytes"
"fmt"
+ "os"
"reflect"
+ "strconv"
+ "time"
"github.com/konflux-ci/integration-service/api/v1beta2"
"github.com/tonglil/buflogr"
@@ -44,22 +47,34 @@ import (
var _ = Describe("Snapshot Adapter", Ordered, func() {
var (
- adapter *Adapter
- logger helpers.IntegrationLogger
- buf bytes.Buffer
+ adapter *Adapter
+ logger helpers.IntegrationLogger
+ buf bytes.Buffer
+ mockReporter *status.MockReporterInterface
+ mockStatus *status.MockStatusInterface
hasComp *applicationapiv1alpha1.Component
hasComp2 *applicationapiv1alpha1.Component
hasApp *applicationapiv1alpha1.Application
hasSnapshot *applicationapiv1alpha1.Snapshot
hasPRSnapshot *applicationapiv1alpha1.Snapshot
+ hasComSnapshot2 *applicationapiv1alpha1.Snapshot
+ hasComSnapshot3 *applicationapiv1alpha1.Snapshot
+ groupSnapshot *applicationapiv1alpha1.Snapshot
+ githubSnapshot *applicationapiv1alpha1.Snapshot
integrationTestScenario *v1beta2.IntegrationTestScenario
)
const (
- SampleRepoLink = "https://github.com/devfile-samples/devfile-sample-java-springboot-basic"
- SampleImage = "quay.io/redhat-appstudio/sample-image@sha256:841328df1b9f8c4087adbdcfec6cc99ac8308805dea83f6d415d6fb8d40227c1"
- SampleCommit = "a2ba645d50e471d5f084b"
- SampleRevision = "random-value"
+ SampleRepoLink = "https://github.com/devfile-samples/devfile-sample-java-springboot-basic"
+ SampleImage = "quay.io/redhat-appstudio/sample-image@sha256:841328df1b9f8c4087adbdcfec6cc99ac8308805dea83f6d415d6fb8d40227c1"
+ SampleDigest = "sha256:841328df1b9f8c4087adbdcfec6cc99ac8308805dea83f6d415d6fb8d40227c1"
+ SampleCommit = "a2ba645d50e471d5f084b"
+ SampleRevision = "random-value"
+ hasComSnapshot2Name = "hascomsnapshot2-sample"
+ hasComSnapshot3Name = "hascomsnapshot3-sample"
+ prGroup = "feature1"
+ prGroupSha = "feature1hash"
+ plrstarttime = 1775992257
)
BeforeAll(func() {
@@ -116,6 +131,114 @@ var _ = Describe("Snapshot Adapter", Ordered, func() {
},
}
Expect(k8sClient.Create(ctx, hasComp2)).Should(Succeed())
+
+ hasComSnapshot2 = &applicationapiv1alpha1.Snapshot{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: hasComSnapshot2Name,
+ Namespace: "default",
+ Labels: map[string]string{
+ gitops.SnapshotTypeLabel: gitops.SnapshotComponentType,
+ gitops.SnapshotComponentLabel: hasComSnapshot2Name,
+ gitops.PipelineAsCodeEventTypeLabel: gitops.PipelineAsCodePullRequestType,
+ gitops.PRGroupHashLabel: prGroupSha,
+ "pac.test.appstudio.openshift.io/url-org": "testorg",
+ "pac.test.appstudio.openshift.io/url-repository": "testrepo",
+ gitops.PipelineAsCodeSHALabel: "sha",
+ gitops.PipelineAsCodePullRequestAnnotation: "1",
+ },
+ Annotations: map[string]string{
+ "test.appstudio.openshift.io/pr-last-update": "2023-08-26T17:57:50+02:00",
+ gitops.BuildPipelineRunStartTime: strconv.Itoa(plrstarttime + 100),
+ gitops.PRGroupAnnotation: prGroup,
+ gitops.PipelineAsCodeGitProviderAnnotation: "github",
+ gitops.PipelineAsCodeInstallationIDAnnotation: "123",
+ },
+ },
+ Spec: applicationapiv1alpha1.SnapshotSpec{
+ Application: hasApp.Name,
+ Components: []applicationapiv1alpha1.SnapshotComponent{
+ {
+ Name: hasComSnapshot3Name,
+ ContainerImage: SampleImage + "@" + SampleDigest,
+ },
+ {
+ Name: hasComSnapshot2Name,
+ ContainerImage: SampleImage + "@" + SampleDigest,
+ },
+ },
+ },
+ }
+ Expect(k8sClient.Create(ctx, hasComSnapshot2)).Should(Succeed())
+
+ hasComSnapshot3 = &applicationapiv1alpha1.Snapshot{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: hasComSnapshot3Name,
+ Namespace: "default",
+ Labels: map[string]string{
+ gitops.SnapshotTypeLabel: gitops.SnapshotComponentType,
+ gitops.SnapshotComponentLabel: hasComSnapshot3Name,
+ gitops.PipelineAsCodeEventTypeLabel: gitops.PipelineAsCodePullRequestType,
+ gitops.PRGroupHashLabel: prGroupSha,
+ "pac.test.appstudio.openshift.io/url-org": "testorg",
+ "pac.test.appstudio.openshift.io/url-repository": "testrepo",
+ gitops.PipelineAsCodeSHALabel: "sha",
+ gitops.PipelineAsCodePullRequestAnnotation: "1",
+ },
+ Annotations: map[string]string{
+ "test.appstudio.openshift.io/pr-last-update": "2023-08-26T17:57:50+02:00",
+ gitops.BuildPipelineRunStartTime: strconv.Itoa(plrstarttime + 200),
+ gitops.PRGroupAnnotation: prGroup,
+ gitops.PipelineAsCodeGitProviderAnnotation: "github",
+ gitops.PipelineAsCodePullRequestAnnotation: "1",
+ gitops.PipelineAsCodeInstallationIDAnnotation: "123",
+ },
+ },
+ Spec: applicationapiv1alpha1.SnapshotSpec{
+ Application: hasApp.Name,
+ Components: []applicationapiv1alpha1.SnapshotComponent{
+ {
+ Name: hasComSnapshot2Name,
+ ContainerImage: SampleImage + "@" + SampleDigest,
+ },
+ {
+ Name: hasComSnapshot3Name,
+ ContainerImage: SampleImage + "@" + SampleDigest,
+ },
+ },
+ },
+ }
+ Expect(k8sClient.Create(ctx, hasComSnapshot3)).Should(Succeed())
+
+ groupSnapshot = &applicationapiv1alpha1.Snapshot{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "groupsnapshot",
+ Namespace: "default",
+ Labels: map[string]string{
+ gitops.SnapshotTypeLabel: gitops.SnapshotGroupType,
+ gitops.PipelineAsCodeEventTypeLabel: gitops.PipelineAsCodePullRequestType,
+ gitops.PRGroupHashLabel: prGroupSha,
+ },
+ Annotations: map[string]string{
+ gitops.PRGroupAnnotation: prGroup,
+ gitops.GroupSnapshotInfoAnnotation: "[{\"namespace\":\"default\",\"component\":\"component1-sample\",\"buildPipelineRun\":\"\",\"snapshot\":\"hascomsnapshot2-sample\"},{\"namespace\":\"default\",\"component\":\"component3-sample\",\"buildPipelineRun\":\"\",\"snapshot\":\"hascomsnapshot3-sample\"}]",
+ gitops.SnapshotTestsStatusAnnotation: "[{\"scenario\":\"scenario-1\",\"status\":\"EnvironmentProvisionError\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"completionTime\":\"2023-07-26T17:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:49+02:00\",\"details\":\"Failed to find deploymentTargetClass with right provisioner for copy of existingEnvironment\"}]",
+ },
+ },
+ Spec: applicationapiv1alpha1.SnapshotSpec{
+ Application: hasApp.Name,
+ Components: []applicationapiv1alpha1.SnapshotComponent{
+ {
+ Name: hasComSnapshot2Name,
+ ContainerImage: SampleImage + "@" + SampleDigest,
+ },
+ {
+ Name: hasComSnapshot3Name,
+ ContainerImage: SampleImage + "@" + SampleDigest,
+ },
+ },
+ },
+ }
+ Expect(k8sClient.Create(ctx, groupSnapshot)).Should(Succeed())
})
AfterAll(func() {
@@ -125,6 +248,12 @@ var _ = Describe("Snapshot Adapter", Ordered, func() {
Expect(err == nil || errors.IsNotFound(err)).To(BeTrue())
err = k8sClient.Delete(ctx, hasComp2)
Expect(err == nil || errors.IsNotFound(err)).To(BeTrue())
+ err = k8sClient.Delete(ctx, groupSnapshot)
+ Expect(err == nil || errors.IsNotFound(err)).To(BeTrue())
+ err = k8sClient.Delete(ctx, hasComSnapshot2)
+ Expect(err == nil || errors.IsNotFound(err)).To(BeTrue())
+ err = k8sClient.Delete(ctx, hasComSnapshot3)
+ Expect(err == nil || errors.IsNotFound(err)).To(BeTrue())
})
BeforeEach(func() {
@@ -151,10 +280,11 @@ var _ = Describe("Snapshot Adapter", Ordered, func() {
},
},
}
+ Expect(k8sClient.Create(ctx, hasSnapshot)).Should(Succeed())
hasPRSnapshot = &applicationapiv1alpha1.Snapshot{
ObjectMeta: metav1.ObjectMeta{
- Name: "snapshot-PR-sample",
+ Name: "snapshot-pr-sample",
Namespace: "default",
Labels: map[string]string{
gitops.SnapshotTypeLabel: "component",
@@ -172,6 +302,7 @@ var _ = Describe("Snapshot Adapter", Ordered, func() {
"build.appstudio.redhat.com/commit_sha": "6c65b2fcaea3e1a0a92476c8b5dc89e92a85f025",
"appstudio.redhat.com/updateComponentOnSuccess": "false",
gitops.SnapshotTestsStatusAnnotation: "[{\"scenario\":\"scenario-1\",\"status\":\"EnvironmentProvisionError\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"completionTime\":\"2023-07-26T17:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:49+02:00\",\"details\":\"Failed to find deploymentTargetClass with right provisioner for copy of existingEnvironment\"}]",
+ gitops.PipelineAsCodeGitProviderAnnotation: gitops.PipelineAsCodeGitHubProviderType,
},
},
Spec: applicationapiv1alpha1.SnapshotSpec{
@@ -191,7 +322,7 @@ var _ = Describe("Snapshot Adapter", Ordered, func() {
},
},
}
- Expect(k8sClient.Create(ctx, hasSnapshot)).Should(Succeed())
+ Expect(k8sClient.Create(ctx, hasPRSnapshot)).Should(Succeed())
integrationTestScenario = &v1beta2.IntegrationTestScenario{
ObjectMeta: metav1.ObjectMeta{
@@ -223,6 +354,7 @@ var _ = Describe("Snapshot Adapter", Ordered, func() {
},
},
}
+
Expect(k8sClient.Create(ctx, integrationTestScenario)).Should(Succeed())
})
@@ -240,17 +372,17 @@ var _ = Describe("Snapshot Adapter", Ordered, func() {
Expect(reflect.TypeOf(NewAdapter(ctx, hasSnapshot, hasApp, logger, loader.NewMockLoader(), k8sClient))).To(Equal(reflect.TypeOf(&Adapter{})))
})
- It("ensures the statusReport is called", func() {
+ It("ensures the statusReport is called for component snapshot", func() {
ctrl := gomock.NewController(GinkgoT())
- mockReporter := status.NewMockReporterInterface(ctrl)
+ mockReporter = status.NewMockReporterInterface(ctrl)
mockStatus := status.NewMockStatusInterface(ctrl)
-
- mockReporter.EXPECT().GetReporterName().Return("mocked_reporter")
-
+ mockReporter.EXPECT().GetReporterName().Return("mocked-reporter").AnyTimes()
mockStatus.EXPECT().GetReporter(gomock.Any()).Return(mockReporter)
- // ReportSnapshotStatus must be called once
- mockStatus.EXPECT().ReportSnapshotStatus(gomock.Any(), gomock.Any(), gomock.Any()).Times(1)
+ mockStatus.EXPECT().GetReporter(gomock.Any()).AnyTimes()
+ mockReporter.EXPECT().GetReporterName().AnyTimes()
+ mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
+ mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Any()).Times(1)
mockScenarios := []v1beta2.IntegrationTestScenario{}
adapter = NewAdapter(ctx, hasPRSnapshot, hasApp, logger, loader.NewMockLoader(), k8sClient)
@@ -274,6 +406,37 @@ var _ = Describe("Snapshot Adapter", Ordered, func() {
fmt.Fprintf(GinkgoWriter, "-------result: %v\n", result)
Expect(!result.CancelRequest && err == nil).To(BeTrue())
})
+
+ It("ensures the statusReport is called for group snapshot", func() {
+ buf = bytes.Buffer{}
+ log := helpers.IntegrationLogger{Logger: buflogr.NewWithBuffer(&buf)}
+ ctrl := gomock.NewController(GinkgoT())
+ mockReporter = status.NewMockReporterInterface(ctrl)
+ mockStatus := status.NewMockStatusInterface(ctrl)
+ mockReporter.EXPECT().GetReporterName().Return("mocked-reporter").AnyTimes()
+ mockStatus.EXPECT().GetReporter(gomock.Any()).Return(mockReporter)
+ mockStatus.EXPECT().GetReporter(gomock.Any()).AnyTimes()
+ mockReporter.EXPECT().GetReporterName().AnyTimes()
+ mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
+ mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Any()).Times(1)
+
+ mockScenarios := []v1beta2.IntegrationTestScenario{}
+ adapter = NewAdapter(ctx, groupSnapshot, hasApp, log, loader.NewMockLoader(), k8sClient)
+ adapter.status = mockStatus
+ adapter.context = toolkit.GetMockedContext(ctx, []toolkit.MockData{
+ {
+ ContextKey: loader.ApplicationContextKey,
+ Resource: hasApp,
+ },
+ {
+ ContextKey: loader.RequiredIntegrationTestScenariosContextKey,
+ Resource: mockScenarios,
+ },
+ })
+ result, err := adapter.EnsureSnapshotTestStatusReportedToGitProvider()
+ fmt.Fprintf(GinkgoWriter, "-------test: %v\n", buf.String())
+ Expect(!result.CancelRequest && err == nil).To(BeTrue())
+ })
})
When("New Adapter is created for a push-type Snapshot that passed all tests", func() {
@@ -535,4 +698,113 @@ var _ = Describe("Snapshot Adapter", Ordered, func() {
})
})
+
+ When("", func() {
+ BeforeEach(func() {
+ buf = bytes.Buffer{}
+
+ githubSnapshot = &applicationapiv1alpha1.Snapshot{
+ ObjectMeta: metav1.ObjectMeta{
+ Labels: map[string]string{
+ "pac.test.appstudio.openshift.io/git-provider": "github",
+ },
+ },
+ }
+
+ ctrl := gomock.NewController(GinkgoT())
+ mockReporter = status.NewMockReporterInterface(ctrl)
+ mockReporter.EXPECT().GetReporterName().Return("mocked-reporter").AnyTimes()
+ mockStatus = status.NewMockStatusInterface(ctrl)
+ })
+ It("doesn't report anything when there are not test results", func() {
+ mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(0) // without test results reporter shouldn't be initialized
+ mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Any()).Times(0) // without test results reported shouldn't report status
+
+ adapter = NewAdapter(ctx, githubSnapshot, hasApp, logger, loader.NewMockLoader(), k8sClient)
+ adapter.status = mockStatus
+ err := adapter.ReportSnapshotStatus(githubSnapshot)
+ Expect(err).NotTo(HaveOccurred())
+ })
+
+ It("doesn't report anything when data are older", func() {
+ mockStatus.EXPECT().GetReporter(gomock.Any()).Return(mockReporter)
+ mockStatus.EXPECT().GetReporter(gomock.Any()).AnyTimes()
+ mockReporter.EXPECT().GetReporterName().AnyTimes()
+
+ mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
+ mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Any()).Times(0) // data are older, status shouldn't be reported
+
+ hasPRSnapshot.Annotations["test.appstudio.openshift.io/status"] = "[{\"scenario\":\"scenario1\",\"status\":\"InProgress\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:50+02:00\",\"details\":\"Test in progress\"}]"
+ hasPRSnapshot.Annotations["test.appstudio.openshift.io/git-reporter-status"] = "{\"scenarios\":{\"scenario1\":{\"lastUpdateTime\":\"2023-08-26T17:57:50+02:00\"}}}"
+ adapter = NewAdapter(ctx, hasPRSnapshot, hasApp, logger, loader.NewMockLoader(), k8sClient)
+ adapter.status = mockStatus
+ err := adapter.ReportSnapshotStatus(adapter.snapshot)
+ Expect(err).NotTo(HaveOccurred())
+ })
+
+ It("Report new status if it was updated", func() {
+ mockStatus.EXPECT().GetReporter(gomock.Any()).Return(mockReporter)
+ mockStatus.EXPECT().GetReporter(gomock.Any()).AnyTimes()
+ mockReporter.EXPECT().GetReporterName().AnyTimes()
+
+ mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
+ mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Any()).Times(1)
+
+ hasPRSnapshot.Annotations["test.appstudio.openshift.io/status"] = "[{\"scenario\":\"scenario1\",\"status\":\"InProgress\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:50+02:00\",\"details\":\"Test in progress\"}]"
+ hasPRSnapshot.Annotations["test.appstudio.openshift.io/git-reporter-status"] = "{\"scenarios\":{\"scenario1\":{\"lastUpdateTime\":\"2023-08-26T17:57:49+02:00\"}}}"
+ hasPRSnapshot.Annotations["test.appstudio.openshift.io/group-test-info"] = "[{\"namespace\":\"default\",\"component\":\"devfile-sample-java-springboot-basic-8969\",\"buildPipelineRun\":\"build-plr-java-qjfxz\",\"snapshot\":\"app-8969-bbn7d\"},{\"namespace\":\"default\",\"component\":\"devfile-sample-go-basic-8969\",\"buildPipelineRun\":\"build-plr-go-jmsjq\",\"snapshot\":\"app-8969-kzq2l\"}]"
+ adapter = NewAdapter(ctx, hasPRSnapshot, hasApp, logger, loader.NewMockLoader(), k8sClient)
+ adapter.status = mockStatus
+ err := adapter.ReportSnapshotStatus(adapter.snapshot)
+ Expect(err).NotTo(HaveOccurred())
+ })
+
+ It("Report new status if it was updated (old way - migration test)", func() {
+ mockStatus.EXPECT().GetReporter(gomock.Any()).Return(mockReporter)
+ mockStatus.EXPECT().GetReporter(gomock.Any()).AnyTimes()
+ mockReporter.EXPECT().GetReporterName().AnyTimes()
+
+ mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
+ mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Any()).Times(1)
+
+ hasPRSnapshot.Annotations["test.appstudio.openshift.io/status"] = "[{\"scenario\":\"scenario1\",\"status\":\"InProgress\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:50+02:00\",\"details\":\"Test in progress\"}]"
+ hasPRSnapshot.Annotations["test.appstudio.openshift.io/pr-last-update"] = "2023-08-26T17:57:49+02:00"
+ adapter = NewAdapter(ctx, hasPRSnapshot, hasApp, logger, loader.NewMockLoader(), k8sClient)
+ adapter.status = mockStatus
+ err := adapter.ReportSnapshotStatus(adapter.snapshot)
+ fmt.Fprintf(GinkgoWriter, "-------test: %v\n", "")
+ Expect(err).NotTo(HaveOccurred())
+ })
+
+ It("report expected textual data for InProgress test scenario", func() {
+ os.Setenv("CONSOLE_NAME", "Konflux Staging")
+ log := helpers.IntegrationLogger{Logger: buflogr.NewWithBuffer(&buf)}
+
+ mockStatus.EXPECT().GetReporter(gomock.Any()).Return(mockReporter)
+ mockStatus.EXPECT().GetReporter(gomock.Any()).AnyTimes()
+ mockReporter.EXPECT().GetReporterName().AnyTimes()
+
+ hasPRSnapshot.Annotations["test.appstudio.openshift.io/status"] = "[{\"scenario\":\"scenario1\",\"status\":\"InProgress\",\"testPipelineRunName\":\"test-pipelinerun\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:50+02:00\",\"details\":\"Test in progress\"}]"
+ t, err := time.Parse(time.RFC3339, "2023-07-26T16:57:49+02:00")
+ Expect(err).NotTo(HaveOccurred())
+ expectedTestReport := status.TestReport{
+ FullName: "Konflux Staging / scenario1 / component-sample",
+ ScenarioName: "scenario1",
+ SnapshotName: "snapshot-pr-sample",
+ ComponentName: "component-sample",
+ Text: "Test in progress",
+ Summary: "Integration test for snapshot snapshot-pr-sample and scenario scenario1 is in progress",
+ Status: intgteststat.IntegrationTestStatusInProgress,
+ StartTime: &t,
+ TestPipelineRunName: "test-pipelinerun",
+ }
+ mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
+ mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Eq(expectedTestReport)).Times(1)
+ adapter = NewAdapter(ctx, hasPRSnapshot, hasApp, log, loader.NewMockLoader(), k8sClient)
+ adapter.status = mockStatus
+ err = adapter.ReportSnapshotStatus(adapter.snapshot)
+ fmt.Fprintf(GinkgoWriter, "-------test: %v\n", buf.String())
+ Expect(err).NotTo(HaveOccurred())
+ })
+ })
})
diff --git a/status/mock_status.go b/status/mock_status.go
index fd1556eb5..0928aaba5 100644
--- a/status/mock_status.go
+++ b/status/mock_status.go
@@ -99,16 +99,16 @@ func (mr *MockStatusInterfaceMockRecorder) IsPRMRInSnapshotOpened(arg0, arg1 any
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsPRMRInSnapshotOpened", reflect.TypeOf((*MockStatusInterface)(nil).IsPRMRInSnapshotOpened), arg0, arg1)
}
-// ReportSnapshotStatus mocks base method.
-func (m *MockStatusInterface) ReportSnapshotStatus(arg0 context.Context, arg1 ReporterInterface, arg2 *v1alpha1.Snapshot) error {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "ReportSnapshotStatus", arg0, arg1, arg2)
- ret0, _ := ret[0].(error)
- return ret0
-}
-
-// ReportSnapshotStatus indicates an expected call of ReportSnapshot
-func (mr *MockStatusInterfaceMockRecorder) ReportSnapshotStatus(arg0, arg1, arg2 any) *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReportSnapshotStatus", reflect.TypeOf((*MockStatusInterface)(nil).ReportSnapshotStatus), arg0, arg1, arg2)
-}
+// // ReportSnapshotStatus mocks base method.
+// func (m *MockStatusInterface) ReportSnapshotStatus(arg0 context.Context, arg1 *v1alpha1.Snapshot) error {
+// m.ctrl.T.Helper()
+// ret := m.ctrl.Call(m, "ReportSnapshotStatus", arg0, arg1)
+// ret0, _ := ret[0].(error)
+// return ret0
+// }
+
+// // ReportSnapshotStatus indicates an expected call of ReportSnapshot
+// func (mr *MockStatusInterfaceMockRecorder) ReportSnapshotStatus(arg0, arg1 any) *gomock.Call {
+// mr.mock.ctrl.T.Helper()
+// return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReportSnapshotStatus", reflect.TypeOf((*MockStatusInterface)(nil).ReportSnapshotStatus), arg0, arg1)
+// }
diff --git a/status/status.go b/status/status.go
index 427640d5c..7f46d6204 100644
--- a/status/status.go
+++ b/status/status.go
@@ -21,7 +21,6 @@ package status
import (
"context"
"encoding/json"
- "errors"
"fmt"
"net/url"
"os"
@@ -39,7 +38,6 @@ import (
gitlab "github.com/xanzy/go-gitlab"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
- "k8s.io/client-go/util/retry"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
)
@@ -187,7 +185,6 @@ func MigrateSnapshotToReportStatus(s *applicationapiv1alpha1.Snapshot, testStatu
type StatusInterface interface {
GetReporter(*applicationapiv1alpha1.Snapshot) ReporterInterface
- ReportSnapshotStatus(context.Context, ReporterInterface, *applicationapiv1alpha1.Snapshot) error
// Check if PR/MR is opened
IsPRMRInSnapshotOpened(context.Context, *applicationapiv1alpha1.Snapshot) (bool, error)
// Check if github PR is open
@@ -226,93 +223,23 @@ func (s *Status) GetReporter(snapshot *applicationapiv1alpha1.Snapshot) Reporter
return nil
}
-// ReportSnapshotStatus reports status of all integration tests into Pull Request
-func (s *Status) ReportSnapshotStatus(ctx context.Context, reporter ReporterInterface, snapshot *applicationapiv1alpha1.Snapshot) error {
-
- statuses, err := gitops.NewSnapshotIntegrationTestStatusesFromSnapshot(snapshot)
- if err != nil {
- s.logger.Error(err, "failed to get test status annotations from snapshot",
- "snapshot.Namespace", snapshot.Namespace, "snapshot.Name", snapshot.Name)
- return err
- }
-
- integrationTestStatusDetails := statuses.GetStatuses()
- if len(integrationTestStatusDetails) == 0 {
- // no tests to report, skip
- s.logger.Info("No test result to report to GitHub, skipping",
- "snapshot.Namespace", snapshot.Namespace, "snapshot.Name", snapshot.Name)
- return nil
- }
-
- if err := reporter.Initialize(ctx, snapshot); err != nil {
- s.logger.Error(err, "Failed to initialize reporter", "reporter", reporter.GetReporterName())
- return fmt.Errorf("failed to initialize reporter: %w", err)
- }
- s.logger.Info("Reporter initialized", "reporter", reporter.GetReporterName())
-
- MigrateSnapshotToReportStatus(snapshot, integrationTestStatusDetails)
-
- srs, err := NewSnapshotReportStatusFromSnapshot(snapshot)
- if err != nil {
- s.logger.Error(err, "failed to get latest snapshot write metadata annotation for snapshot",
- "snapshot.NameSpace", snapshot.Namespace, "snapshot.Name", snapshot.Name)
- srs, _ = NewSnapshotReportStatus("")
- }
-
- err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
- for _, integrationTestStatusDetail := range integrationTestStatusDetails {
- if srs.IsNewer(integrationTestStatusDetail.ScenarioName, integrationTestStatusDetail.LastUpdateTime) {
- s.logger.Info("Integration Test contains new status updates", "scenario.Name", integrationTestStatusDetail.ScenarioName)
- } else {
- //integration test contains no changes
- continue
- }
- testReport, reportErr := s.generateTestReport(ctx, *integrationTestStatusDetail, snapshot)
- if reportErr != nil {
- if writeErr := WriteSnapshotReportStatus(ctx, s.client, snapshot, srs); writeErr != nil { // try to write what was already written
- return fmt.Errorf("failed to generate test report AND write snapshot report status metadata: %w", errors.Join(reportErr, writeErr))
- }
- return fmt.Errorf("failed to generate test report: %w", reportErr)
- }
- if reportStatusErr := reporter.ReportStatus(ctx, *testReport); reportStatusErr != nil {
- if writeErr := WriteSnapshotReportStatus(ctx, s.client, snapshot, srs); writeErr != nil { // try to write what was already written
- return fmt.Errorf("failed to report status AND write snapshot report status metadata: %w", errors.Join(reportStatusErr, writeErr))
- }
- return fmt.Errorf("failed to update status: %w", reportStatusErr)
- }
- srs.SetLastUpdateTime(integrationTestStatusDetail.ScenarioName, integrationTestStatusDetail.LastUpdateTime)
- }
- if err := WriteSnapshotReportStatus(ctx, s.client, snapshot, srs); err != nil {
- return fmt.Errorf("failed to write snapshot report status metadata: %w", err)
- }
- return err
- })
- if err != nil {
- return fmt.Errorf("issue occured during generating or updating report status: %w", err)
- }
-
- s.logger.Info(fmt.Sprintf("Successfully updated the %s annotation", gitops.SnapshotStatusReportAnnotation), "snapshotReporterStatus.value", srs)
-
- return nil
-}
-
-// generateTestReport generates TestReport to be used by all reporters
-func (s *Status) generateTestReport(ctx context.Context, detail intgteststat.IntegrationTestStatusDetail, snapshot *applicationapiv1alpha1.Snapshot) (*TestReport, error) {
+// GenerateTestReport generates TestReport to be used by all reporters
+func GenerateTestReport(ctx context.Context, client client.Client, detail intgteststat.IntegrationTestStatusDetail, testedSnapshot *applicationapiv1alpha1.Snapshot, componentName string) (*TestReport, error) {
var componentSnapshotInfos []*gitops.ComponentSnapshotInfo
var err error
- if componentSnapshotInfoString, ok := snapshot.Annotations[gitops.GroupSnapshotInfoAnnotation]; ok {
+ if componentSnapshotInfoString, ok := testedSnapshot.Annotations[gitops.GroupSnapshotInfoAnnotation]; ok {
componentSnapshotInfos, err = gitops.UnmarshalJSON([]byte(componentSnapshotInfoString))
if err != nil {
return nil, fmt.Errorf("failed to unmarshal JSON string: %w", err)
}
}
- text, err := s.generateText(ctx, detail, snapshot.Namespace, componentSnapshotInfos)
+ text, err := generateText(ctx, client, detail, testedSnapshot.Namespace, componentSnapshotInfos)
if err != nil {
return nil, fmt.Errorf("failed to generate text message: %w", err)
}
- summary, err := GenerateSummary(detail.Status, snapshot.Name, detail.ScenarioName)
+ summary, err := GenerateSummary(detail.Status, testedSnapshot.Name, detail.ScenarioName)
if err != nil {
return nil, fmt.Errorf("failed to generate summary message: %w", err)
}
@@ -320,16 +247,16 @@ func (s *Status) generateTestReport(ctx context.Context, detail intgteststat.Int
consoleName := getConsoleName()
fullName := fmt.Sprintf("%s / %s", consoleName, detail.ScenarioName)
- if snapshot.Labels[gitops.SnapshotComponentLabel] != "" {
- fullName = fmt.Sprintf("%s / %s", fullName, snapshot.Labels[gitops.SnapshotComponentLabel])
+ if componentName != "" {
+ fullName = fmt.Sprintf("%s / %s", fullName, componentName)
}
report := TestReport{
Text: text,
FullName: fullName,
ScenarioName: detail.ScenarioName,
- SnapshotName: snapshot.Name,
- ComponentName: snapshot.Labels[gitops.SnapshotComponentLabel],
+ SnapshotName: testedSnapshot.Name,
+ ComponentName: componentName,
Status: detail.Status,
Summary: summary,
StartTime: detail.StartTime,
@@ -340,18 +267,19 @@ func (s *Status) generateTestReport(ctx context.Context, detail intgteststat.Int
}
// generateText generates a text with details for the given state
-func (s *Status) generateText(ctx context.Context, integrationTestStatusDetail intgteststat.IntegrationTestStatusDetail, namespace string, componentSnapshotInfos []*gitops.ComponentSnapshotInfo) (string, error) {
+func generateText(ctx context.Context, client client.Client, integrationTestStatusDetail intgteststat.IntegrationTestStatusDetail, namespace string, componentSnapshotInfos []*gitops.ComponentSnapshotInfo) (string, error) {
+ log := log.FromContext(ctx)
if integrationTestStatusDetail.Status == intgteststat.IntegrationTestStatusTestPassed || integrationTestStatusDetail.Status == intgteststat.IntegrationTestStatusTestFail {
pipelineRunName := integrationTestStatusDetail.TestPipelineRunName
pipelineRun := &tektonv1.PipelineRun{}
- err := s.client.Get(ctx, types.NamespacedName{
+ err := client.Get(ctx, types.NamespacedName{
Namespace: namespace,
Name: pipelineRunName,
}, pipelineRun)
if err != nil {
if apierrors.IsNotFound(err) {
- s.logger.Error(err, "Failed to fetch pipelineRun", "pipelineRun.Name", pipelineRunName)
+ log.Error(err, "Failed to fetch pipelineRun", "pipelineRun.Name", pipelineRunName)
text := fmt.Sprintf("%s\n\n\n(Failed to fetch test result details because pipelineRun %s/%s can not be found.)", integrationTestStatusDetail.Details, namespace, pipelineRunName)
return text, nil
}
@@ -359,11 +287,11 @@ func (s *Status) generateText(ctx context.Context, integrationTestStatusDetail i
return "", fmt.Errorf("error while getting the pipelineRun %s: %w", pipelineRunName, err)
}
- taskRuns, err := helpers.GetAllChildTaskRunsForPipelineRun(ctx, s.client, pipelineRun)
+ taskRuns, err := helpers.GetAllChildTaskRunsForPipelineRun(ctx, client, pipelineRun)
if err != nil {
return "", fmt.Errorf("error while getting all child taskRuns from pipelineRun %s: %w", pipelineRunName, err)
}
- text, err := FormatTestsSummary(taskRuns, pipelineRunName, namespace, componentSnapshotInfos, s.logger)
+ text, err := FormatTestsSummary(taskRuns, pipelineRunName, namespace, componentSnapshotInfos, log)
if err != nil {
return "", err
}
@@ -542,3 +470,32 @@ func (s Status) IsPRInSnapshotOpened(ctx context.Context, reporter ReporterInter
}
return false, err
}
+
+// GetComponentSnapshotsFromGroupSnapshot return the component snapshot list which component snapshot is created from
+func GetComponentSnapshotsFromGroupSnapshot(ctx context.Context, c client.Client, groupSnapshot *applicationapiv1alpha1.Snapshot) ([]*applicationapiv1alpha1.Snapshot, error) {
+ log := log.FromContext(ctx)
+ var componentSnapshotInfos []*gitops.ComponentSnapshotInfo
+ var componentSnapshots []*applicationapiv1alpha1.Snapshot
+ var err error
+ if componentSnapshotInfoString, ok := groupSnapshot.Annotations[gitops.GroupSnapshotInfoAnnotation]; ok {
+ componentSnapshotInfos, err = gitops.UnmarshalJSON([]byte(componentSnapshotInfoString))
+ if err != nil {
+ return nil, fmt.Errorf("failed to unmarshal JSON string: %w", err)
+ }
+ }
+
+ for _, componentSnapshotInfo := range componentSnapshotInfos {
+ componentSnapshot := &applicationapiv1alpha1.Snapshot{}
+ err = c.Get(ctx, types.NamespacedName{
+ Namespace: groupSnapshot.Namespace,
+ Name: componentSnapshotInfo.Snapshot,
+ }, componentSnapshot)
+ if err != nil {
+ log.Error(err, fmt.Sprintf("failed to find component snapshot %s included in group snapshot %s/%s", componentSnapshotInfo.Snapshot, groupSnapshot.Namespace, groupSnapshot.Name))
+ continue
+ }
+ componentSnapshots = append(componentSnapshots, componentSnapshot)
+ }
+ return componentSnapshots, nil
+
+}
diff --git a/status/status_test.go b/status/status_test.go
index 9c488525c..88f4f4dc8 100644
--- a/status/status_test.go
+++ b/status/status_test.go
@@ -20,6 +20,7 @@ import (
"context"
"fmt"
"os"
+ "strconv"
"time"
"github.com/go-logr/logr"
@@ -31,8 +32,10 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
+ "github.com/konflux-ci/integration-service/gitops"
"github.com/konflux-ci/integration-service/pkg/integrationteststatus"
"github.com/konflux-ci/integration-service/status"
+ "k8s.io/apimachinery/pkg/api/errors"
)
// Custom matcher for gomock, to match expected summary in TestReport
@@ -59,18 +62,44 @@ func HasSummary(value string) gomock.Matcher {
return hasSummary{expectedSummary: value}
}
+func newIntegrationTestStatusDetail(expectedScenarioStatus integrationteststatus.IntegrationTestStatus) integrationteststatus.IntegrationTestStatusDetail {
+ ts, _ := time.Parse(time.RFC3339, "2023-07-26T16:57:49+02:00")
+ tc, _ := time.Parse(time.RFC3339, "2023-07-26T17:57:49+02:00")
+ return integrationteststatus.IntegrationTestStatusDetail{
+ ScenarioName: "scenario1",
+ Status: expectedScenarioStatus,
+ LastUpdateTime: time.Now().UTC(),
+ Details: "failed",
+ StartTime: &ts,
+ CompletionTime: &tc,
+ TestPipelineRunName: "test-pipelinerun",
+ }
+}
+
var _ = Describe("Status Adapter", func() {
var (
- githubSnapshot *applicationapiv1alpha1.Snapshot
- hasSnapshot *applicationapiv1alpha1.Snapshot
- mockReporter *status.MockReporterInterface
+ githubSnapshot *applicationapiv1alpha1.Snapshot
+ hasSnapshot *applicationapiv1alpha1.Snapshot
+ hasComSnapshot2 *applicationapiv1alpha1.Snapshot
+ hasComSnapshot3 *applicationapiv1alpha1.Snapshot
+ groupSnapshot *applicationapiv1alpha1.Snapshot
+ mockReporter *status.MockReporterInterface
pipelineRun *tektonv1.PipelineRun
successfulTaskRun *tektonv1.TaskRun
failedTaskRun *tektonv1.TaskRun
skippedTaskRun *tektonv1.TaskRun
mockK8sClient *MockK8sClient
+
+ hasComSnapshot2Name = "hascomsnapshot2-sample"
+ hasComSnapshot3Name = "hascomsnapshot3-sample"
+
+ prGroup = "feature1"
+ prGroupSha = "feature1hash"
+ plrstarttime = 1775992257
+ SampleImage = "quay.io/redhat-appstudio/sample-image@sha256:841328df1b9f8c4087adbdcfec6cc99ac8308805dea83f6d415d6fb8d40227c1"
+ SampleDigest = "sha256:841328df1b9f8c4087adbdcfec6cc99ac8308805dea83f6d415d6fb8d40227c1"
)
BeforeEach(func() {
@@ -279,6 +308,111 @@ var _ = Describe("Status Adapter", func() {
},
}
+ hasComSnapshot2 = &applicationapiv1alpha1.Snapshot{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: hasComSnapshot2Name,
+ Namespace: "default",
+ Labels: map[string]string{
+ gitops.SnapshotTypeLabel: gitops.SnapshotComponentType,
+ gitops.SnapshotComponentLabel: hasComSnapshot2Name,
+ gitops.PipelineAsCodeEventTypeLabel: gitops.PipelineAsCodePullRequestType,
+ gitops.PRGroupHashLabel: prGroupSha,
+ "pac.test.appstudio.openshift.io/url-org": "testorg",
+ "pac.test.appstudio.openshift.io/url-repository": "testrepo",
+ gitops.PipelineAsCodeSHALabel: "sha",
+ gitops.PipelineAsCodePullRequestAnnotation: "1",
+ },
+ Annotations: map[string]string{
+ "test.appstudio.openshift.io/pr-last-update": "2023-08-26T17:57:50+02:00",
+ gitops.BuildPipelineRunStartTime: strconv.Itoa(plrstarttime + 100),
+ gitops.PRGroupAnnotation: prGroup,
+ gitops.PipelineAsCodeGitProviderAnnotation: "github",
+ gitops.PipelineAsCodeInstallationIDAnnotation: "123",
+ },
+ },
+ Spec: applicationapiv1alpha1.SnapshotSpec{
+ Application: "application-sample",
+ Components: []applicationapiv1alpha1.SnapshotComponent{
+ {
+ Name: hasComSnapshot2Name,
+ ContainerImage: SampleImage + "@" + SampleDigest,
+ },
+ {
+ Name: hasComSnapshot3Name,
+ ContainerImage: SampleImage + "@" + SampleDigest,
+ },
+ },
+ },
+ }
+
+ hasComSnapshot3 = &applicationapiv1alpha1.Snapshot{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: hasComSnapshot3Name,
+ Namespace: "default",
+ Labels: map[string]string{
+ gitops.SnapshotTypeLabel: gitops.SnapshotComponentType,
+ gitops.SnapshotComponentLabel: hasComSnapshot3Name,
+ gitops.PipelineAsCodeEventTypeLabel: gitops.PipelineAsCodePullRequestType,
+ gitops.PRGroupHashLabel: prGroupSha,
+ "pac.test.appstudio.openshift.io/url-org": "testorg",
+ "pac.test.appstudio.openshift.io/url-repository": "testrepo",
+ gitops.PipelineAsCodeSHALabel: "sha",
+ gitops.PipelineAsCodePullRequestAnnotation: "1",
+ },
+ Annotations: map[string]string{
+ "test.appstudio.openshift.io/pr-last-update": "2023-08-26T17:57:50+02:00",
+ gitops.BuildPipelineRunStartTime: strconv.Itoa(plrstarttime + 200),
+ gitops.PRGroupAnnotation: prGroup,
+ gitops.PipelineAsCodeGitProviderAnnotation: "github",
+ gitops.PipelineAsCodePullRequestAnnotation: "1",
+ gitops.PipelineAsCodeInstallationIDAnnotation: "123",
+ },
+ },
+ Spec: applicationapiv1alpha1.SnapshotSpec{
+ Application: "application-sample",
+ Components: []applicationapiv1alpha1.SnapshotComponent{
+ {
+ Name: hasComSnapshot2Name,
+ ContainerImage: SampleImage + "@" + SampleDigest,
+ },
+ {
+ Name: hasComSnapshot3Name,
+ ContainerImage: SampleImage + "@" + SampleDigest,
+ },
+ },
+ },
+ }
+
+ groupSnapshot = &applicationapiv1alpha1.Snapshot{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "groupsnapshot",
+ Namespace: "default",
+ Labels: map[string]string{
+ gitops.SnapshotTypeLabel: gitops.SnapshotGroupType,
+ gitops.PipelineAsCodeEventTypeLabel: gitops.PipelineAsCodePullRequestType,
+ gitops.PRGroupHashLabel: prGroupSha,
+ },
+ Annotations: map[string]string{
+ gitops.PRGroupAnnotation: prGroup,
+ gitops.GroupSnapshotInfoAnnotation: "[{\"namespace\":\"default\",\"component\":\"component1-sample\",\"buildPipelineRun\":\"\",\"snapshot\":\"hascomsnapshot2-sample\"},{\"namespace\":\"default\",\"component\":\"component3-sample\",\"buildPipelineRun\":\"\",\"snapshot\":\"hascomsnapshot3-sample\"}]",
+ gitops.SnapshotTestsStatusAnnotation: "[{\"scenario\":\"scenario-1\",\"status\":\"EnvironmentProvisionError\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"completionTime\":\"2023-07-26T17:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:49+02:00\",\"details\":\"Failed to find deploymentTargetClass with right provisioner for copy of existingEnvironment\"}]",
+ },
+ },
+ Spec: applicationapiv1alpha1.SnapshotSpec{
+ Application: "application-sample",
+ Components: []applicationapiv1alpha1.SnapshotComponent{
+ {
+ Name: hasComSnapshot2Name,
+ ContainerImage: SampleImage + "@" + SampleDigest,
+ },
+ {
+ Name: hasComSnapshot3Name,
+ ContainerImage: SampleImage + "@" + SampleDigest,
+ },
+ },
+ },
+ }
+
mockK8sClient = &MockK8sClient{
getInterceptor: func(key client.ObjectKey, obj client.Object) {
if taskRun, ok := obj.(*tektonv1.TaskRun); ok {
@@ -295,10 +429,56 @@ var _ = Describe("Status Adapter", func() {
plr.Status = pipelineRun.Status
}
}
+ if snapshot, ok := obj.(*applicationapiv1alpha1.Snapshot); ok {
+ if key.Name == hasComSnapshot2.Name {
+ snapshot.Name = hasComSnapshot2.Name
+ }
+ if key.Name == hasComSnapshot3.Name {
+ snapshot.Name = hasComSnapshot3.Name
+ }
+ }
},
listInterceptor: func(list client.ObjectList) {},
}
+ hasSnapshot = &applicationapiv1alpha1.Snapshot{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "snapshot-sample",
+ Namespace: "default",
+ Labels: map[string]string{
+ "test.appstudio.openshift.io/type": "component",
+ "appstudio.openshift.io/component": "component-sample",
+ "build.appstudio.redhat.com/pipeline": "enterprise-contract",
+ "pac.test.appstudio.openshift.io/git-provider": "github",
+ "pac.test.appstudio.openshift.io/url-org": "devfile-sample",
+ "pac.test.appstudio.openshift.io/url-repository": "devfile-sample-go-basic",
+ "pac.test.appstudio.openshift.io/sha": "12a4a35ccd08194595179815e4646c3a6c08bb77",
+ "pac.test.appstudio.openshift.io/event-type": "pull_request",
+ },
+ Annotations: map[string]string{
+ "build.appstudio.redhat.com/commit_sha": "6c65b2fcaea3e1a0a92476c8b5dc89e92a85f025",
+ "appstudio.redhat.com/updateComponentOnSuccess": "false",
+ "pac.test.appstudio.openshift.io/repo-url": "https://github.com/devfile-sample/devfile-sample-go-basic",
+ },
+ },
+ Spec: applicationapiv1alpha1.SnapshotSpec{
+ Application: "application-sample",
+ Components: []applicationapiv1alpha1.SnapshotComponent{
+ {
+ Name: "component-sample",
+ ContainerImage: "sample_image",
+ Source: applicationapiv1alpha1.ComponentSource{
+ ComponentSourceUnion: applicationapiv1alpha1.ComponentSourceUnion{
+ GitSource: &applicationapiv1alpha1.GitSource{
+ Revision: "sample_revision",
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+
githubSnapshot = &applicationapiv1alpha1.Snapshot{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
@@ -310,6 +490,7 @@ var _ = Describe("Status Adapter", func() {
ctrl := gomock.NewController(GinkgoT())
mockReporter = status.NewMockReporterInterface(ctrl)
mockReporter.EXPECT().GetReporterName().Return("mocked-reporter").AnyTimes()
+ mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
os.Setenv("CONSOLE_NAME", "Red Hat Konflux")
})
@@ -325,91 +506,19 @@ var _ = Describe("Status Adapter", func() {
Expect(reporter.GetReporterName()).To(Equal("GithubReporter"))
})
- It("doesn't report anything when there are not test results", func() {
-
- mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(0) // without test results reporter shouldn't be initialized
- mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Any()).Times(0) // without test results reported shouldn't report status
-
- st := status.NewStatus(logr.Discard(), nil)
- err := st.ReportSnapshotStatus(context.Background(), mockReporter, githubSnapshot)
- Expect(err).NotTo(HaveOccurred())
- })
-
- It("doesn't report anything when data are older", func() {
-
- mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
- mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Any()).Times(0) // data are older, status shouldn't be reported
-
- hasSnapshot.Annotations["test.appstudio.openshift.io/status"] = "[{\"scenario\":\"scenario1\",\"status\":\"InProgress\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:50+02:00\",\"details\":\"Test in progress\"}]"
- hasSnapshot.Annotations["test.appstudio.openshift.io/git-reporter-status"] = "{\"scenarios\":{\"scenario1\":{\"lastUpdateTime\":\"2023-08-26T17:57:50+02:00\"}}}"
- st := status.NewStatus(logr.Discard(), mockK8sClient)
- err := st.ReportSnapshotStatus(context.Background(), mockReporter, hasSnapshot)
- Expect(err).NotTo(HaveOccurred())
- })
-
- It("doesn't report anything when data are older (old way - migration test)", func() {
-
- mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
- mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Any()).Times(0) // data are older, status shouldn't be reported
-
+ It("can migrate snapshot to reportStatus in old way - migration test)", func() {
hasSnapshot.Annotations["test.appstudio.openshift.io/status"] = "[{\"scenario\":\"scenario1\",\"status\":\"InProgress\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:50+02:00\",\"details\":\"Test in progress\"}]"
hasSnapshot.Annotations["test.appstudio.openshift.io/pr-last-update"] = "2023-08-26T17:57:50+02:00"
- st := status.NewStatus(logr.Discard(), mockK8sClient)
- err := st.ReportSnapshotStatus(context.Background(), mockReporter, hasSnapshot)
- Expect(err).NotTo(HaveOccurred())
- })
-
- It("Report new status if it was updated", func() {
-
- mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
- mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Any()).Times(1)
-
- hasSnapshot.Annotations["test.appstudio.openshift.io/status"] = "[{\"scenario\":\"scenario1\",\"status\":\"InProgress\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:50+02:00\",\"details\":\"Test in progress\"}]"
- hasSnapshot.Annotations["test.appstudio.openshift.io/git-reporter-status"] = "{\"scenarios\":{\"scenario1\":{\"lastUpdateTime\":\"2023-08-26T17:57:49+02:00\"}}}"
- hasSnapshot.Annotations["test.appstudio.openshift.io/group-test-info"] = "[{\"namespace\":\"default\",\"component\":\"devfile-sample-java-springboot-basic-8969\",\"buildPipelineRun\":\"build-plr-java-qjfxz\",\"snapshot\":\"app-8969-bbn7d\"},{\"namespace\":\"default\",\"component\":\"devfile-sample-go-basic-8969\",\"buildPipelineRun\":\"build-plr-go-jmsjq\",\"snapshot\":\"app-8969-kzq2l\"}]"
- st := status.NewStatus(logr.Discard(), mockK8sClient)
- err := st.ReportSnapshotStatus(context.Background(), mockReporter, hasSnapshot)
- Expect(err).NotTo(HaveOccurred())
- })
-
- It("Report new status if it was updated (old way - migration test)", func() {
-
- mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
- mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Any()).Times(1)
-
- hasSnapshot.Annotations["test.appstudio.openshift.io/status"] = "[{\"scenario\":\"scenario1\",\"status\":\"InProgress\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:50+02:00\",\"details\":\"Test in progress\"}]"
- hasSnapshot.Annotations["test.appstudio.openshift.io/pr-last-update"] = "2023-08-26T17:57:49+02:00"
- st := status.NewStatus(logr.Discard(), mockK8sClient)
- err := st.ReportSnapshotStatus(context.Background(), mockReporter, hasSnapshot)
- Expect(err).NotTo(HaveOccurred())
- })
-
- It("report expected textual data for InProgress test scenario", func() {
- os.Setenv("CONSOLE_NAME", "Konflux Staging")
- hasSnapshot.Annotations["test.appstudio.openshift.io/status"] = "[{\"scenario\":\"scenario1\",\"status\":\"InProgress\",\"testPipelineRunName\":\"test-pipelinerun\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:50+02:00\",\"details\":\"Test in progress\"}]"
- t, err := time.Parse(time.RFC3339, "2023-07-26T16:57:49+02:00")
- Expect(err).NotTo(HaveOccurred())
- expectedTestReport := status.TestReport{
- FullName: "Konflux Staging / scenario1 / component-sample",
- ScenarioName: "scenario1",
- SnapshotName: "snapshot-sample",
- ComponentName: "component-sample",
- Text: "Test in progress",
- Summary: "Integration test for snapshot snapshot-sample and scenario scenario1 is in progress",
- Status: integrationteststatus.IntegrationTestStatusInProgress,
- StartTime: &t,
- TestPipelineRunName: "test-pipelinerun",
- }
- mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
- mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Eq(expectedTestReport)).Times(1)
-
- st := status.NewStatus(logr.Discard(), mockK8sClient)
- err = st.ReportSnapshotStatus(context.Background(), mockReporter, hasSnapshot)
+ statuses, err := gitops.NewSnapshotIntegrationTestStatusesFromSnapshot(hasSnapshot)
Expect(err).NotTo(HaveOccurred())
+ integrationTestStatusDetails := statuses.GetStatuses()
+ status.MigrateSnapshotToReportStatus(hasSnapshot, integrationTestStatusDetails)
+ Expect(hasSnapshot.Annotations[gitops.SnapshotStatusReportAnnotation]).Should(ContainSubstring("lastUpdateTime"))
})
It("report status for TestPassed test scenario", func() {
hasSnapshot.Annotations["test.appstudio.openshift.io/status"] = "[{\"scenario\":\"scenario1\",\"status\":\"TestPassed\",\"testPipelineRunName\":\"test-pipelinerun\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"completionTime\":\"2023-07-26T17:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:55+02:00\",\"details\":\"failed\"}]"
+ integrationTestStatusDetail := newIntegrationTestStatusDetail(integrationteststatus.IntegrationTestStatusTestPassed)
delete(hasSnapshot.Labels, "appstudio.openshift.io/component")
ts, err := time.Parse(time.RFC3339, "2023-07-26T16:57:49+02:00")
Expect(err).NotTo(HaveOccurred())
@@ -439,28 +548,22 @@ var _ = Describe("Status Adapter", func() {
CompletionTime: &tc,
TestPipelineRunName: "test-pipelinerun",
}
- mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
- mockReporter.EXPECT().ReportStatus(gomock.Any(), gomock.Eq(expectedTestReport)).Times(1)
- st := status.NewStatus(logr.Discard(), mockK8sClient)
- err = st.ReportSnapshotStatus(context.Background(), mockReporter, hasSnapshot)
+ testReport, err := status.GenerateTestReport(context.Background(), mockK8sClient, integrationTestStatusDetail, hasSnapshot, "")
Expect(err).NotTo(HaveOccurred())
+ Expect(testReport).To(Equal(&expectedTestReport))
})
DescribeTable(
"report right summary per status",
func(expectedScenarioStatus integrationteststatus.IntegrationTestStatus, expectedTextEnding string) {
- statusAnnotationTempl := "[{\"scenario\":\"scenario1\",\"status\":\"%s\",\"testPipelineRunName\":\"test-pipelinerun\",\"startTime\":\"2023-07-26T16:57:49+02:00\",\"completionTime\":\"2023-07-26T17:57:49+02:00\",\"lastUpdateTime\":\"2023-08-26T17:57:55+02:00\",\"details\":\"failed\"}]"
- hasSnapshot.Annotations["test.appstudio.openshift.io/status"] = fmt.Sprintf(statusAnnotationTempl, expectedScenarioStatus)
+ integrationTestStatusDetail := newIntegrationTestStatusDetail(expectedScenarioStatus)
expectedSummary := fmt.Sprintf("Integration test for snapshot snapshot-sample and scenario scenario1 %s", expectedTextEnding)
- mockReporter.EXPECT().Initialize(gomock.Any(), gomock.Any()).Times(1)
- mockReporter.EXPECT().ReportStatus(gomock.Any(), HasSummary(expectedSummary)).Times(1)
-
- st := status.NewStatus(logr.Discard(), mockK8sClient)
- err := st.ReportSnapshotStatus(context.Background(), mockReporter, hasSnapshot)
+ testReport, err := status.GenerateTestReport(context.Background(), mockK8sClient, integrationTestStatusDetail, hasSnapshot, "component-sample")
Expect(err).NotTo(HaveOccurred())
+ Expect(testReport.Summary).To(Equal(expectedSummary))
},
Entry("Passed", integrationteststatus.IntegrationTestStatusTestPassed, "has passed"),
Entry("Failed", integrationteststatus.IntegrationTestStatusTestFail, "has failed"),
@@ -479,6 +582,13 @@ var _ = Describe("Status Adapter", func() {
}
})
+ It("check getting component snapshots from group snapshot", func() {
+ componentSnapshots, err := status.GetComponentSnapshotsFromGroupSnapshot(context.Background(), mockK8sClient, groupSnapshot)
+ Expect(err).NotTo(HaveOccurred())
+ Expect(componentSnapshots).To(HaveLen(2))
+
+ })
+
Describe("SnapshotReportStatus (SRS)", func() {
const (
scenarioName = "test-scenario"
@@ -502,6 +612,7 @@ var _ = Describe("Status Adapter", func() {
})
It("Reseting dirty bit works", func() {
+ Expect(mockK8sClient.Create(context.Background(), hasSnapshot)).Should(Succeed())
hasSRS.SetLastUpdateTime(scenarioName, now)
Expect(hasSRS.IsDirty()).To(BeTrue())
@@ -513,9 +624,16 @@ var _ = Describe("Status Adapter", func() {
HaveKeyWithValue(scenarioName, &status.ScenarioReportStatus{
LastUpdateTime: &now,
}))
+ Expect(hasSnapshot.Annotations[gitops.SnapshotStatusReportAnnotation]).To(Equal(""))
+ err := status.WriteSnapshotReportStatus(context.Background(), mockK8sClient, hasSnapshot, hasSRS)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(hasSnapshot.Annotations[gitops.SnapshotStatusReportAnnotation]).NotTo(BeNil())
+ err = mockK8sClient.Delete(context.Background(), hasSnapshot)
+ Expect(err == nil || errors.IsNotFound(err)).To(BeTrue())
})
It("New scenario can be added to SRS", func() {
+ Expect(mockK8sClient.Create(context.Background(), hasSnapshot)).Should(Succeed())
hasSRS.SetLastUpdateTime(scenarioName, now)
Expect(hasSRS.IsDirty()).To(BeTrue())
@@ -523,6 +641,13 @@ var _ = Describe("Status Adapter", func() {
HaveKeyWithValue(scenarioName, &status.ScenarioReportStatus{
LastUpdateTime: &now,
}))
+
+ Expect(hasSnapshot.Annotations[gitops.SnapshotStatusReportAnnotation]).To(Equal(""))
+ err := status.WriteSnapshotReportStatus(context.Background(), mockK8sClient, hasSnapshot, hasSRS)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(hasSnapshot.Annotations[gitops.SnapshotStatusReportAnnotation]).NotTo(BeNil())
+ err = mockK8sClient.Delete(context.Background(), hasSnapshot)
+ Expect(err == nil || errors.IsNotFound(err)).To(BeTrue())
})
It("Additional scenario can be added to SRS", func() {