Add API call for languages if java in input

If a user explicitly includes java in their language inputs, always
make an api call to check for kotlin in the repo.

Also, add some suggestions from code reviews.
This commit is contained in:
Andrew Eisenberg 2022-11-24 11:06:29 -08:00
Родитель ad7ca9bf21
Коммит eb19ecbad1
12 изменённых файлов: 112 добавлений и 92 удалений

5
lib/config-utils.js сгенерированный
Просмотреть файл

@ -19,7 +19,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.downloadPacks = exports.getConfig = exports.getPathToParsedConfigFile = exports.initConfig = exports.parsePacks = exports.validatePackSpecification = exports.prettyPrintPack = exports.parsePacksSpecification = exports.parsePacksFromConfig = exports.calculateAugmentation = exports.getDefaultConfig = exports.getRawLanguages = exports.getLanguages = exports.getUnknownLanguagesError = exports.getNoLanguagesError = exports.getConfigFileDirectoryGivenMessage = exports.getConfigFileFormatInvalidMessage = exports.getConfigFileRepoFormatInvalidMessage = exports.getConfigFileDoesNotExistErrorMessage = exports.getConfigFileOutsideWorkspaceErrorMessage = exports.getLocalPathDoesNotExist = exports.getLocalPathOutsideOfRepository = exports.getPacksStrInvalid = exports.getPacksInvalid = exports.getPacksInvalidSplit = exports.getPathsInvalid = exports.getPathsIgnoreInvalid = exports.getQueryUsesInvalid = exports.getQueriesMissingUses = exports.getQueriesInvalid = exports.getDisableDefaultQueriesInvalid = exports.getNameInvalid = exports.validateAndSanitisePath = exports.defaultAugmentationProperties = void 0;
exports.downloadPacks = exports.getConfig = exports.getPathToParsedConfigFile = exports.initConfig = exports.parsePacks = exports.validatePackSpecification = exports.prettyPrintPack = exports.parsePacksSpecification = exports.parsePacksFromConfig = exports.calculateAugmentation = exports.getDefaultConfig = exports.getRawLanguages = exports.getLanguages = exports.getLanguagesInRepo = exports.getUnknownLanguagesError = exports.getNoLanguagesError = exports.getConfigFileDirectoryGivenMessage = exports.getConfigFileFormatInvalidMessage = exports.getConfigFileRepoFormatInvalidMessage = exports.getConfigFileDoesNotExistErrorMessage = exports.getConfigFileOutsideWorkspaceErrorMessage = exports.getLocalPathDoesNotExist = exports.getLocalPathOutsideOfRepository = exports.getPacksStrInvalid = exports.getPacksInvalid = exports.getPacksInvalidSplit = exports.getPathsInvalid = exports.getPathsIgnoreInvalid = exports.getQueryUsesInvalid = exports.getQueriesMissingUses = exports.getQueriesInvalid = exports.getDisableDefaultQueriesInvalid = exports.getNameInvalid = exports.validateAndSanitisePath = exports.defaultAugmentationProperties = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
// We need to import `performance` on Node 12
@ -408,6 +408,7 @@ async function getLanguagesInRepo(repository, logger) {
}
return [...languages];
}
exports.getLanguagesInRepo = getLanguagesInRepo;
/**
* Get the languages to analyse.
*
@ -448,6 +449,8 @@ async function getLanguages(codeQL, languagesInput, repository, logger) {
parsedLanguages.push(parsedLanguage);
}
}
// Any unknown languages here would have come directly from the input
// since we filter unknown languages coming from the GitHub API.
if (unknownLanguages.length > 0) {
throw new Error(getUnknownLanguagesError(unknownLanguages));
}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

38
lib/config-utils.test.js сгенерированный
Просмотреть файл

@ -934,14 +934,7 @@ function parseInputAndConfigMacro(t, packsFromConfig, packsFromInput, languages,
languages, "/a/b", mockLogger), expected);
}
parseInputAndConfigMacro.title = (providedTitle) => `Parse Packs input and config: ${providedTitle}`;
const mockLogger = {
info: (message) => {
console.log("info:", message);
},
debug: (message) => {
console.log("debug:", message);
},
};
const mockLogger = (0, logging_1.getRunnerLogger)(true);
function parseInputAndConfigErrorMacro(t, packsFromConfig, packsFromInput, languages, packsFromInputOverride, expected) {
t.throws(() => {
configUtils.parsePacks(packsFromConfig, packsFromInput, packsFromInputOverride, languages, "/a/b", mockLogger);
@ -1285,23 +1278,6 @@ const mockRepositoryNwo = (0, repository_1.parseRepositoryNwo)("owner/repo");
expectedLanguages: ["javascript", "csharp", "cpp"],
expectedApiCall: true,
},
].forEach((args) => {
(0, ava_1.default)(`getLanguages: ${args.name}`, async (t) => {
const mockRequest = (0, testing_utils_1.mockLanguagesInRepo)(args.languagesInRepository);
const languages = args.codeqlResolvedLanguages.reduce((acc, lang) => ({
...acc,
[lang]: true,
}), {});
const codeQL = (0, codeql_1.setCodeQL)({
resolveLanguages: () => Promise.resolve(languages),
});
const actualLanguages = await configUtils.getLanguages(codeQL, args.languagesInput, mockRepositoryNwo, mockLogger);
t.deepEqual(actualLanguages.sort(), args.expectedLanguages.sort());
t.deepEqual(mockRequest.called, args.expectedApiCall);
});
});
// eslint-disable-next-line github/array-foreach
[
{
name: "no languages",
codeqlResolvedLanguages: ["javascript", "java", "python"],
@ -1319,7 +1295,7 @@ const mockRepositoryNwo = (0, repository_1.parseRepositoryNwo)("owner/repo");
expectedError: configUtils.getUnknownLanguagesError(["a", "b"]),
},
].forEach((args) => {
(0, ava_1.default)(`getLanguages (error when empty): ${args.name}`, async (t) => {
(0, ava_1.default)(`getLanguages: ${args.name}`, async (t) => {
const mockRequest = (0, testing_utils_1.mockLanguagesInRepo)(args.languagesInRepository);
const languages = args.codeqlResolvedLanguages.reduce((acc, lang) => ({
...acc,
@ -1328,7 +1304,15 @@ const mockRepositoryNwo = (0, repository_1.parseRepositoryNwo)("owner/repo");
const codeQL = (0, codeql_1.setCodeQL)({
resolveLanguages: () => Promise.resolve(languages),
});
await t.throwsAsync(async () => await configUtils.getLanguages(codeQL, args.languagesInput, mockRepositoryNwo, mockLogger), { message: args.expectedError });
if (args.expectedLanguages) {
// happy path
const actualLanguages = await configUtils.getLanguages(codeQL, args.languagesInput, mockRepositoryNwo, mockLogger);
t.deepEqual(actualLanguages.sort(), args.expectedLanguages.sort());
}
else {
// there is an error
await t.throwsAsync(async () => await configUtils.getLanguages(codeQL, args.languagesInput, mockRepositoryNwo, mockLogger), { message: args.expectedError });
}
t.deepEqual(mockRequest.called, args.expectedApiCall);
});
});

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

17
lib/util.js сгенерированный
Просмотреть файл

@ -728,17 +728,26 @@ async function shouldBypassToolcache(featuresEnablement, codeqlUrl, languagesInp
if (await featuresEnablement.getValue(feature_flags_1.Feature.BypassToolcacheEnabled)) {
return true;
}
let bypass = false;
// Check if the toolcache is disabled for kotlin and swift.
if (await featuresEnablement.getValue(feature_flags_1.Feature.BypassToolcacheKotlinSwiftEnabled)) {
// Now check to see if kotlin or swift is one of the languages being analyzed.
const { rawLanguages } = await (0, config_utils_1.getRawLanguages)(languagesInput, repository, logger);
const bypass = rawLanguages.some((lang) => languages_1.KOTLIN_SWIFT_BYPASS.includes(lang));
const { rawLanguages, autodetected } = await (0, config_utils_1.getRawLanguages)(languagesInput, repository, logger);
bypass = rawLanguages.some((lang) => languages_1.KOTLIN_SWIFT_BYPASS.includes(lang));
if (bypass) {
logger.info(`Bypassing toolcache for kotlin or swift. Languages: ${rawLanguages}`);
}
return bypass;
else if (!autodetected && rawLanguages.includes(languages_1.Language.java)) {
// special case: java was explicitly specified, but there might be
// some kotlin in the repository, so we need to make a request for that.
const langsInRepo = await (0, config_utils_1.getLanguagesInRepo)(repository, logger);
if (langsInRepo.includes("kotlin")) {
logger.info(`Bypassing toolcache for kotlin.`);
bypass = true;
}
}
}
return false;
return bypass;
}
exports.shouldBypassToolcache = shouldBypassToolcache;
//# sourceMappingURL=util.js.map

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

20
lib/util.test.js сгенерированный
Просмотреть файл

@ -449,10 +449,28 @@ const mockRepositoryNwo = (0, repository_1.parseRepositoryNwo)("owner/repo");
expected: true,
expectedApiCall: true,
},
{
name: "bypass java from input if there is kotlin in repository",
features: [feature_flags_1.Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "java",
languagesInRepository: ["kotlin", "other"],
expected: true,
expectedApiCall: true,
},
{
name: "don't bypass java from input if there is no kotlin in repository",
features: [feature_flags_1.Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "java",
languagesInRepository: ["java", "other"],
expected: false,
expectedApiCall: true,
},
].forEach((args) => {
(0, ava_1.default)(`shouldBypassToolcache: ${args.name}`, async (t) => {
const mockRequest = (0, testing_utils_1.mockLanguagesInRepo)(args.languagesInRepository);
const mockLogger = (0, testing_utils_1.getRecordingLogger)([]);
const mockLogger = (0, logging_1.getRunnerLogger)(true);
const featureEnablement = (0, testing_utils_1.createFeatures)(args.features);
const codeqlUrl = args.hasCustomCodeQL ? "custom-codeql-url" : undefined;
const actual = await util.shouldBypassToolcache(featureEnablement, codeqlUrl, args.languagesInput, mockRepositoryNwo, mockLogger);

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -1764,14 +1764,7 @@ function parseInputAndConfigMacro(
parseInputAndConfigMacro.title = (providedTitle: string) =>
`Parse Packs input and config: ${providedTitle}`;
const mockLogger = {
info: (message: string) => {
console.log("info:", message);
},
debug: (message: string) => {
console.log("debug:", message);
},
} as Logger;
const mockLogger = getRunnerLogger(true);
function parseInputAndConfigErrorMacro(
t: ExecutionContext<unknown>,
@ -2503,33 +2496,6 @@ const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
expectedLanguages: ["javascript", "csharp", "cpp"],
expectedApiCall: true,
},
].forEach((args) => {
test(`getLanguages: ${args.name}`, async (t) => {
const mockRequest = mockLanguagesInRepo(args.languagesInRepository);
const languages = args.codeqlResolvedLanguages.reduce(
(acc, lang) => ({
...acc,
[lang]: true,
}),
{}
);
const codeQL = setCodeQL({
resolveLanguages: () => Promise.resolve(languages),
});
const actualLanguages = await configUtils.getLanguages(
codeQL,
args.languagesInput,
mockRepositoryNwo,
mockLogger
);
t.deepEqual(actualLanguages.sort(), args.expectedLanguages.sort());
t.deepEqual(mockRequest.called, args.expectedApiCall);
});
});
// eslint-disable-next-line github/array-foreach
[
{
name: "no languages",
codeqlResolvedLanguages: ["javascript", "java", "python"],
@ -2547,7 +2513,7 @@ const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
expectedError: configUtils.getUnknownLanguagesError(["a", "b"]),
},
].forEach((args) => {
test(`getLanguages (error when empty): ${args.name}`, async (t) => {
test(`getLanguages: ${args.name}`, async (t) => {
const mockRequest = mockLanguagesInRepo(args.languagesInRepository);
const languages = args.codeqlResolvedLanguages.reduce(
(acc, lang) => ({
@ -2560,16 +2526,29 @@ const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
resolveLanguages: () => Promise.resolve(languages),
});
await t.throwsAsync(
async () =>
await configUtils.getLanguages(
codeQL,
args.languagesInput,
mockRepositoryNwo,
mockLogger
),
{ message: args.expectedError }
);
if (args.expectedLanguages) {
// happy path
const actualLanguages = await configUtils.getLanguages(
codeQL,
args.languagesInput,
mockRepositoryNwo,
mockLogger
);
t.deepEqual(actualLanguages.sort(), args.expectedLanguages.sort());
} else {
// there is an error
await t.throwsAsync(
async () =>
await configUtils.getLanguages(
codeQL,
args.languagesInput,
mockRepositoryNwo,
mockLogger
),
{ message: args.expectedError }
);
}
t.deepEqual(mockRequest.called, args.expectedApiCall);
});
});

Просмотреть файл

@ -860,7 +860,7 @@ export function getUnknownLanguagesError(languages: string[]): string {
* Gets the set of languages in the current repository that are
* scannable by CodeQL.
*/
async function getLanguagesInRepo(
export async function getLanguagesInRepo(
repository: RepositoryNwo,
logger: Logger
): Promise<LanguageOrAlias[]> {
@ -937,6 +937,9 @@ export async function getLanguages(
parsedLanguages.push(parsedLanguage);
}
}
// Any unknown languages here would have come directly from the input
// since we filter unknown languages coming from the GitHub API.
if (unknownLanguages.length > 0) {
throw new Error(getUnknownLanguagesError(unknownLanguages));
}

Просмотреть файл

@ -14,7 +14,6 @@ import { getRunnerLogger } from "./logging";
import { parseRepositoryNwo } from "./repository";
import {
createFeatures,
getRecordingLogger,
mockLanguagesInRepo,
setupTests,
} from "./testing-utils";
@ -541,10 +540,28 @@ const mockRepositoryNwo = parseRepositoryNwo("owner/repo");
expected: true,
expectedApiCall: true,
},
{
name: "bypass java from input if there is kotlin in repository",
features: [Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "java",
languagesInRepository: ["kotlin", "other"],
expected: true,
expectedApiCall: true,
},
{
name: "don't bypass java from input if there is no kotlin in repository",
features: [Feature.BypassToolcacheKotlinSwiftEnabled],
hasCustomCodeQL: false,
languagesInput: "java",
languagesInRepository: ["java", "other"],
expected: false,
expectedApiCall: true,
},
].forEach((args) => {
test(`shouldBypassToolcache: ${args.name}`, async (t) => {
const mockRequest = mockLanguagesInRepo(args.languagesInRepository);
const mockLogger = getRecordingLogger([]);
const mockLogger = getRunnerLogger(true);
const featureEnablement = createFeatures(args.features);
const codeqlUrl = args.hasCustomCodeQL ? "custom-codeql-url" : undefined;
const actual = await util.shouldBypassToolcache(

Просмотреть файл

@ -14,6 +14,7 @@ import * as apiCompatibility from "./api-compatibility.json";
import { CodeQL, CODEQL_VERSION_NEW_TRACING } from "./codeql";
import {
Config,
getLanguagesInRepo,
getRawLanguages,
parsePacksSpecification,
prettyPrintPack,
@ -860,25 +861,31 @@ export async function shouldBypassToolcache(
return true;
}
let bypass = false;
// Check if the toolcache is disabled for kotlin and swift.
if (
await featuresEnablement.getValue(Feature.BypassToolcacheKotlinSwiftEnabled)
) {
// Now check to see if kotlin or swift is one of the languages being analyzed.
const { rawLanguages } = await getRawLanguages(
const { rawLanguages, autodetected } = await getRawLanguages(
languagesInput,
repository,
logger
);
const bypass = rawLanguages.some((lang) =>
KOTLIN_SWIFT_BYPASS.includes(lang)
);
bypass = rawLanguages.some((lang) => KOTLIN_SWIFT_BYPASS.includes(lang));
if (bypass) {
logger.info(
`Bypassing toolcache for kotlin or swift. Languages: ${rawLanguages}`
);
} else if (!autodetected && rawLanguages.includes(Language.java)) {
// special case: java was explicitly specified, but there might be
// some kotlin in the repository, so we need to make a request for that.
const langsInRepo = await getLanguagesInRepo(repository, logger);
if (langsInRepo.includes("kotlin")) {
logger.info(`Bypassing toolcache for kotlin.`);
bypass = true;
}
}
return bypass;
}
return false;
return bypass;
}