@@ -15,10 +15,12 @@ import { getRunnerLogger } from "./logging";
1515import { OverlayDatabaseMode } from "./overlay/overlay-database-mode" ;
1616import * as overlayStatus from "./overlay/status" ;
1717import { parseRepositoryNwo } from "./repository" ;
18+ import { JobStatus } from "./status-report" ;
1819import {
1920 createFeatures ,
2021 createTestConfig ,
2122 DEFAULT_ACTIONS_VARS ,
23+ getTestEnv ,
2224 makeMacro ,
2325 makeVersionInfo ,
2426 RecordingLogger ,
@@ -58,6 +60,8 @@ test.serial("init-post action with debug mode off", async (t) => {
5860 createTestConfig ( { debugMode : false } ) ,
5961 parseRepositoryNwo ( "github/codeql-action" ) ,
6062 createFeatures ( [ ] ) ,
63+ "success" ,
64+ getTestEnv ( ) ,
6165 getRunnerLogger ( true ) ,
6266 ) ;
6367
@@ -80,6 +84,8 @@ test.serial("init-post action with debug mode on", async (t) => {
8084 createTestConfig ( { debugMode : true } ) ,
8185 parseRepositoryNwo ( "github/codeql-action" ) ,
8286 createFeatures ( [ ] ) ,
87+ "success" ,
88+ getTestEnv ( ) ,
8389 getRunnerLogger ( true ) ,
8490 ) ;
8591
@@ -375,6 +381,8 @@ test.serial(
375381 } ) ,
376382 parseRepositoryNwo ( "github/codeql-action" ) ,
377383 createFeatures ( [ Feature . OverlayAnalysisStatusSave ] ) ,
384+ "success" ,
385+ getTestEnv ( ) ,
378386 getRunnerLogger ( true ) ,
379387 ) ;
380388
@@ -443,6 +451,8 @@ test.serial(
443451 } ) ,
444452 parseRepositoryNwo ( "github/codeql-action" ) ,
445453 createFeatures ( [ ] ) ,
454+ "success" ,
455+ getTestEnv ( ) ,
446456 getRunnerLogger ( true ) ,
447457 ) ;
448458
@@ -457,8 +467,13 @@ test.serial(
457467test . serial ( "does not save overlay status when build successful" , async ( t ) => {
458468 return await util . withTmpDir ( async ( tmpDir ) => {
459469 setupActionsVars ( tmpDir , tmpDir ) ;
460- // Mark analyze as having completed successfully.
470+ // Mark analyze as having completed successfully. `tryUploadSarifIfRunFailed` reads this from
471+ // the process environment, while `recordOverlayStatus` reads it from the environment it is
472+ // given.
461473 process . env [ EnvVar . ANALYZE_DID_COMPLETE_SUCCESSFULLY ] = "true" ;
474+ const env = getTestEnv ( {
475+ [ EnvVar . ANALYZE_DID_COMPLETE_SUCCESSFULLY ] : "true" ,
476+ } ) ;
462477
463478 sinon . stub ( util , "checkDiskUsage" ) . resolves ( {
464479 numAvailableBytes : 100 * NUM_BYTES_PER_GIB ,
@@ -480,6 +495,8 @@ test.serial("does not save overlay status when build successful", async (t) => {
480495 } ) ,
481496 parseRepositoryNwo ( "github/codeql-action" ) ,
482497 createFeatures ( [ Feature . OverlayAnalysisStatusSave ] ) ,
498+ "success" ,
499+ env ,
483500 getRunnerLogger ( true ) ,
484501 ) ;
485502
@@ -517,6 +534,8 @@ test.serial(
517534 } ) ,
518535 parseRepositoryNwo ( "github/codeql-action" ) ,
519536 createFeatures ( [ ] ) ,
537+ "success" ,
538+ getTestEnv ( ) ,
520539 getRunnerLogger ( true ) ,
521540 ) ;
522541
@@ -528,6 +547,137 @@ test.serial(
528547 } ,
529548) ;
530549
550+ /**
551+ * Runs `uploadFailureInfo` for an overlay-base job that did not complete successfully, with the
552+ * given job status from the Actions runtime environment.
553+ */
554+ async function runOverlayPostStep ( {
555+ jobStatus,
556+ codeQlReportedError = false ,
557+ } : {
558+ jobStatus : string | undefined ;
559+ codeQlReportedError ?: boolean ;
560+ } ) {
561+ return await util . withTmpDir ( async ( tmpDir ) => {
562+ setupActionsVars ( tmpDir , tmpDir ) ;
563+ delete process . env [ EnvVar . ANALYZE_DID_COMPLETE_SUCCESSFULLY ] ;
564+ const env = getTestEnv (
565+ codeQlReportedError
566+ ? { [ EnvVar . JOB_STATUS ] : JobStatus . FailureStatus }
567+ : { } ,
568+ ) ;
569+
570+ sinon . stub ( util , "checkDiskUsage" ) . resolves ( {
571+ numAvailableBytes : 100 * NUM_BYTES_PER_GIB ,
572+ numTotalBytes : 200 * NUM_BYTES_PER_GIB ,
573+ } ) ;
574+
575+ const saveOverlayStatusStub = sinon
576+ . stub ( overlayStatus , "saveOverlayStatus" )
577+ . resolves ( true ) ;
578+
579+ await initActionPostHelper . uploadFailureInfo (
580+ sinon . spy ( ) ,
581+ sinon . spy ( ) ,
582+ codeql . createStubCodeQL ( { } ) ,
583+ createTestConfig ( {
584+ debugMode : false ,
585+ languages : [ "javascript" ] ,
586+ overlayDatabaseMode : OverlayDatabaseMode . OverlayBase ,
587+ } ) ,
588+ parseRepositoryNwo ( "github/codeql-action" ) ,
589+ createFeatures ( [ Feature . OverlayAnalysisStatusSave ] ) ,
590+ jobStatus ,
591+ env ,
592+ getRunnerLogger ( true ) ,
593+ ) ;
594+
595+ return { saveOverlayStatusStub } ;
596+ } ) ;
597+ }
598+
599+ test . serial (
600+ "does not save overlay status when the job was cancelled" ,
601+ async ( t ) => {
602+ const { saveOverlayStatusStub } = await runOverlayPostStep ( {
603+ jobStatus : "cancelled" ,
604+ } ) ;
605+
606+ t . true (
607+ saveOverlayStatusStub . notCalled ,
608+ "a cancellation tells us nothing about whether the analysis would have succeeded" ,
609+ ) ;
610+ } ,
611+ ) ;
612+
613+ test . serial (
614+ "does not save overlay status when the job status is not recognised" ,
615+ async ( t ) => {
616+ const { saveOverlayStatusStub } = await runOverlayPostStep ( {
617+ jobStatus : "some-new-status" ,
618+ } ) ;
619+
620+ t . true (
621+ saveOverlayStatusStub . notCalled ,
622+ "a status we do not recognise tells us nothing about whether the analysis would have succeeded" ,
623+ ) ;
624+ } ,
625+ ) ;
626+
627+ test . serial (
628+ "does not save overlay status when the job status is unavailable" ,
629+ async ( t ) => {
630+ const { saveOverlayStatusStub } = await runOverlayPostStep ( {
631+ jobStatus : undefined ,
632+ } ) ;
633+
634+ t . true (
635+ saveOverlayStatusStub . notCalled ,
636+ "without a job status we cannot tell whether the analysis would have succeeded" ,
637+ ) ;
638+ } ,
639+ ) ;
640+
641+ test . serial (
642+ "saves overlay status when the job failed rather than being cancelled" ,
643+ async ( t ) => {
644+ const { saveOverlayStatusStub } = await runOverlayPostStep ( {
645+ jobStatus : "failure" ,
646+ } ) ;
647+
648+ t . true (
649+ saveOverlayStatusStub . calledOnce ,
650+ "a failed job indicates that the analysis itself failed" ,
651+ ) ;
652+ } ,
653+ ) ;
654+
655+ test . serial ( "saves overlay status when the job succeeded" , async ( t ) => {
656+ const { saveOverlayStatusStub } = await runOverlayPostStep ( {
657+ jobStatus : "success" ,
658+ } ) ;
659+
660+ t . true (
661+ saveOverlayStatusStub . calledOnce ,
662+ "the analysis did not complete successfully even though the job as a whole succeeded" ,
663+ ) ;
664+ } ) ;
665+
666+ test . serial (
667+ "saves overlay status when a CodeQL Action reported an error before the run was cancelled" ,
668+ async ( t ) => {
669+ const { saveOverlayStatusStub } = await runOverlayPostStep ( {
670+ jobStatus : "cancelled" ,
671+ codeQlReportedError : true ,
672+ } ) ;
673+
674+ t . true (
675+ saveOverlayStatusStub . calledOnce ,
676+ "the analysis genuinely failed, even though the run was later cancelled" ,
677+ ) ;
678+ } ,
679+ ) ;
680+
531681function createTestWorkflow (
532682 steps : workflow . WorkflowJobStep [ ] ,
533683) : workflow . Workflow {
0 commit comments