diff --git a/libs/domains/observability/feature/src/lib/alerting/alert-rules-overview/alert-rules-overview.tsx b/libs/domains/observability/feature/src/lib/alerting/alert-rules-overview/alert-rules-overview.tsx
index c5492aa18cf..c1491ee01c0 100644
--- a/libs/domains/observability/feature/src/lib/alerting/alert-rules-overview/alert-rules-overview.tsx
+++ b/libs/domains/observability/feature/src/lib/alerting/alert-rules-overview/alert-rules-overview.tsx
@@ -4,6 +4,7 @@ import { type PropsWithChildren, type ReactNode, useMemo, useState } from 'react
import { useNavigate } from 'react-router-dom'
import { match } from 'ts-pattern'
import { type AnyService } from '@qovery/domains/services/data-access'
+import { useDeploymentStatus } from '@qovery/domains/services/feature'
import {
APPLICATION_MONITORING_ALERTS_URL,
APPLICATION_MONITORING_ALERT_EDIT_URL,
@@ -101,6 +102,10 @@ export function AlertRulesOverview({
const { openModal, closeModal } = useModal()
const { openModalConfirmation } = useModalConfirmation()
const navigate = useNavigate()
+ const { data: deploymentStatus } = useDeploymentStatus({
+ environmentId: service?.environment?.id,
+ serviceId: service?.id,
+ })
const { mutate: deleteAlertRule } = useDeleteAlertRule({ organizationId })
@@ -156,6 +161,13 @@ export function AlertRulesOverview({
[selectedAlertRuleIds.size, selectableAlertRules.length]
)
+ const canCreateAlerts = useMemo(() => {
+ return (
+ deploymentStatus?.service_deployment_status !== undefined &&
+ deploymentStatus?.service_deployment_status !== 'NEVER_DEPLOYED'
+ )
+ }, [deploymentStatus])
+
const toggleSelectAll = (checked: boolean) => {
if (checked) {
const allIds = new Set(selectableAlertRules.map((alertRule) => alertRule.id))
@@ -240,10 +252,14 @@ export function AlertRulesOverview({
)}
{onCreateKeyAlerts && (
-
+
+
+
+
+
)}
) : (
diff --git a/libs/domains/observability/feature/src/lib/alerting/alerting-creation-flow/alerting-creation-flow.tsx b/libs/domains/observability/feature/src/lib/alerting/alerting-creation-flow/alerting-creation-flow.tsx
index 7ff45e92059..48330b0e0a9 100644
--- a/libs/domains/observability/feature/src/lib/alerting/alerting-creation-flow/alerting-creation-flow.tsx
+++ b/libs/domains/observability/feature/src/lib/alerting/alerting-creation-flow/alerting-creation-flow.tsx
@@ -164,7 +164,7 @@ export function AlertingCreationFlow({
service?.min_running_instances !== service?.max_running_instances
if (!containerName) return
- if (hasPublicPort && !ingressName) return
+ if (hasPublicPort && !(ingressName || httpRouteName)) return
if (hasAutoscaling && !hpaName) return
try {
diff --git a/libs/domains/observability/feature/src/lib/service/service-alerting/service-alerting.spec.tsx b/libs/domains/observability/feature/src/lib/service/service-alerting/service-alerting.spec.tsx
index 2444abb1b95..a4b331bcd48 100644
--- a/libs/domains/observability/feature/src/lib/service/service-alerting/service-alerting.spec.tsx
+++ b/libs/domains/observability/feature/src/lib/service/service-alerting/service-alerting.spec.tsx
@@ -1,5 +1,5 @@
import { AlertRuleState } from 'qovery-typescript-axios'
-import { renderWithProviders, screen } from '@qovery/shared/util-tests'
+import { renderWithProviders, screen, within } from '@qovery/shared/util-tests'
import { ServiceAlerting } from './service-alerting'
const mockUseParams = jest.fn()
@@ -8,6 +8,7 @@ const mockUseAlertRulesGhosted = jest.fn()
const mockUseDeleteAlertRule = jest.fn()
const mockUseEnvironment = jest.fn()
const mockUseService = jest.fn()
+const mockUseDeploymentStatus = jest.fn()
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
@@ -32,6 +33,7 @@ jest.mock('../../hooks/use-environment/use-environment', () => ({
jest.mock('@qovery/domains/services/feature', () => ({
useService: (params: unknown) => mockUseService(params),
+ useDeploymentStatus: (params: unknown) => mockUseDeploymentStatus(params),
}))
describe('ServiceAlerting', () => {
@@ -93,6 +95,30 @@ describe('ServiceAlerting', () => {
mockUseDeleteAlertRule.mockReturnValue({
mutate: jest.fn(),
})
+ mockUseDeploymentStatus.mockReturnValue({
+ data: { service_deployment_status: 'DEPLOYED' },
+ isFetched: true,
+ })
+ })
+
+ it('should display tooltip explaining alerts require deployment when service was never deployed', async () => {
+ mockUseDeploymentStatus.mockReturnValue({
+ data: { service_deployment_status: 'NEVER_DEPLOYED' },
+ isFetched: true,
+ })
+
+ const { userEvent } = renderWithProviders()
+
+ const headerToolbar = screen.getByRole('heading', { name: 'Alert rules' }).parentElement
+ expect(headerToolbar).toBeInTheDocument()
+ const newAlertButton = within(headerToolbar as HTMLElement).getByRole('button', { name: /new alert/i })
+ await userEvent.hover(newAlertButton.parentElement ?? newAlertButton)
+
+ expect(
+ await screen.findByRole('tooltip', {
+ name: 'You need to deploy your service to create alerts',
+ })
+ ).toBeInTheDocument()
})
it('should render loader when environment is not loaded', () => {
diff --git a/libs/domains/observability/feature/src/lib/service/service-alerting/service-alerting.tsx b/libs/domains/observability/feature/src/lib/service/service-alerting/service-alerting.tsx
index c31f1861137..4fd3c6985c1 100644
--- a/libs/domains/observability/feature/src/lib/service/service-alerting/service-alerting.tsx
+++ b/libs/domains/observability/feature/src/lib/service/service-alerting/service-alerting.tsx
@@ -1,8 +1,8 @@
-import { type PropsWithChildren } from 'react'
+import { type PropsWithChildren, useMemo } from 'react'
import { useParams } from 'react-router-dom'
import { type AnyService } from '@qovery/domains/services/data-access'
-import { useService } from '@qovery/domains/services/feature'
-import { Button, Chart, Heading, Icon, Section, useModal } from '@qovery/shared/ui'
+import { useDeploymentStatus, useService } from '@qovery/domains/services/feature'
+import { Button, Chart, Heading, Icon, Section, Tooltip, useModal } from '@qovery/shared/ui'
import { AlertRulesOverview } from '../../alerting/alert-rules-overview/alert-rules-overview'
import { CreateKeyAlertsModal } from '../../alerting/create-key-alerts-modal/create-key-alerts-modal'
import { useEnvironment } from '../../hooks/use-environment/use-environment'
@@ -15,6 +15,10 @@ interface ServiceAlertingContentProps extends PropsWithChildren {
function ServiceAlertingContent({ organizationId, projectId, service, children }: ServiceAlertingContentProps) {
const { openModal, closeModal } = useModal()
+ const { data: deploymentStatus } = useDeploymentStatus({
+ environmentId: service?.environment?.id,
+ serviceId: service?.id,
+ })
const createKeyAlertsModal = () => {
openModal({
@@ -32,15 +36,33 @@ function ServiceAlertingContent({ organizationId, projectId, service, children }
})
}
+ const canCreateAlerts = useMemo(() => {
+ return (
+ deploymentStatus?.service_deployment_status !== undefined &&
+ deploymentStatus?.service_deployment_status !== 'NEVER_DEPLOYED'
+ )
+ }, [deploymentStatus])
+
return (
Alert rules
-
+
+
+
+
+