# Instructions - Following Playwright test failed. - Explain why, be concise, respect Playwright best practices. - Provide a snippet of code with the fix, if possible. # Test info - Name: tssc/full_workflow.test.ts >> TSSC Complete Workflow >> Deployment Verification >> should promote and verify deployment to production environment - Location: tests/tssc/full_workflow.test.ts:121:5 # Error details ``` ArgoCDApplicationNotFoundError: ArgoCD application 'e2e-tests-nodejs-sikztvbm-prod' not found in namespace 'tssc-gitops' ``` # Test source ```ts 1 | import { KubeClient } from '../../ocp/kubeClient'; 2 | import { ApplicationKind } from '../types/application.types'; 3 | import { 4 | ArgoCDApplicationNotFoundError, 5 | ArgoCDConnectionError, 6 | } from '../errors/argocd.errors'; 7 | import { LoggerFactory, Logger } from '../../../logger/logger'; 8 | 9 | /** 10 | * Service for managing ArgoCD applications 11 | */ 12 | export class ArgoCDApplicationService { 13 | private readonly API_GROUP = 'argoproj.io'; 14 | private readonly API_VERSION = 'v1alpha1'; 15 | private readonly APPLICATIONS_PLURAL = 'applications'; 16 | private readonly logger: Logger; 17 | 18 | constructor(private readonly kubeClient: KubeClient) { 19 | this.logger = LoggerFactory.getLogger('argocd.application'); 20 | } 21 | 22 | /** 23 | * Get ArgoCD Application 24 | */ 25 | public async getApplication( 26 | applicationName: string, 27 | namespace: string 28 | ): Promise { 29 | try { 30 | const options = this.kubeClient.createApiOptions( 31 | this.API_GROUP, 32 | this.API_VERSION, 33 | this.APPLICATIONS_PLURAL, 34 | namespace, 35 | { name: applicationName } 36 | ); 37 | 38 | const application = await this.kubeClient.getResource(options); 39 | 40 | if (!application) { > 41 | throw new ArgoCDApplicationNotFoundError(applicationName, namespace); | ^ ArgoCDApplicationNotFoundError: ArgoCD application 'e2e-tests-nodejs-sikztvbm-prod' not found in namespace 'tssc-gitops' 42 | } 43 | 44 | return application; 45 | } catch (error) { 46 | if (error instanceof ArgoCDApplicationNotFoundError) { 47 | throw error; 48 | } 49 | // Handle 404 specifically for application not found 50 | const statusCode = (error as any)?.response?.statusCode; 51 | if (statusCode === 404) { 52 | throw new ArgoCDApplicationNotFoundError(applicationName, namespace); 53 | } 54 | this.logger.error(`Error retrieving application ${applicationName}: ${error}`); 55 | throw new ArgoCDConnectionError( 56 | `Failed to get application ${applicationName}`, 57 | error instanceof Error ? error : new Error(String(error)) 58 | ); 59 | } 60 | } 61 | 62 | /** 63 | * List all ArgoCD Applications in a namespace 64 | */ 65 | public async listApplications( 66 | namespace: string, 67 | labelSelector?: string 68 | ): Promise { 69 | try { 70 | const options = this.kubeClient.createApiOptions( 71 | this.API_GROUP, 72 | this.API_VERSION, 73 | this.APPLICATIONS_PLURAL, 74 | namespace, 75 | { ...(labelSelector ? { labelSelector } : {}) } 76 | ); 77 | 78 | const applications = await this.kubeClient.listResources(options); 79 | 80 | return applications || []; 81 | } catch (error) { 82 | this.logger.error(`Error listing applications in namespace ${namespace}: ${error}`); 83 | return []; 84 | } 85 | } 86 | 87 | /** 88 | * Get the status of an ArgoCD application 89 | */ 90 | public async getApplicationStatus( 91 | applicationName: string, 92 | namespace: string 93 | ): Promise { 94 | const application = await this.getApplication(applicationName, namespace); 95 | 96 | if (!application.status) { 97 | return 'Status information not available'; 98 | } 99 | 100 | const healthStatus = application.status.health?.status || 'Unknown'; 101 | const syncStatus = application.status.sync?.status || 'Unknown'; 102 | const operationPhase = application.status.operationState?.phase || 'Unknown'; 103 | const reconciledAt = application.status.reconciledAt || 'Unknown'; 104 | 105 | let resourcesSummary = ''; 106 | if (application.status.resources && application.status.resources.length > 0) { 107 | const resourceCount = application.status.resources.length; 108 | const healthyCount = application.status.resources.filter( 109 | r => r.health?.status === 'Healthy' 110 | ).length; 111 | 112 | resourcesSummary = `Resources: ${healthyCount}/${resourceCount} healthy`; 113 | } 114 | 115 | // Format the status information 116 | return `Health: ${healthStatus}, Sync: ${syncStatus}, Operation: ${operationPhase}, Last Reconciled: ${reconciledAt}${ 117 | resourcesSummary ? ', ' + resourcesSummary : '' 118 | }`; 119 | } 120 | 121 | /** 122 | * Get health status of an ArgoCD application 123 | */ 124 | public async getApplicationHealth( 125 | applicationName: string, 126 | namespace: string 127 | ): Promise { 128 | const application = await this.getApplication(applicationName, namespace); 129 | return application.status?.health?.status || 'Unknown'; 130 | } 131 | 132 | /** 133 | * Get sync status of an ArgoCD application 134 | */ 135 | public async getApplicationSyncStatus( 136 | applicationName: string, 137 | namespace: string 138 | ): Promise { 139 | const application = await this.getApplication(applicationName, namespace); 140 | return application.status?.sync?.status || 'Unknown'; 141 | } ```