diff --git a/internal/controller/applicationdeploymentstatus_test.go b/internal/controller/applicationdeploymentstatus_test.go new file mode 100644 index 00000000..d4a45ce0 --- /dev/null +++ b/internal/controller/applicationdeploymentstatus_test.go @@ -0,0 +1,320 @@ +package controller + +import ( + "context" + "net/http" + "time" + + argocdv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" + "github.com/argoproj/gitops-engine/pkg/health" + synccommon "github.com/argoproj/gitops-engine/pkg/sync/common" + "github.com/int128/argocd-commenter/internal/controller/githubmock" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + crclient "sigs.k8s.io/controller-runtime/pkg/client" +) + +var _ = Describe("Deployment status", func() { + var app argocdv1alpha1.Application + var deploymentStatus githubmock.DeploymentStatus + + BeforeEach(func(ctx context.Context) { + By("Setting up a deployment status endpoint") + deploymentStatus = githubmock.DeploymentStatus{} + githubServer.AddHandlers(map[string]http.Handler{ + "GET /api/v3/repos/owner/repo-deployment/deployments/101/statuses": deploymentStatus.ListEndpoint(), + "POST /api/v3/repos/owner/repo-deployment/deployments/101/statuses": deploymentStatus.CreateEndpoint(), + }) + + By("Creating an application") + app = argocdv1alpha1.Application{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "argoproj.io/v1alpha1", + Kind: "Application", + }, + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "fixture-deployment-status-phase-", + Namespace: "default", + Annotations: map[string]string{ + "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/owner/repo-deployment/deployments/101", + }, + }, + Spec: argocdv1alpha1.ApplicationSpec{ + Project: "default", + Source: &argocdv1alpha1.ApplicationSource{ + RepoURL: "https://github.com/owner/repo-deployment.git", + Path: "test", + TargetRevision: "main", + }, + Destination: argocdv1alpha1.ApplicationDestination{ + Server: "https://kubernetes.default.svc", + Namespace: "default", + }, + }, + } + Expect(k8sClient.Create(ctx, &app)).Should(Succeed()) + }) + + Context("When the application is synced", func() { + BeforeEach(func(ctx context.Context) { + By("Updating the application to running") + startedAt := metav1.Now() + app.Status.OperationState = &argocdv1alpha1.OperationState{ + Phase: synccommon.OperationRunning, + StartedAt: startedAt, + Operation: argocdv1alpha1.Operation{ + Sync: &argocdv1alpha1.SyncOperation{ + Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", + }, + }, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(1)) + + By("Updating the application to succeeded") + finishedAt := metav1.Now() + app.Status.OperationState = &argocdv1alpha1.OperationState{ + Phase: synccommon.OperationSucceeded, + StartedAt: startedAt, + FinishedAt: &finishedAt, + Operation: argocdv1alpha1.Operation{ + Sync: &argocdv1alpha1.SyncOperation{ + Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", + }, + }, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(2)) + }) + + Context("When the application is healthy", func() { + It("Should create deployment statuses", func(ctx context.Context) { + By("Updating the application to progressing") + app.Status.Health = argocdv1alpha1.HealthStatus{ + Status: health.HealthStatusProgressing, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + + By("Updating the application to healthy") + app.Status.Health = argocdv1alpha1.HealthStatus{ + Status: health.HealthStatusHealthy, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(3)) + }, SpecTimeout(3*time.Second)) + + It("Should not create any deployment status after healthy", func(ctx context.Context) { + By("Updating the application to progressing") + app.Status.Health = argocdv1alpha1.HealthStatus{ + Status: health.HealthStatusProgressing, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + + By("Updating the application to healthy") + app.Status.Health = argocdv1alpha1.HealthStatus{ + Status: health.HealthStatusHealthy, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(3)) + + By("Updating the application to progressing") + app.Status.Health = argocdv1alpha1.HealthStatus{ + Status: health.HealthStatusProgressing, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + + By("Updating the application to healthy") + app.Status.Health = argocdv1alpha1.HealthStatus{ + Status: health.HealthStatusHealthy, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + Consistently(func() int { return deploymentStatus.CreateCount() }, "100ms").Should(Equal(3)) + + By("Updating the application to running") + startedAt := metav1.Now() + app.Status.OperationState = &argocdv1alpha1.OperationState{ + Phase: synccommon.OperationRunning, + StartedAt: startedAt, + Operation: argocdv1alpha1.Operation{ + Sync: &argocdv1alpha1.SyncOperation{ + Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", + }, + }, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + + By("Updating the application to succeeded") + finishedAt := metav1.Now() + app.Status.OperationState = &argocdv1alpha1.OperationState{ + Phase: synccommon.OperationSucceeded, + StartedAt: startedAt, + FinishedAt: &finishedAt, + Operation: argocdv1alpha1.Operation{ + Sync: &argocdv1alpha1.SyncOperation{ + Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", + }, + }, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + Consistently(func() int { return deploymentStatus.CreateCount() }, "100ms").Should(Equal(3)) + }, SpecTimeout(3*time.Second)) + }) + }) + + Context("When the sync operation is failed", func() { + It("Should create deployment statuses", func(ctx context.Context) { + By("Updating the application to running") + app.Status.OperationState = &argocdv1alpha1.OperationState{ + Phase: synccommon.OperationRunning, + StartedAt: metav1.Now(), + Operation: argocdv1alpha1.Operation{ + Sync: &argocdv1alpha1.SyncOperation{ + Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", + }, + }, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(1)) + + By("Updating the application to retrying") + startedAt := metav1.Now() + app.Status.OperationState = &argocdv1alpha1.OperationState{ + Phase: synccommon.OperationRunning, + StartedAt: startedAt, + RetryCount: 1, + Operation: argocdv1alpha1.Operation{ + Sync: &argocdv1alpha1.SyncOperation{ + Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", + }, + }, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + Consistently(func() int { return deploymentStatus.CreateCount() }, 100*time.Millisecond).Should(Equal(1)) + + By("Updating the application to failed") + finishedAt := metav1.Now() + app.Status.OperationState = &argocdv1alpha1.OperationState{ + Phase: synccommon.OperationFailed, + StartedAt: startedAt, + FinishedAt: &finishedAt, + Operation: argocdv1alpha1.Operation{ + Sync: &argocdv1alpha1.SyncOperation{ + Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa101", + }, + }, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(2)) + }, SpecTimeout(3*time.Second)) + }) +}) + +var _ = Describe("Deployment status", func() { + Context("When an application was synced before the deployment annotation is updated", func() { + var app argocdv1alpha1.Application + + BeforeEach(func(ctx context.Context) { + By("Creating an application") + app = argocdv1alpha1.Application{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "argoproj.io/v1alpha1", + Kind: "Application", + }, + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "fixture-deployment-status-phase-", + Namespace: "default", + Annotations: map[string]string{ + "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/owner/repo-deployment/deployments/999", + }, + }, + Spec: argocdv1alpha1.ApplicationSpec{ + Project: "default", + Source: &argocdv1alpha1.ApplicationSource{ + RepoURL: "https://github.com/owner/repo-deployment.git", + Path: "test", + TargetRevision: "main", + }, + Destination: argocdv1alpha1.ApplicationDestination{ + Server: "https://kubernetes.default.svc", + Namespace: "default", + }, + }, + } + Expect(k8sClient.Create(ctx, &app)).Should(Succeed()) + }) + + It("Should finally create a deployment status", func(ctx context.Context) { + By("Setting up a deployment status endpoint") + var deploymentStatus githubmock.DeploymentStatus + githubServer.AddHandlers(map[string]http.Handler{ + "GET /api/v3/repos/owner/repo-deployment/deployments/101/statuses": deploymentStatus.ListEndpoint(), + "POST /api/v3/repos/owner/repo-deployment/deployments/101/statuses": deploymentStatus.CreateEndpoint(), + }) + + By("Updating the application to running") + startedAt := metav1.Now() + app.Status.OperationState = &argocdv1alpha1.OperationState{ + Phase: synccommon.OperationRunning, + StartedAt: startedAt, + Operation: argocdv1alpha1.Operation{ + Sync: &argocdv1alpha1.SyncOperation{ + Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + }, + }, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + Consistently(func() int { return deploymentStatus.CreateCount() }, 100*time.Millisecond).Should(Equal(0)) + + By("Updating the deployment annotation") + app.Annotations = map[string]string{ + "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/owner/repo-deployment/deployments/101", + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + Eventually(func() int { return deploymentStatus.CreateCount() }, + // This depends on requeueIntervalWhenDeploymentNotFound and takes longer time + 2*requeueIntervalWhenDeploymentNotFound, + ).Should(Equal(1)) + + By("Updating the application to succeeded") + finishedAt := metav1.Now() + app.Status.OperationState = &argocdv1alpha1.OperationState{ + Phase: synccommon.OperationSucceeded, + StartedAt: startedAt, + FinishedAt: &finishedAt, + Operation: argocdv1alpha1.Operation{ + Sync: &argocdv1alpha1.SyncOperation{ + Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + }, + }, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + Eventually(func() int { return deploymentStatus.CreateCount() }, 3*time.Second).Should(Equal(2)) + }, SpecTimeout(5*time.Second)) + + It("Should retry to create a deployment status until timeout", func(ctx context.Context) { + By("Updating the application to running") + app.Status.OperationState = &argocdv1alpha1.OperationState{ + Phase: synccommon.OperationRunning, + StartedAt: metav1.NewTime(metav1.Now().Add(-requeueTimeoutWhenDeploymentNotFound)), + Operation: argocdv1alpha1.Operation{ + Sync: &argocdv1alpha1.SyncOperation{ + Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + }, + }, + } + Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) + + By("Finding the retry event") + Eventually(func(g Gomega) { + var eventList corev1.EventList + g.Expect(k8sClient.List(ctx, &eventList, crclient.MatchingFields{ + "involvedObject.name": app.Name, + "reason": "DeploymentNotFoundRetryTimeout", + })).Should(Succeed()) + g.Expect(eventList.Items).Should(HaveLen(1)) + }) + }) + }) +}) diff --git a/internal/controller/applicationhealthdeployment_controller_test.go b/internal/controller/applicationhealthdeployment_controller_test.go deleted file mode 100644 index 5bf15529..00000000 --- a/internal/controller/applicationhealthdeployment_controller_test.go +++ /dev/null @@ -1,209 +0,0 @@ -package controller - -import ( - "context" - "net/http" - "time" - - argocdv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" - "github.com/argoproj/gitops-engine/pkg/health" - "github.com/int128/argocd-commenter/internal/controller/githubmock" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -var _ = Describe("Deployment status on health status changed", func() { - var app argocdv1alpha1.Application - var deploymentStatus githubmock.DeploymentStatus - - BeforeEach(func(ctx context.Context) { - By("Setting up a deployment status endpoint") - deploymentStatus = githubmock.DeploymentStatus{} - githubServer.AddHandlers(map[string]http.Handler{ - "GET /api/v3/repos/test/health-deployment/deployments/101/statuses": deploymentStatus.ListEndpoint(), - "POST /api/v3/repos/test/health-deployment/deployments/101/statuses": deploymentStatus.CreateEndpoint(), - }) - - By("Creating an application") - app = argocdv1alpha1.Application{ - TypeMeta: metav1.TypeMeta{ - APIVersion: "argoproj.io/v1alpha1", - Kind: "Application", - }, - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "fixture-deployment-status-health-", - Namespace: "default", - }, - Spec: argocdv1alpha1.ApplicationSpec{ - Project: "default", - Source: &argocdv1alpha1.ApplicationSource{ - RepoURL: "https://github.com/test/health-deployment.git", - Path: "test", - TargetRevision: "main", - }, - Destination: argocdv1alpha1.ApplicationDestination{ - Server: "https://kubernetes.default.svc", - Namespace: "default", - }, - }, - } - Expect(k8sClient.Create(ctx, &app)).Should(Succeed()) - - By("Updating the application to progressing") - app.Status = argocdv1alpha1.ApplicationStatus{ - Health: argocdv1alpha1.HealthStatus{ - Status: health.HealthStatusProgressing, - }, - OperationState: &argocdv1alpha1.OperationState{ - StartedAt: metav1.Now(), - Operation: argocdv1alpha1.Operation{ - Sync: &argocdv1alpha1.SyncOperation{ - Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - }, - }, - }, - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - }) - - Context("When an application is healthy", func() { - It("Should notify a deployment status once", func(ctx context.Context) { - By("Updating the deployment annotation") - app.Annotations = map[string]string{ - "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/test/health-deployment/deployments/101", - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the application to degraded") - app.Status.Health.Status = health.HealthStatusDegraded - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(1)) - - By("Updating the application to healthy") - app.Status.Health.Status = health.HealthStatusHealthy - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(2)) - - By("Updating the application to progressing") - app.Status.Health.Status = health.HealthStatusProgressing - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the application to healthy, again") - app.Status.Health.Status = health.HealthStatusHealthy - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Consistently(func() int { return deploymentStatus.CreateCount() }, "100ms").Should(Equal(2)) - }, SpecTimeout(3*time.Second)) - }) - - Context("When the deployment annotation is updated and then the application becomes healthy", func() { - It("Should notify a deployment status", func(ctx context.Context) { - By("Updating the deployment annotation") - app.Annotations = map[string]string{ - "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/test/health-deployment/deployments/999", - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the application to healthy") - app.Status.Health.Status = health.HealthStatusHealthy - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the deployment annotation") - app.Annotations = map[string]string{ - "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/test/health-deployment/deployments/101", - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Consistently(func() int { return deploymentStatus.CreateCount() }, "100ms").Should(BeZero()) - - By("Updating the application to progressing") - app.Status.Health.Status = health.HealthStatusProgressing - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the application to healthy") - app.Status.Health.Status = health.HealthStatusHealthy - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(1)) - }, SpecTimeout(3*time.Second)) - }) - - Context("When an application became healthy before the deployment annotation is updated", func() { - It("Should notify a deployment status when the deployment annotation is valid", func(ctx context.Context) { - By("Updating the deployment annotation") - app.Annotations = map[string]string{ - "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/test/health-deployment/deployments/999", - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the application to healthy") - app.Status.Health.Status = health.HealthStatusHealthy - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Consistently(func() int { return deploymentStatus.CreateCount() }, "100ms").Should(BeZero()) - - By("Updating the deployment annotation") - app.Annotations = map[string]string{ - "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/test/health-deployment/deployments/101", - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(1)) - - By("Deleting the old deployment") - deploymentStatus.NotFound = true - - By("Setting up the new deployment status endpoint") - var newDeploymentStatus githubmock.DeploymentStatus - githubServer.AddHandlers(map[string]http.Handler{ - "GET /api/v3/repos/test/health-deployment/deployments/102/statuses": newDeploymentStatus.ListEndpoint(), - "POST /api/v3/repos/test/health-deployment/deployments/102/statuses": newDeploymentStatus.CreateEndpoint(), - }) - - By("Updating the application to progressing") - app.Status.Health.Status = health.HealthStatusProgressing - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the application to healthy") - app.Status.Health.Status = health.HealthStatusHealthy - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Consistently(func() int { return newDeploymentStatus.CreateCount() }, "100ms").Should(BeZero()) - - By("Updating the deployment annotation") - app.Annotations = map[string]string{ - "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/test/health-deployment/deployments/102", - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Eventually(func() int { return newDeploymentStatus.CreateCount() }).Should(Equal(1)) - Expect(deploymentStatus.CreateCount()).Should(Equal(1)) - }, SpecTimeout(3*time.Second)) - - It("Should retry a deployment status until timeout", func(ctx context.Context) { - By("Updating the deployment annotation") - app.Annotations = map[string]string{ - "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/test/health-deployment/deployments/999", - } - app.Status = argocdv1alpha1.ApplicationStatus{ - OperationState: &argocdv1alpha1.OperationState{ - StartedAt: metav1.NewTime(time.Now().Add(-requeueTimeoutWhenDeploymentNotFound)), - }, - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the application to progressing") - app.Status.Health.Status = health.HealthStatusProgressing - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the application to healthy") - app.Status.Health.Status = health.HealthStatusHealthy - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - Eventually(func(g Gomega) { - var eventList corev1.EventList - g.Expect(k8sClient.List(ctx, &eventList, client.MatchingFields{ - "involvedObject.name": app.Name, - "reason": "DeploymentNotFoundRetryTimeout", - })).Should(Succeed()) - g.Expect(eventList.Items).Should(HaveLen(1)) - }) - }, SpecTimeout(3*time.Second)) - }) -}) diff --git a/internal/controller/applicationphasedeployment_controller_test.go b/internal/controller/applicationphasedeployment_controller_test.go deleted file mode 100644 index e70bd3da..00000000 --- a/internal/controller/applicationphasedeployment_controller_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package controller - -import ( - "context" - "net/http" - "time" - - argocdv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" - "github.com/argoproj/gitops-engine/pkg/health" - synccommon "github.com/argoproj/gitops-engine/pkg/sync/common" - "github.com/int128/argocd-commenter/internal/controller/githubmock" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -var _ = Describe("Deployment status on sync operation phase changed", func() { - var app argocdv1alpha1.Application - var deploymentStatus githubmock.DeploymentStatus - - BeforeEach(func(ctx context.Context) { - By("Setting up a deployment status endpoint") - deploymentStatus = githubmock.DeploymentStatus{} - githubServer.AddHandlers(map[string]http.Handler{ - "GET /api/v3/repos/test/phase-deployment/deployments/101/statuses": deploymentStatus.ListEndpoint(), - "POST /api/v3/repos/test/phase-deployment/deployments/101/statuses": deploymentStatus.CreateEndpoint(), - }) - - By("Creating an application") - app = argocdv1alpha1.Application{ - TypeMeta: metav1.TypeMeta{ - APIVersion: "argoproj.io/v1alpha1", - Kind: "Application", - }, - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "fixture-deployment-status-phase-", - Namespace: "default", - }, - Spec: argocdv1alpha1.ApplicationSpec{ - Project: "default", - Source: &argocdv1alpha1.ApplicationSource{ - RepoURL: "https://github.com/test/phase-deployment.git", - Path: "test", - TargetRevision: "main", - }, - Destination: argocdv1alpha1.ApplicationDestination{ - Server: "https://kubernetes.default.svc", - Namespace: "default", - }, - }, - } - Expect(k8sClient.Create(ctx, &app)).Should(Succeed()) - }) - - Context("When an application is synced", func() { - It("Should notify a deployment status", func(ctx context.Context) { - By("Updating the deployment annotation") - app.Annotations = map[string]string{ - "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/test/phase-deployment/deployments/101", - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the application to running") - app.Status = argocdv1alpha1.ApplicationStatus{ - OperationState: &argocdv1alpha1.OperationState{ - Phase: synccommon.OperationRunning, - StartedAt: metav1.Now(), - Operation: argocdv1alpha1.Operation{ - Sync: &argocdv1alpha1.SyncOperation{ - Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - }, - }, - }, - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(1)) - - By("Updating the application to succeeded") - app.Status.OperationState.Phase = synccommon.OperationSucceeded - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(2)) - - By("Updating the application to healthy") - app.Status.Health.Status = health.HealthStatusHealthy - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(3)) - - By("Updating the application to running") - app.Status.OperationState.Phase = synccommon.OperationRunning - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the application to succeeded") - app.Status.OperationState.Phase = synccommon.OperationSucceeded - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Consistently(func() int { return deploymentStatus.CreateCount() }, "100ms").Should(Equal(3)) - }, SpecTimeout(3*time.Second)) - }) - - Context("When an application sync operation is failed", func() { - It("Should notify a deployment status", func(ctx context.Context) { - By("Updating the deployment annotation") - app.Annotations = map[string]string{ - "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/test/phase-deployment/deployments/101", - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the application to running") - app.Status = argocdv1alpha1.ApplicationStatus{ - OperationState: &argocdv1alpha1.OperationState{ - Phase: synccommon.OperationRunning, - StartedAt: metav1.Now(), - Operation: argocdv1alpha1.Operation{ - Sync: &argocdv1alpha1.SyncOperation{ - Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - }, - }, - }, - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(1)) - - By("Updating the application to failed") - app.Status.OperationState.Phase = synccommon.OperationFailed - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - Eventually(func() int { return deploymentStatus.CreateCount() }).Should(Equal(2)) - }, SpecTimeout(3*time.Second)) - }) - - Context("When an application was synced before the deployment annotation is updated", func() { - It("Should skip the notification", func(ctx context.Context) { - By("Updating the deployment annotation") - app.Annotations = map[string]string{ - "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/test/phase-deployment/deployments/999", - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the application to succeeded") - app.Status = argocdv1alpha1.ApplicationStatus{ - OperationState: &argocdv1alpha1.OperationState{ - Phase: synccommon.OperationSucceeded, - StartedAt: metav1.Now(), - Operation: argocdv1alpha1.Operation{ - Sync: &argocdv1alpha1.SyncOperation{ - Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - }, - }, - }, - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - - By("Updating the deployment annotation") - app.Annotations = map[string]string{ - "argocd-commenter.int128.github.io/deployment-url": "https://api.github.com/repos/test/phase-deployment/deployments/101", - } - Expect(k8sClient.Update(ctx, &app)).Should(Succeed()) - // this test depends on requeueIntervalWhenDeploymentNotFound and takes longer time - Eventually(func() int { return deploymentStatus.CreateCount() }, 3*time.Second).Should(Equal(1)) - }, SpecTimeout(5*time.Second)) - }) -})