@@ -170,6 +170,7 @@ export class PhasedScriptAction extends BaseScriptAction<IPhasedCommandConfig> i
170170 private readonly _nodeDiagnosticDirParameter : CommandLineStringParameter ;
171171 private readonly _debugBuildCacheIdsParameter : CommandLineFlagParameter ;
172172 private readonly _includePhaseDeps : CommandLineFlagParameter | undefined ;
173+ private readonly _showExistingFailureLogsParameter : CommandLineFlagParameter ;
173174
174175 public constructor ( options : IPhasedScriptActionOptions ) {
175176 super ( options ) ;
@@ -326,6 +327,14 @@ export class PhasedScriptAction extends BaseScriptAction<IPhasedCommandConfig> i
326327 'Logs information about the components of the build cache ids for individual operations. This is useful for debugging the incremental build logic.'
327328 } ) ;
328329
330+ this . _showExistingFailureLogsParameter = this . defineFlagParameter ( {
331+ parameterLongName : '--show-existing-failure-logs' ,
332+ description :
333+ 'Skips execution of operations and instead displays any existing failure logs for the selected projects. ' +
334+ 'This is useful for reviewing failures from a previous run without re-executing the operations. ' +
335+ 'Operations without existing failure logs will be silenced.'
336+ } ) ;
337+
329338 this . defineScriptParameters ( ) ;
330339
331340 // Associate parameters with their respective phases
@@ -485,43 +494,62 @@ export class PhasedScriptAction extends BaseScriptAction<IPhasedCommandConfig> i
485494 }
486495
487496 const isWatch : boolean = this . _watchParameter ?. value || this . _alwaysWatch ;
497+ const showExistingFailureLogs : boolean = this . _showExistingFailureLogsParameter . value ;
498+
499+ // If showing existing failure logs, we don't want to enable watch mode
500+ if ( showExistingFailureLogs && isWatch ) {
501+ throw new Error ( 'The --show-existing-failure-logs parameter cannot be used with --watch.' ) ;
502+ }
488503
489504 await measureAsyncFn ( `${ PERF_PREFIX } :applySituationalPlugins` , async ( ) => {
490- if ( isWatch && this . _noIPCParameter ?. value === false ) {
505+ if ( showExistingFailureLogs ) {
506+ // Apply the plugin that replays existing failure logs without executing operations
507+ terminal . writeVerboseLine ( `Mode: showing existing failure logs` ) ;
508+ const { ShowExistingFailureLogsPlugin } = await import (
509+ /* webpackChunkName: 'ShowExistingFailureLogsPlugin' */
510+ '../../logic/operations/ShowExistingFailureLogsPlugin'
511+ ) ;
512+ new ShowExistingFailureLogsPlugin ( {
513+ terminal
514+ } ) . apply ( this . hooks ) ;
515+ } else if ( isWatch && this . _noIPCParameter ?. value === false ) {
491516 new (
492517 await import (
493518 /* webpackChunkName: 'IPCOperationRunnerPlugin' */ '../../logic/operations/IPCOperationRunnerPlugin'
494519 )
495520 ) . IPCOperationRunnerPlugin ( ) . apply ( this . hooks ) ;
496521 }
497522
498- if ( buildCacheConfiguration ?. buildCacheEnabled ) {
499- terminal . writeVerboseLine ( `Incremental strategy: cache restoration` ) ;
500- new CacheableOperationPlugin ( {
501- allowWarningsInSuccessfulBuild :
502- ! ! this . rushConfiguration . experimentsConfiguration . configuration
503- . buildCacheWithAllowWarningsInSuccessfulBuild ,
504- buildCacheConfiguration,
505- cobuildConfiguration,
506- terminal
507- } ) . apply ( this . hooks ) ;
508-
509- if ( this . _debugBuildCacheIdsParameter . value ) {
510- new DebugHashesPlugin ( terminal ) . apply ( this . hooks ) ;
523+ // Skip build cache and legacy skip plugins when showing existing failure logs
524+ if ( ! showExistingFailureLogs ) {
525+ if ( buildCacheConfiguration ?. buildCacheEnabled ) {
526+ terminal . writeVerboseLine ( `Incremental strategy: cache restoration` ) ;
527+ new CacheableOperationPlugin ( {
528+ allowWarningsInSuccessfulBuild :
529+ ! ! this . rushConfiguration . experimentsConfiguration . configuration
530+ . buildCacheWithAllowWarningsInSuccessfulBuild ,
531+ buildCacheConfiguration,
532+ cobuildConfiguration,
533+ terminal
534+ } ) . apply ( this . hooks ) ;
535+
536+ if ( this . _debugBuildCacheIdsParameter . value ) {
537+ new DebugHashesPlugin ( terminal ) . apply ( this . hooks ) ;
538+ }
539+ } else if ( ! this . _disableBuildCache ) {
540+ terminal . writeVerboseLine ( `Incremental strategy: output preservation` ) ;
541+ // Explicitly disabling the build cache also disables legacy skip detection.
542+ new LegacySkipPlugin ( {
543+ allowWarningsInSuccessfulBuild :
544+ this . rushConfiguration . experimentsConfiguration . configuration
545+ . buildSkipWithAllowWarningsInSuccessfulBuild ,
546+ terminal,
547+ changedProjectsOnly,
548+ isIncrementalBuildAllowed : this . _isIncrementalBuildAllowed
549+ } ) . apply ( this . hooks ) ;
550+ } else {
551+ terminal . writeVerboseLine ( `Incremental strategy: none (full rebuild)` ) ;
511552 }
512- } else if ( ! this . _disableBuildCache ) {
513- terminal . writeVerboseLine ( `Incremental strategy: output preservation` ) ;
514- // Explicitly disabling the build cache also disables legacy skip detection.
515- new LegacySkipPlugin ( {
516- allowWarningsInSuccessfulBuild :
517- this . rushConfiguration . experimentsConfiguration . configuration
518- . buildSkipWithAllowWarningsInSuccessfulBuild ,
519- terminal,
520- changedProjectsOnly,
521- isIncrementalBuildAllowed : this . _isIncrementalBuildAllowed
522- } ) . apply ( this . hooks ) ;
523- } else {
524- terminal . writeVerboseLine ( `Incremental strategy: none (full rebuild)` ) ;
525553 }
526554
527555 const showBuildPlan : boolean = this . _cobuildPlanParameter ?. value ?? false ;
0 commit comments