@@ -97,6 +97,7 @@ async function* runBuildAndTest(
97
97
context : BuilderContext ,
98
98
extensions : ApplicationBuilderExtensions | undefined ,
99
99
) : AsyncIterable < BuilderOutput > {
100
+ let consecutiveErrorCount = 0 ;
100
101
for await ( const buildResult of buildApplicationInternal (
101
102
applicationBuildOptions ,
102
103
context ,
@@ -117,7 +118,25 @@ async function* runBuildAndTest(
117
118
assert ( buildResult . files , 'Builder did not provide result files.' ) ;
118
119
119
120
// Pass the build artifacts to the executor
120
- yield * executor . execute ( buildResult ) ;
121
+ try {
122
+ yield * executor . execute ( buildResult ) ;
123
+
124
+ // Successful execution resets the failure counter
125
+ consecutiveErrorCount = 0 ;
126
+ } catch ( e ) {
127
+ assertIsError ( e ) ;
128
+ context . logger . error ( `An exception occurred during test execution:\n${ e . stack ?? e . message } ` ) ;
129
+ yield { success : false } ;
130
+ consecutiveErrorCount ++ ;
131
+ }
132
+
133
+ if ( consecutiveErrorCount >= 3 ) {
134
+ context . logger . error (
135
+ 'Test runner process has failed multiple times in a row. Please fix the configuration and restart the process.' ,
136
+ ) ;
137
+
138
+ return ;
139
+ }
121
140
}
122
141
}
123
142
@@ -141,15 +160,36 @@ export async function* execute(
141
160
`NOTE: The "unit-test" builder is currently EXPERIMENTAL and not ready for production use.` ,
142
161
) ;
143
162
144
- const normalizedOptions = await normalizeOptions ( context , projectName , options ) ;
145
- const runner = await loadTestRunner ( normalizedOptions . runnerName ) ;
163
+ // Initialize the test runner and normalize options
164
+ let runner ;
165
+ let normalizedOptions ;
166
+ try {
167
+ normalizedOptions = await normalizeOptions ( context , projectName , options ) ;
168
+ runner = await loadTestRunner ( normalizedOptions . runnerName ) ;
169
+ } catch ( e ) {
170
+ assertIsError ( e ) ;
171
+ context . logger . error (
172
+ `An exception occurred during initialization of the test runner:\n${ e . stack ?? e . message } ` ,
173
+ ) ;
174
+ yield { success : false } ;
175
+
176
+ return ;
177
+ }
146
178
147
179
if ( runner . isStandalone ) {
148
- await using executor = await runner . createExecutor ( context , normalizedOptions , undefined ) ;
149
- yield * executor . execute ( {
150
- kind : ResultKind . Full ,
151
- files : { } ,
152
- } ) ;
180
+ try {
181
+ await using executor = await runner . createExecutor ( context , normalizedOptions , undefined ) ;
182
+ yield * executor . execute ( {
183
+ kind : ResultKind . Full ,
184
+ files : { } ,
185
+ } ) ;
186
+ } catch ( e ) {
187
+ assertIsError ( e ) ;
188
+ context . logger . error (
189
+ `An exception occurred during standalone test execution:\n${ e . stack ?? e . message } ` ,
190
+ ) ;
191
+ yield { success : false } ;
192
+ }
153
193
154
194
return ;
155
195
}
@@ -164,41 +204,65 @@ export async function* execute(
164
204
} catch ( e ) {
165
205
assertIsError ( e ) ;
166
206
context . logger . error (
167
- `Could not load build target options for "${ targetStringFromTarget ( normalizedOptions . buildTarget ) } ".\n` +
207
+ `Could not load build target options for "${ targetStringFromTarget (
208
+ normalizedOptions . buildTarget ,
209
+ ) } ".\n` +
168
210
`Please check your 'angular.json' configuration.\n` +
169
211
`Error: ${ e . message } ` ,
170
212
) ;
213
+ yield { success : false } ;
171
214
172
215
return ;
173
216
}
174
217
175
- // Get runner-specific build options from the hook
176
- const {
177
- buildOptions : runnerBuildOptions ,
178
- virtualFiles,
179
- testEntryPointMappings,
180
- } = await runner . getBuildOptions ( normalizedOptions , buildTargetOptions ) ;
218
+ // Get runner-specific build options
219
+ let runnerBuildOptions ;
220
+ let virtualFiles ;
221
+ let testEntryPointMappings ;
222
+ try {
223
+ ( {
224
+ buildOptions : runnerBuildOptions ,
225
+ virtualFiles,
226
+ testEntryPointMappings,
227
+ } = await runner . getBuildOptions ( normalizedOptions , buildTargetOptions ) ) ;
228
+ } catch ( e ) {
229
+ assertIsError ( e ) ;
230
+ context . logger . error (
231
+ `An exception occurred while getting runner-specific build options:\n${ e . stack ?? e . message } ` ,
232
+ ) ;
233
+ yield { success : false } ;
234
+
235
+ return ;
236
+ }
181
237
182
- await using executor = await runner . createExecutor (
183
- context ,
184
- normalizedOptions ,
185
- testEntryPointMappings ,
186
- ) ;
238
+ try {
239
+ await using executor = await runner . createExecutor (
240
+ context ,
241
+ normalizedOptions ,
242
+ testEntryPointMappings ,
243
+ ) ;
187
244
188
- const finalExtensions = prepareBuildExtensions (
189
- virtualFiles ,
190
- normalizedOptions . projectSourceRoot ,
191
- extensions ,
192
- ) ;
245
+ const finalExtensions = prepareBuildExtensions (
246
+ virtualFiles ,
247
+ normalizedOptions . projectSourceRoot ,
248
+ extensions ,
249
+ ) ;
193
250
194
- // Prepare and run the application build
195
- const applicationBuildOptions = {
196
- ...buildTargetOptions ,
197
- ...runnerBuildOptions ,
198
- watch : normalizedOptions . watch ,
199
- tsConfig : normalizedOptions . tsConfig ,
200
- progress : normalizedOptions . buildProgress ?? buildTargetOptions . progress ,
201
- } satisfies ApplicationBuilderInternalOptions ;
251
+ // Prepare and run the application build
252
+ const applicationBuildOptions = {
253
+ ...buildTargetOptions ,
254
+ ...runnerBuildOptions ,
255
+ watch : normalizedOptions . watch ,
256
+ tsConfig : normalizedOptions . tsConfig ,
257
+ progress : normalizedOptions . buildProgress ?? buildTargetOptions . progress ,
258
+ } satisfies ApplicationBuilderInternalOptions ;
202
259
203
- yield * runBuildAndTest ( executor , applicationBuildOptions , context , finalExtensions ) ;
260
+ yield * runBuildAndTest ( executor , applicationBuildOptions , context , finalExtensions ) ;
261
+ } catch ( e ) {
262
+ assertIsError ( e ) ;
263
+ context . logger . error (
264
+ `An exception occurred while creating the test executor:\n${ e . stack ?? e . message } ` ,
265
+ ) ;
266
+ yield { success : false } ;
267
+ }
204
268
}
0 commit comments