Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libs/domains/services/feature/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './lib/auto-deploy-badge/auto-deploy-badge'
export * from './lib/auto-deploy-setting/auto-deploy-setting'
export * from './lib/auto-deploy-section/auto-deploy-section'
export * from './lib/git-webhook-status-badge/git-webhook-status-badge'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { type IconName } from '@fortawesome/fontawesome-common-types'
import { type GitWebhookStatusResponse } from 'qovery-typescript-axios'
import { useParams } from 'react-router-dom'
import { APPLICATION_SETTINGS_GENERAL_URL, APPLICATION_SETTINGS_URL, APPLICATION_URL } from '@qovery/shared/routes'
import { Icon, Link, LoaderSpinner, Tooltip } from '@qovery/shared/ui'
import { useGitWebhookStatus } from '../hooks/use-git-webhook-status/use-git-webhook-status'

export interface AutoDeployBadgeProps {
serviceId: string
}

const webhookStatusConfig: Record<
GitWebhookStatusResponse['status'],
{
icon: IconName
iconClassName: string
tooltip: string
}
> = {
ACTIVE: {
icon: 'circle-check',
iconClassName: 'text-green-500',
tooltip: 'Webhook is correctly configured. Auto-deploy will trigger on git events.',
},
NOT_CONFIGURED: {
icon: 'circle-question',
iconClassName: 'text-red-500',
tooltip: 'No webhook found for auto-deployment. Click to configure it in settings.',
},
MISCONFIGURED: {
icon: 'triangle-exclamation',
iconClassName: 'text-yellow-500',
tooltip: 'Webhook is missing required events. Click to fix it in settings.',
},
UNABLE_TO_VERIFY: {
icon: 'circle-exclamation',
iconClassName: 'text-neutral-350',
tooltip:
"Couldn't verify webhook status. This could be due to expired credentials, insufficient permissions, or git provider API unavailability.",
},
}

export function AutoDeployBadge({ serviceId }: AutoDeployBadgeProps) {
const { organizationId = '', projectId = '', environmentId = '', applicationId = '' } = useParams()
const { data: webhookStatus, isLoading } = useGitWebhookStatus({ serviceId })

const config = webhookStatus ? webhookStatusConfig[webhookStatus.status] : undefined
const tooltipContent = config?.tooltip ?? 'Auto-deploy enabled. Click to view settings.'

const settingsUrl =
APPLICATION_URL(organizationId, projectId, environmentId, applicationId) +
APPLICATION_SETTINGS_URL +
APPLICATION_SETTINGS_GENERAL_URL

return (
<Tooltip content={tooltipContent}>
<Link as="button" color="neutral" variant="surface" size="xs" to={settingsUrl}>
<Icon className="text-neutral-350" iconName="arrows-rotate" />
<span className="ml-1.5">Auto-deploy</span>
{isLoading ? (
<LoaderSpinner classWidth="w-3" />
) : (
config && <Icon iconName={config.icon} className={`ml-1 text-xs ${config.iconClassName}`} />
)}
</Link>
</Tooltip>
)
}

export default AutoDeployBadge
26 changes: 17 additions & 9 deletions libs/pages/application/src/lib/ui/container/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useCluster } from '@qovery/domains/clusters/feature'
import { EnvironmentMode, useEnvironment } from '@qovery/domains/environments/feature'
import { type AnyService, type Database } from '@qovery/domains/services/data-access'
import {
AutoDeployBadge,
NeedRedeployFlag,
ServiceActionToolbar,
ServiceAvatar,
Expand All @@ -15,7 +16,7 @@ import {
useService,
} from '@qovery/domains/services/feature'
import { VariablesProvider } from '@qovery/domains/variables/feature'
import { IconEnum } from '@qovery/shared/enums'
import { IconEnum, isHelmGitSource, isJobGitSource } from '@qovery/shared/enums'
import {
APPLICATION_DEPLOYMENTS_URL,
APPLICATION_GENERAL_URL,
Expand Down Expand Up @@ -155,14 +156,21 @@ export function Container({ children }: ContainerProps) {
</Link>
</Tooltip>
</Skeleton>
<Skeleton width={22} height={24} show={!service}>
{service && 'auto_deploy' in service && service.auto_deploy && (
<Tooltip content="Auto-deploy">
<Badge variant="outline">
<Icon className="text-neutral-350" iconName="arrows-rotate" />
</Badge>
</Tooltip>
)}
<Skeleton width={120} height={24} show={!service}>
{service &&
'auto_deploy' in service &&
service.auto_deploy &&
match(service)
.with({ serviceType: 'APPLICATION' }, { serviceType: 'TERRAFORM' }, () => (
<AutoDeployBadge serviceId={service.id} />
))
.with({ serviceType: 'JOB' }, (job) =>
isJobGitSource(job.source) ? <AutoDeployBadge serviceId={service.id} /> : null
)
.with({ serviceType: 'HELM' }, (helm) =>
isHelmGitSource(helm.source) ? <AutoDeployBadge serviceId={service.id} /> : null
)
.otherwise(() => null)}
</Skeleton>
</div>
</div>
Expand Down