Skip to content
Open
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
29 changes: 29 additions & 0 deletions lib/init-action.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions src/init-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
import {
getDiffInformedAnalysisBranches,
getPullRequestEditedDiffRanges,
shouldPerformDiffInformedAnalysis,
writeDiffRangesJsonFile,
} from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment";
Expand All @@ -64,6 +65,7 @@ import {
downloadOverlayBaseDatabaseFromCache,
OverlayBaseDatabaseDownloadStats,
OverlayDatabaseMode,
revertOverlayModeIfDiffInformedUnavailable,
} from "./overlay";
import { getRepositoryNwo, RepositoryNwo } from "./repository";
import { ToolsSource } from "./setup-codeql";
Expand Down Expand Up @@ -438,6 +440,27 @@ async function run(startedAt: Date) {
return;
}

let diffInformedAnalysisExpected = false;
try {
diffInformedAnalysisExpected = await shouldPerformDiffInformedAnalysis(
codeql,
features,
logger,
);
} catch (e) {
logger.warning(
`Failed to determine diff-informed analysis availability: ${getErrorMessage(e)}`,
);
// Treat errors conservatively: assume diff-informed was expected so that
// the overlay fallback triggers if the diff ranges file is missing.
diffInformedAnalysisExpected = true;
}
revertOverlayModeIfDiffInformedUnavailable(
config,
diffInformedAnalysisExpected,
logger,
);

let overlayBaseDatabaseStats: OverlayBaseDatabaseDownloadStats | undefined;
let dependencyCachingStatus: DependencyCacheRestoreStatusReport | undefined;
try {
Expand Down
75 changes: 75 additions & 0 deletions src/overlay/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
getCacheRestoreKeyPrefix,
getCacheSaveKey,
OverlayDatabaseMode,
revertOverlayModeIfDiffInformedUnavailable,
writeBaseDatabaseOidsFile,
writeOverlayChangesFile,
} from ".";
Expand Down Expand Up @@ -602,3 +603,77 @@ test.serial("overlay-base database cache keys remain stable", async (t) => {
`Expected save key "${saveKey}" to start with restore key prefix "${restoreKeyPrefix}"`,
);
});

test.serial(
"revertOverlayModeIfDiffInformedUnavailable: no-op when mode is not Overlay",
(t) => {
const config = createTestConfig({});
config.overlayDatabaseMode = OverlayDatabaseMode.None;
const logger = getRunnerLogger(true);

revertOverlayModeIfDiffInformedUnavailable(config, true, logger);

t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
},
);

test.serial(
"revertOverlayModeIfDiffInformedUnavailable: no-op when diff ranges file exists",
async (t) => {
await withTmpDir(async (tmpDir) => {
const config = createTestConfig({});
config.overlayDatabaseMode = OverlayDatabaseMode.Overlay;
const logger = getRunnerLogger(true);

// Create the diff ranges file so it exists
const diffRangesPath = path.join(tmpDir, "pr-diff-range.json");
await fs.promises.writeFile(diffRangesPath, "[]");
const stub = sinon
.stub(actionsUtil, "getDiffRangesJsonFilePath")
.returns(diffRangesPath);

try {
revertOverlayModeIfDiffInformedUnavailable(config, true, logger);
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.Overlay);
} finally {
stub.restore();
}
});
},
);

test.serial(
"revertOverlayModeIfDiffInformedUnavailable: reverts to None when diff ranges file is missing",
(t) => {
const config = createTestConfig({});
config.overlayDatabaseMode =
OverlayDatabaseMode.Overlay as OverlayDatabaseMode;
const logger = getRunnerLogger(true);

const stub = sinon
.stub(actionsUtil, "getDiffRangesJsonFilePath")
.returns("/nonexistent/path/pr-diff-range.json");

try {
revertOverlayModeIfDiffInformedUnavailable(config, true, logger);
t.is(
config.overlayDatabaseMode,
OverlayDatabaseMode.None as OverlayDatabaseMode,
);
} finally {
stub.restore();
}
},
);

test.serial(
"revertOverlayModeIfDiffInformedUnavailable: no-op when diff-informed analysis is not expected",
(t) => {
const config = createTestConfig({});
config.overlayDatabaseMode = OverlayDatabaseMode.Overlay;
const logger = getRunnerLogger(true);

revertOverlayModeIfDiffInformedUnavailable(config, false, logger);
t.is(config.overlayDatabaseMode, OverlayDatabaseMode.Overlay);
},
);
33 changes: 33 additions & 0 deletions src/overlay/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,39 @@ const OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500;
const OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES =
OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB * 1_000_000;

/**
* If overlay analysis is enabled but diff-informed analysis failed to produce
* its output file, reverts the overlay database mode to `None`. Overlay
* without diff-informed is an untested combination that can produce inaccurate
* results, so we fall back to a full non-overlay analysis instead.
*
* @param config The configuration object whose `overlayDatabaseMode` may be mutated.
* @param diffInformedAnalysisExpected Whether diff-informed analysis was expected
* to run for this workflow. When true and the diff ranges file is missing, the
* overlay mode is reverted.
* @param logger The logger instance.
*/
export function revertOverlayModeIfDiffInformedUnavailable(
config: Config,
diffInformedAnalysisExpected: boolean,
logger: Logger,
): void {
if (config.overlayDatabaseMode !== OverlayDatabaseMode.Overlay) {
return;
}

if (
diffInformedAnalysisExpected &&
!fs.existsSync(actionsUtil.getDiffRangesJsonFilePath())
) {
logger.warning(
"Diff-informed analysis is not available for this pull request. " +
`Reverting overlay database mode to ${OverlayDatabaseMode.None}.`,
);
config.overlayDatabaseMode = OverlayDatabaseMode.None;
}
}

/**
* Writes a JSON file containing Git OIDs for all tracked files (represented
* by path relative to the source root) under the source root. The file is
Expand Down
Loading