mirror of
https://github.com/github/codeql-action.git
synced 2026-11-01 18:49:41 +00:00
Compare commits
12 Commits
default-se
...
mbg/macos2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
120993f723 | ||
|
|
f1396bd6e2 | ||
|
|
8d18caadc8 | ||
|
|
410d706e43 | ||
|
|
ce1de8daea | ||
|
|
9410c4a524 | ||
|
|
80d7b74bf4 | ||
|
|
efea0445d3 | ||
|
|
8f2596eca1 | ||
|
|
1fb93080c2 | ||
|
|
be54d791a1 | ||
|
|
4a6767cdd0 |
277
lib/entry-points.js
generated
277
lib/entry-points.js
generated
@@ -28347,7 +28347,7 @@ var require_io = __commonJS({
|
||||
exports2.mv = mv;
|
||||
exports2.rmRF = rmRF;
|
||||
exports2.mkdirP = mkdirP;
|
||||
exports2.which = which9;
|
||||
exports2.which = which10;
|
||||
exports2.findInPath = findInPath;
|
||||
var assert_1 = require("assert");
|
||||
var path30 = __importStar2(require("path"));
|
||||
@@ -28423,13 +28423,13 @@ var require_io = __commonJS({
|
||||
yield ioUtil.mkdir(fsPath, { recursive: true });
|
||||
});
|
||||
}
|
||||
function which9(tool, check) {
|
||||
function which10(tool, check) {
|
||||
return __awaiter2(this, void 0, void 0, function* () {
|
||||
if (!tool) {
|
||||
throw new Error("parameter 'tool' is required");
|
||||
}
|
||||
if (check) {
|
||||
const result = yield which9(tool, false);
|
||||
const result = yield which10(tool, false);
|
||||
if (!result) {
|
||||
if (ioUtil.IS_WINDOWS) {
|
||||
throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`);
|
||||
@@ -28610,11 +28610,11 @@ var require_toolrunner = __commonJS({
|
||||
var events = __importStar2(require("events"));
|
||||
var child = __importStar2(require("child_process"));
|
||||
var path30 = __importStar2(require("path"));
|
||||
var io9 = __importStar2(require_io());
|
||||
var io10 = __importStar2(require_io());
|
||||
var ioUtil = __importStar2(require_io_util());
|
||||
var timers_1 = require("timers");
|
||||
var IS_WINDOWS = process.platform === "win32";
|
||||
var ToolRunner7 = class extends events.EventEmitter {
|
||||
var ToolRunner8 = class extends events.EventEmitter {
|
||||
constructor(toolPath, args, options) {
|
||||
super();
|
||||
if (!toolPath) {
|
||||
@@ -28826,7 +28826,7 @@ var require_toolrunner = __commonJS({
|
||||
if (!ioUtil.isRooted(this.toolPath) && (this.toolPath.includes("/") || IS_WINDOWS && this.toolPath.includes("\\"))) {
|
||||
this.toolPath = path30.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath);
|
||||
}
|
||||
this.toolPath = yield io9.which(this.toolPath, true);
|
||||
this.toolPath = yield io10.which(this.toolPath, true);
|
||||
return new Promise((resolve15, reject) => __awaiter2(this, void 0, void 0, function* () {
|
||||
this._debug(`exec tool: ${this.toolPath}`);
|
||||
this._debug("arguments:");
|
||||
@@ -28923,7 +28923,7 @@ var require_toolrunner = __commonJS({
|
||||
});
|
||||
}
|
||||
};
|
||||
exports2.ToolRunner = ToolRunner7;
|
||||
exports2.ToolRunner = ToolRunner8;
|
||||
function argStringToArray(argString) {
|
||||
const args = [];
|
||||
let inQuotes = false;
|
||||
@@ -42426,7 +42426,7 @@ var require_cacheUtils = __commonJS({
|
||||
var core29 = __importStar2(require_core());
|
||||
var exec3 = __importStar2(require_exec());
|
||||
var glob2 = __importStar2(require_glob());
|
||||
var io9 = __importStar2(require_io());
|
||||
var io10 = __importStar2(require_io());
|
||||
var crypto3 = __importStar2(require("crypto"));
|
||||
var fs34 = __importStar2(require("fs"));
|
||||
var path30 = __importStar2(require("path"));
|
||||
@@ -42452,7 +42452,7 @@ var require_cacheUtils = __commonJS({
|
||||
tempDirectory = path30.join(baseLocation, "actions", "temp");
|
||||
}
|
||||
const dest = path30.join(tempDirectory, crypto3.randomUUID());
|
||||
yield io9.mkdirP(dest);
|
||||
yield io10.mkdirP(dest);
|
||||
return dest;
|
||||
});
|
||||
}
|
||||
@@ -42541,7 +42541,7 @@ var require_cacheUtils = __commonJS({
|
||||
return constants_1.GnuTarPathOnWindows;
|
||||
}
|
||||
const versionOutput = yield getVersion("tar");
|
||||
return versionOutput.toLowerCase().includes("gnu tar") ? io9.which("tar") : "";
|
||||
return versionOutput.toLowerCase().includes("gnu tar") ? io10.which("tar") : "";
|
||||
});
|
||||
}
|
||||
function assertDefined(name, value) {
|
||||
@@ -113305,7 +113305,7 @@ var require_tar = __commonJS({
|
||||
exports2.createTar = createTar;
|
||||
var core29 = __importStar2(require_core());
|
||||
var exec_1 = require_exec();
|
||||
var io9 = __importStar2(require_io());
|
||||
var io10 = __importStar2(require_io());
|
||||
var fs_1 = require("fs");
|
||||
var path30 = __importStar2(require("path"));
|
||||
var utils = __importStar2(require_cacheUtils());
|
||||
@@ -113325,12 +113325,12 @@ var require_tar = __commonJS({
|
||||
break;
|
||||
}
|
||||
case "darwin": {
|
||||
const gnuTar = yield io9.which("gtar", false);
|
||||
const gnuTar = yield io10.which("gtar", false);
|
||||
if (gnuTar) {
|
||||
return { path: gnuTar, type: constants_1.ArchiveToolType.GNU };
|
||||
} else {
|
||||
return {
|
||||
path: yield io9.which("tar", true),
|
||||
path: yield io10.which("tar", true),
|
||||
type: constants_1.ArchiveToolType.BSD
|
||||
};
|
||||
}
|
||||
@@ -113339,7 +113339,7 @@ var require_tar = __commonJS({
|
||||
break;
|
||||
}
|
||||
return {
|
||||
path: yield io9.which("tar", true),
|
||||
path: yield io10.which("tar", true),
|
||||
type: constants_1.ArchiveToolType.GNU
|
||||
};
|
||||
});
|
||||
@@ -113468,7 +113468,7 @@ var require_tar = __commonJS({
|
||||
} finally {
|
||||
if (tempDirectory) {
|
||||
try {
|
||||
yield io9.rmRF(tempDirectory);
|
||||
yield io10.rmRF(tempDirectory);
|
||||
} catch (error3) {
|
||||
core29.debug(`Failed to delete temporary tar directory: ${error3}`);
|
||||
}
|
||||
@@ -113484,7 +113484,7 @@ var require_tar = __commonJS({
|
||||
function extractTar3(archivePath, compressionMethod) {
|
||||
return __awaiter2(this, void 0, void 0, function* () {
|
||||
const workingDirectory = getWorkingDirectory();
|
||||
yield io9.mkdirP(workingDirectory);
|
||||
yield io10.mkdirP(workingDirectory);
|
||||
yield execReadCommands(archivePath, compressionMethod, "extract");
|
||||
});
|
||||
}
|
||||
@@ -114348,7 +114348,7 @@ var require_tool_cache = __commonJS({
|
||||
exports2.isExplicitVersion = isExplicitVersion;
|
||||
exports2.evaluateVersions = evaluateVersions;
|
||||
var core29 = __importStar2(require_core());
|
||||
var io9 = __importStar2(require_io());
|
||||
var io10 = __importStar2(require_io());
|
||||
var crypto3 = __importStar2(require("crypto"));
|
||||
var fs34 = __importStar2(require("fs"));
|
||||
var mm = __importStar2(require_manifest());
|
||||
@@ -114375,7 +114375,7 @@ var require_tool_cache = __commonJS({
|
||||
function downloadTool3(url2, dest, auth2, headers) {
|
||||
return __awaiter2(this, void 0, void 0, function* () {
|
||||
dest = dest || path30.join(_getTempDirectory(), crypto3.randomUUID());
|
||||
yield io9.mkdirP(path30.dirname(dest));
|
||||
yield io10.mkdirP(path30.dirname(dest));
|
||||
core29.debug(`Downloading ${url2}`);
|
||||
core29.debug(`Destination ${dest}`);
|
||||
const maxAttempts = 3;
|
||||
@@ -114428,7 +114428,7 @@ var require_tool_cache = __commonJS({
|
||||
if (!succeeded) {
|
||||
core29.debug("download failed");
|
||||
try {
|
||||
yield io9.rmRF(dest);
|
||||
yield io10.rmRF(dest);
|
||||
} catch (err) {
|
||||
core29.debug(`Failed to delete '${dest}'. ${err.message}`);
|
||||
}
|
||||
@@ -114483,7 +114483,7 @@ var require_tool_cache = __commonJS({
|
||||
silent: true
|
||||
};
|
||||
try {
|
||||
const powershellPath = yield io9.which("powershell", true);
|
||||
const powershellPath = yield io10.which("powershell", true);
|
||||
yield (0, exec_1.exec)(`"${powershellPath}"`, args, options);
|
||||
} finally {
|
||||
process.chdir(originalCwd);
|
||||
@@ -114550,7 +114550,7 @@ var require_tool_cache = __commonJS({
|
||||
if (core29.isDebug()) {
|
||||
args.push("-v");
|
||||
}
|
||||
const xarPath = yield io9.which("xar", true);
|
||||
const xarPath = yield io10.which("xar", true);
|
||||
yield (0, exec_1.exec)(`"${xarPath}"`, _unique(args));
|
||||
return dest;
|
||||
});
|
||||
@@ -114573,7 +114573,7 @@ var require_tool_cache = __commonJS({
|
||||
return __awaiter2(this, void 0, void 0, function* () {
|
||||
const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, "");
|
||||
const escapedDest = dest.replace(/'/g, "''").replace(/"|\n|\r/g, "");
|
||||
const pwshPath = yield io9.which("pwsh", false);
|
||||
const pwshPath = yield io10.which("pwsh", false);
|
||||
if (pwshPath) {
|
||||
const pwshCommand = [
|
||||
`$ErrorActionPreference = 'Stop' ;`,
|
||||
@@ -114609,7 +114609,7 @@ var require_tool_cache = __commonJS({
|
||||
"-Command",
|
||||
powershellCommand
|
||||
];
|
||||
const powershellPath = yield io9.which("powershell", true);
|
||||
const powershellPath = yield io10.which("powershell", true);
|
||||
core29.debug(`Using powershell at path: ${powershellPath}`);
|
||||
yield (0, exec_1.exec)(`"${powershellPath}"`, args);
|
||||
}
|
||||
@@ -114617,7 +114617,7 @@ var require_tool_cache = __commonJS({
|
||||
}
|
||||
function extractZipNix(file, dest) {
|
||||
return __awaiter2(this, void 0, void 0, function* () {
|
||||
const unzipPath = yield io9.which("unzip", true);
|
||||
const unzipPath = yield io10.which("unzip", true);
|
||||
const args = [file];
|
||||
if (!core29.isDebug()) {
|
||||
args.unshift("-q");
|
||||
@@ -114638,7 +114638,7 @@ var require_tool_cache = __commonJS({
|
||||
const destPath = yield _createToolPath(tool, version, arch2);
|
||||
for (const itemName of fs34.readdirSync(sourceDir)) {
|
||||
const s = path30.join(sourceDir, itemName);
|
||||
yield io9.cp(s, destPath, { recursive: true });
|
||||
yield io10.cp(s, destPath, { recursive: true });
|
||||
}
|
||||
_completeToolPath(tool, version, arch2);
|
||||
return destPath;
|
||||
@@ -114656,7 +114656,7 @@ var require_tool_cache = __commonJS({
|
||||
const destFolder = yield _createToolPath(tool, version, arch2);
|
||||
const destPath = path30.join(destFolder, targetFile);
|
||||
core29.debug(`destination file ${destPath}`);
|
||||
yield io9.cp(sourceFile, destPath);
|
||||
yield io10.cp(sourceFile, destPath);
|
||||
_completeToolPath(tool, version, arch2);
|
||||
return destFolder;
|
||||
});
|
||||
@@ -114750,7 +114750,7 @@ var require_tool_cache = __commonJS({
|
||||
if (!dest) {
|
||||
dest = path30.join(_getTempDirectory(), crypto3.randomUUID());
|
||||
}
|
||||
yield io9.mkdirP(dest);
|
||||
yield io10.mkdirP(dest);
|
||||
return dest;
|
||||
});
|
||||
}
|
||||
@@ -114759,9 +114759,9 @@ var require_tool_cache = __commonJS({
|
||||
const folderPath = path30.join(_getCacheDirectory(), tool, semver12.clean(version) || version, arch2 || "");
|
||||
core29.debug(`destination ${folderPath}`);
|
||||
const markerPath = `${folderPath}.complete`;
|
||||
yield io9.rmRF(folderPath);
|
||||
yield io9.rmRF(markerPath);
|
||||
yield io9.mkdirP(folderPath);
|
||||
yield io10.rmRF(folderPath);
|
||||
yield io10.rmRF(markerPath);
|
||||
yield io10.mkdirP(folderPath);
|
||||
return folderPath;
|
||||
});
|
||||
}
|
||||
@@ -152391,13 +152391,13 @@ var require_io2 = __commonJS({
|
||||
});
|
||||
}
|
||||
exports2.mkdirP = mkdirP;
|
||||
function which9(tool, check) {
|
||||
function which10(tool, check) {
|
||||
return __awaiter2(this, void 0, void 0, function* () {
|
||||
if (!tool) {
|
||||
throw new Error("parameter 'tool' is required");
|
||||
}
|
||||
if (check) {
|
||||
const result = yield which9(tool, false);
|
||||
const result = yield which10(tool, false);
|
||||
if (!result) {
|
||||
if (ioUtil.IS_WINDOWS) {
|
||||
throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`);
|
||||
@@ -152414,7 +152414,7 @@ var require_io2 = __commonJS({
|
||||
return "";
|
||||
});
|
||||
}
|
||||
exports2.which = which9;
|
||||
exports2.which = which10;
|
||||
function findInPath(tool) {
|
||||
return __awaiter2(this, void 0, void 0, function* () {
|
||||
if (!tool) {
|
||||
@@ -152565,11 +152565,11 @@ var require_toolrunner2 = __commonJS({
|
||||
var events = __importStar2(require("events"));
|
||||
var child = __importStar2(require("child_process"));
|
||||
var path30 = __importStar2(require("path"));
|
||||
var io9 = __importStar2(require_io2());
|
||||
var io10 = __importStar2(require_io2());
|
||||
var ioUtil = __importStar2(require_io_util2());
|
||||
var timers_1 = require("timers");
|
||||
var IS_WINDOWS = process.platform === "win32";
|
||||
var ToolRunner7 = class extends events.EventEmitter {
|
||||
var ToolRunner8 = class extends events.EventEmitter {
|
||||
constructor(toolPath, args, options) {
|
||||
super();
|
||||
if (!toolPath) {
|
||||
@@ -152781,7 +152781,7 @@ var require_toolrunner2 = __commonJS({
|
||||
if (!ioUtil.isRooted(this.toolPath) && (this.toolPath.includes("/") || IS_WINDOWS && this.toolPath.includes("\\"))) {
|
||||
this.toolPath = path30.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath);
|
||||
}
|
||||
this.toolPath = yield io9.which(this.toolPath, true);
|
||||
this.toolPath = yield io10.which(this.toolPath, true);
|
||||
return new Promise((resolve15, reject) => __awaiter2(this, void 0, void 0, function* () {
|
||||
this._debug(`exec tool: ${this.toolPath}`);
|
||||
this._debug("arguments:");
|
||||
@@ -152878,7 +152878,7 @@ var require_toolrunner2 = __commonJS({
|
||||
});
|
||||
}
|
||||
};
|
||||
exports2.ToolRunner = ToolRunner7;
|
||||
exports2.ToolRunner = ToolRunner8;
|
||||
function argStringToArray(argString) {
|
||||
const args = [];
|
||||
let inQuotes = false;
|
||||
@@ -180446,13 +180446,13 @@ var SarifScanOrder = [
|
||||
var fs19 = __toESM(require("fs"));
|
||||
var path16 = __toESM(require("path"));
|
||||
var import_perf_hooks5 = require("perf_hooks");
|
||||
var io5 = __toESM(require_io());
|
||||
var io6 = __toESM(require_io());
|
||||
|
||||
// src/codeql.ts
|
||||
var fs18 = __toESM(require("fs"));
|
||||
var path15 = __toESM(require("path"));
|
||||
var core12 = __toESM(require_core());
|
||||
var toolrunner3 = __toESM(require_toolrunner());
|
||||
var toolrunner4 = __toESM(require_toolrunner());
|
||||
|
||||
// src/cli-errors.ts
|
||||
var SUPPORTED_PLATFORMS = [
|
||||
@@ -183421,6 +183421,8 @@ var semver7 = __toESM(require_semver2());
|
||||
|
||||
// src/platform.ts
|
||||
var import_fs = __toESM(require("fs"));
|
||||
var toolrunner3 = __toESM(require_toolrunner());
|
||||
var io4 = __toESM(require_io());
|
||||
var semver6 = __toESM(require_semver2());
|
||||
function getBundlePlatform(platform2 = process.platform, arch2 = process.arch) {
|
||||
switch (platform2) {
|
||||
@@ -183448,7 +183450,7 @@ var XCODE_SELECT_LINK_PATH = "/private/var/db/xcode_select_link";
|
||||
var XCODE_APP_FILENAME_PATTERN = new RegExp(
|
||||
/(?<filename>Xcode_(?<majorMinor>\d+(\.\d+)?).*\.app)/
|
||||
);
|
||||
function xcodeVersion(logger2) {
|
||||
function xcodeVersionFromLink(logger2) {
|
||||
try {
|
||||
const xcodePath = import_fs.default.readlinkSync(XCODE_SELECT_LINK_PATH);
|
||||
if (xcodePath.trim() === "") {
|
||||
@@ -183476,6 +183478,111 @@ function xcodeVersion(logger2) {
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
async function xcodeVersionFromXcodeBuild(logger2) {
|
||||
try {
|
||||
const xcrun = await io4.which("xcrun", true);
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
const exitCode = await new toolrunner3.ToolRunner(
|
||||
xcrun,
|
||||
["xcodebuild", "-version"],
|
||||
{
|
||||
silent: true,
|
||||
ignoreReturnCode: true,
|
||||
listeners: {
|
||||
stdout: (data) => {
|
||||
stdout += data.toString("utf-8");
|
||||
},
|
||||
stderr: (data) => {
|
||||
stderr += data.toString("utf-8");
|
||||
}
|
||||
}
|
||||
}
|
||||
).exec();
|
||||
if (exitCode !== 0) {
|
||||
logger2.debug(`xcodebuild returned exit code ${exitCode}`);
|
||||
logger2.debug(`stdout:
|
||||
${stdout}`);
|
||||
logger2.debug(`stderr:
|
||||
${stderr}`);
|
||||
return void 0;
|
||||
}
|
||||
const match2 = stdout.match(/^Xcode (\d+(\.\d+)?)/);
|
||||
if (match2 === null) {
|
||||
logger2.debug(
|
||||
`Output doesn't appear to contain the Xcode product version.`
|
||||
);
|
||||
logger2.debug(`stdout:
|
||||
${stdout}`);
|
||||
logger2.debug(`stderr:
|
||||
${stderr}`);
|
||||
return void 0;
|
||||
}
|
||||
const version = semver6.coerce(match2[1].trim());
|
||||
if (version === null) {
|
||||
logger2.debug(
|
||||
`xcodebuild's output couldn't be parsed as a version:
|
||||
${stdout}`
|
||||
);
|
||||
logger2.debug(`stderr:
|
||||
${stderr}`);
|
||||
return void 0;
|
||||
}
|
||||
return version;
|
||||
} catch (err) {
|
||||
logger2.debug(
|
||||
`Unable to determine Xcode version from xcodebuild: ${getErrorMessage(err)}`
|
||||
);
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
async function xcodeSdkVersion(logger2) {
|
||||
try {
|
||||
const xcrun = await io4.which("xcrun", true);
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
const exitCode = await new toolrunner3.ToolRunner(
|
||||
xcrun,
|
||||
["--sdk", "macosx", "--show-sdk-version"],
|
||||
{
|
||||
silent: true,
|
||||
ignoreReturnCode: true,
|
||||
listeners: {
|
||||
stdout: (data) => {
|
||||
stdout += data.toString("utf-8");
|
||||
},
|
||||
stderr: (data) => {
|
||||
stderr += data.toString("utf-8");
|
||||
}
|
||||
}
|
||||
}
|
||||
).exec();
|
||||
if (exitCode !== 0) {
|
||||
logger2.debug(`xcrun returned exit code ${exitCode}`);
|
||||
logger2.debug(`stdout:
|
||||
${stdout}`);
|
||||
logger2.debug(`stderr:
|
||||
${stderr}`);
|
||||
return void 0;
|
||||
}
|
||||
const version = semver6.coerce(stdout.trim());
|
||||
if (version === null) {
|
||||
logger2.debug(
|
||||
`xcrun's output couldn't be parsed as a version:
|
||||
${stdout}`
|
||||
);
|
||||
logger2.debug(`stderr:
|
||||
${stderr}`);
|
||||
return void 0;
|
||||
}
|
||||
return version;
|
||||
} catch (err) {
|
||||
logger2.debug(
|
||||
`Unable to determine Xcode SDK version: ${getErrorMessage(err)}`
|
||||
);
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
|
||||
// src/per-language-bundles.ts
|
||||
var MIN_PER_LANGUAGE_BUNDLE_CLI_VERSION = "2.27.1";
|
||||
@@ -183659,13 +183766,13 @@ var import_child_process = require("child_process");
|
||||
var fs14 = __toESM(require("fs"));
|
||||
var stream = __toESM(require("stream"));
|
||||
var import_toolrunner = __toESM(require_toolrunner());
|
||||
var io4 = __toESM(require_io());
|
||||
var io5 = __toESM(require_io());
|
||||
var toolcache = __toESM(require_tool_cache());
|
||||
var semver8 = __toESM(require_semver2());
|
||||
var MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3";
|
||||
var MIN_REQUIRED_GNU_TAR_VERSION = "1.31";
|
||||
async function getTarVersion() {
|
||||
const tar = await io4.which("tar", true);
|
||||
const tar = await io5.which("tar", true);
|
||||
let stdout = "";
|
||||
const exitCode = await new import_toolrunner.ToolRunner(tar, ["--version"], {
|
||||
listeners: {
|
||||
@@ -185154,7 +185261,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) {
|
||||
])
|
||||
);
|
||||
}
|
||||
await new toolrunner3.ToolRunner(cmd, args, {
|
||||
await new toolrunner4.ToolRunner(cmd, args, {
|
||||
env: env.getDefined()
|
||||
}).exec();
|
||||
},
|
||||
@@ -185175,7 +185282,7 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) {
|
||||
if (automationDetailsId !== void 0) {
|
||||
args.push("--sarif-category", automationDetailsId);
|
||||
}
|
||||
await new toolrunner3.ToolRunner(cmd, args, {
|
||||
await new toolrunner4.ToolRunner(cmd, args, {
|
||||
env: env.getDefined()
|
||||
}).exec();
|
||||
},
|
||||
@@ -185204,13 +185311,13 @@ async function getCodeQLForCmd(logger2, cmd, checkVersion, env = getEnv()) {
|
||||
if (automationDetailsId !== void 0) {
|
||||
args.push("--sarif-category", automationDetailsId);
|
||||
}
|
||||
await new toolrunner3.ToolRunner(cmd, args, {
|
||||
await new toolrunner4.ToolRunner(cmd, args, {
|
||||
env: env.getDefined()
|
||||
}).exec();
|
||||
},
|
||||
async resolveExtractor(language) {
|
||||
let extractorPath = "";
|
||||
await new toolrunner3.ToolRunner(
|
||||
await new toolrunner4.ToolRunner(
|
||||
cmd,
|
||||
[
|
||||
"resolve",
|
||||
@@ -186153,7 +186260,7 @@ async function runFinalize(features, outputDir, threadsFlag, memoryFlag, codeql,
|
||||
async function warnIfGoInstalledAfterInit(config, logger2) {
|
||||
const goInitPath = process.env["CODEQL_ACTION_GO_BINARY" /* GO_BINARY_LOCATION */];
|
||||
if (process.env["CODEQL_ACTION_DID_AUTOBUILD_GOLANG" /* DID_AUTOBUILD_GOLANG */] !== "true" && goInitPath !== void 0) {
|
||||
const goBinaryPath = await io5.which("go", true);
|
||||
const goBinaryPath = await io6.which("go", true);
|
||||
if (goInitPath !== goBinaryPath) {
|
||||
logger2.warning(
|
||||
`Expected \`which go\` to return ${goInitPath}, but got ${goBinaryPath}: please ensure that the correct version of Go is installed before the \`codeql-action/init\` Action is used.`
|
||||
@@ -187502,9 +187609,9 @@ async function addFingerprints(sarifLog, sourceRoot, logger2) {
|
||||
// src/init.ts
|
||||
var fs22 = __toESM(require("fs"));
|
||||
var path18 = __toESM(require("path"));
|
||||
var toolrunner4 = __toESM(require_toolrunner());
|
||||
var toolrunner5 = __toESM(require_toolrunner());
|
||||
var github3 = __toESM(require_github());
|
||||
var io6 = __toESM(require_io());
|
||||
var io7 = __toESM(require_io());
|
||||
async function initCodeQL(toolsInput, apiDetails, tempDir, variant, defaultCliVersion, rawLanguages, otherLanguagePacksReason, useOverlayAwareDefaultCliVersion, features, logger2) {
|
||||
logger2.startGroup("Setup CodeQL tools");
|
||||
const { codeql, toolsDownloadStatusReport, toolsSource, toolsVersion } = await setupCodeQL(
|
||||
@@ -187617,7 +187724,7 @@ async function checkInstallPython311(languages, codeql) {
|
||||
"../python-setup",
|
||||
"check_python12.ps1"
|
||||
);
|
||||
await new toolrunner4.ToolRunner(await io6.which("powershell", true), [
|
||||
await new toolrunner5.ToolRunner(await io7.which("powershell", true), [
|
||||
script
|
||||
]).exec();
|
||||
}
|
||||
@@ -190345,10 +190452,10 @@ var Minimatch = class {
|
||||
let ai = 0;
|
||||
let bi = 0;
|
||||
let result = [];
|
||||
let which9 = "";
|
||||
let which10 = "";
|
||||
while (ai < a.length && bi < b.length) {
|
||||
if (a[ai] === b[bi]) {
|
||||
result.push(which9 === "b" ? b[bi] : a[ai]);
|
||||
result.push(which10 === "b" ? b[bi] : a[ai]);
|
||||
ai++;
|
||||
bi++;
|
||||
} else if (emptyGSMatch && a[ai] === "**" && b[bi] === a[ai + 1]) {
|
||||
@@ -190358,16 +190465,16 @@ var Minimatch = class {
|
||||
result.push(b[bi]);
|
||||
bi++;
|
||||
} else if (a[ai] === "*" && b[bi] && (this.options.dot || !b[bi].startsWith(".")) && b[bi] !== "**") {
|
||||
if (which9 === "b")
|
||||
if (which10 === "b")
|
||||
return false;
|
||||
which9 = "a";
|
||||
which10 = "a";
|
||||
result.push(a[ai]);
|
||||
ai++;
|
||||
bi++;
|
||||
} else if (b[bi] === "*" && a[ai] && (this.options.dot || !a[ai].startsWith(".")) && a[ai] !== "**") {
|
||||
if (which9 === "a")
|
||||
if (which10 === "a")
|
||||
return false;
|
||||
which9 = "b";
|
||||
which10 = "b";
|
||||
result.push(b[bi]);
|
||||
ai++;
|
||||
bi++;
|
||||
@@ -193856,7 +193963,7 @@ async function runWrapper3() {
|
||||
var fs31 = __toESM(require("fs"));
|
||||
var path25 = __toESM(require("path"));
|
||||
var core19 = __toESM(require_core());
|
||||
var io7 = __toESM(require_io());
|
||||
var io8 = __toESM(require_io());
|
||||
var semver11 = __toESM(require_semver2());
|
||||
|
||||
// src/config/inputs.ts
|
||||
@@ -193911,20 +194018,35 @@ async function checkSwiftCompatibility(config, codeql, darwinVersion2) {
|
||||
// src/languages/traced.ts
|
||||
var UNSUPPORTED_DARWIN_FOR_TRACED = 27;
|
||||
var UNSUPPORTED_XCODE_FOR_TRACED = 27;
|
||||
function handleUnsupportedVersion(logger2, config, tracedLanguages, abortUnsupportedTracedAnalysis, product, version) {
|
||||
const unsupportedVersion = product === "macOS" ? UNSUPPORTED_DARWIN_FOR_TRACED : UNSUPPORTED_XCODE_FOR_TRACED;
|
||||
function diagnosticAttributeName(product) {
|
||||
switch (product) {
|
||||
case "macOS":
|
||||
return "darwinVersion";
|
||||
case "Xcode":
|
||||
return "xcodeVersion";
|
||||
case "Xcode SDK":
|
||||
return "xcodeSdkVersion";
|
||||
}
|
||||
}
|
||||
function handleUnsupportedVersion(logger2, config, tracedLanguages, abortUnsupportedTracedAnalysis, productVersion) {
|
||||
const { product, version } = productVersion;
|
||||
const unsupportedVersion = product === "macOS" ? UNSUPPORTED_DARWIN_FOR_TRACED : (
|
||||
// We use the same constant for both Xcode and the Xcode SDK since we treat them
|
||||
// as equivalent indicators for whether traced analysis is unsupported.
|
||||
UNSUPPORTED_XCODE_FOR_TRACED
|
||||
);
|
||||
const baseMessage = [
|
||||
`Traced analysis is not supported on ${product} ${unsupportedVersion} or above.`,
|
||||
`Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`,
|
||||
`and Xcode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.`
|
||||
].join(" ");
|
||||
const attributeName = product === "macOS" ? "darwinVersion" : "xcodeVersion";
|
||||
const attributeName = diagnosticAttributeName(product);
|
||||
for (const language of tracedLanguages) {
|
||||
addDiagnostic(
|
||||
config,
|
||||
language,
|
||||
makeDiagnostic(
|
||||
`codeql-action/unsupported-traced-analysis-${product.toLowerCase()}`,
|
||||
`codeql-action/unsupported-traced-analysis-${product.toLowerCase().replaceAll(" ", "-")}`,
|
||||
`Traced analysis is not supported on this version of ${product}`,
|
||||
{
|
||||
attributes: {
|
||||
@@ -194005,28 +194127,27 @@ async function checkRunnerSupportsTracedAnalysis(action, config, codeql) {
|
||||
config,
|
||||
tracedLanguages,
|
||||
abortUnsupportedTracedAnalysis,
|
||||
"macOS",
|
||||
version
|
||||
{ product: "macOS", version }
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (isSelfHostedRunner(action.env)) {
|
||||
action.logger.debug(
|
||||
"Skipping traced analysis compatibility check for Xcode because we are on a self-hosted runner."
|
||||
);
|
||||
return;
|
||||
const xcodeVer = xcodeVersionFromLink(action.logger) ?? await xcodeVersionFromXcodeBuild(action.logger);
|
||||
let xcodeProduct = void 0;
|
||||
if (xcodeVer !== void 0) {
|
||||
xcodeProduct = { product: "Xcode", version: xcodeVer };
|
||||
} else {
|
||||
const xcodeSdkVer = await xcodeSdkVersion(action.logger);
|
||||
xcodeProduct = xcodeSdkVer !== void 0 ? { product: "Xcode SDK", version: xcodeSdkVer } : void 0;
|
||||
}
|
||||
const xcodeVer = xcodeVersion(action.logger);
|
||||
if (xcodeVer !== void 0 && xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED) {
|
||||
if (xcodeProduct !== void 0 && xcodeProduct.version.major >= UNSUPPORTED_XCODE_FOR_TRACED) {
|
||||
handleUnsupportedVersion(
|
||||
action.logger,
|
||||
config,
|
||||
tracedLanguages,
|
||||
abortUnsupportedTracedAnalysis,
|
||||
"Xcode",
|
||||
xcodeVer
|
||||
xcodeProduct
|
||||
);
|
||||
} else if (xcodeVer === void 0) {
|
||||
} else if (xcodeProduct === void 0) {
|
||||
action.logger.info(
|
||||
"Unable to determine Xcode version. Skipping Xcode compatibility check."
|
||||
);
|
||||
@@ -194644,7 +194765,7 @@ async function run3(actionState) {
|
||||
}
|
||||
if (config.languages.includes("go" /* go */) && process.platform === "linux") {
|
||||
try {
|
||||
const goBinaryPath = await io7.which("go", true);
|
||||
const goBinaryPath = await io8.which("go", true);
|
||||
const fileOutput = await getFileType(goBinaryPath);
|
||||
if (fileOutput.includes("statically linked") && !await codeql.supportsFeature(
|
||||
"indirectTracingSupportsStaticBinaries" /* IndirectTracingSupportsStaticBinaries */
|
||||
@@ -195999,8 +196120,8 @@ function generateCertificateAuthority() {
|
||||
// src/start-proxy/environment.ts
|
||||
var fs33 = __toESM(require("fs"));
|
||||
var path28 = __toESM(require("path"));
|
||||
var toolrunner5 = __toESM(require_toolrunner());
|
||||
var io8 = __toESM(require_io());
|
||||
var toolrunner6 = __toESM(require_toolrunner());
|
||||
var io9 = __toESM(require_io());
|
||||
function checkEnvVar(logger2, name) {
|
||||
const value = process.env[name];
|
||||
if (isDefined2(value)) {
|
||||
@@ -196090,9 +196211,9 @@ function checkJdkSettings(logger2, jdkHome) {
|
||||
}
|
||||
async function showJavaSettings(logger2) {
|
||||
try {
|
||||
const java = await io8.which("java", true);
|
||||
const java = await io9.which("java", true);
|
||||
let output = "";
|
||||
await new toolrunner5.ToolRunner(
|
||||
await new toolrunner6.ToolRunner(
|
||||
java,
|
||||
["-XshowSettings:all", "-XshowSettings:security:all", "-version"],
|
||||
{
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import fs from "fs";
|
||||
|
||||
import type { ExecOptions } from "@actions/exec";
|
||||
import * as toolrunner from "@actions/exec/lib/toolrunner";
|
||||
import * as io from "@actions/io";
|
||||
import test from "ava";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
@@ -344,38 +347,6 @@ test.serial(
|
||||
}),
|
||||
);
|
||||
|
||||
test("checkRunnerSupportsTracedAnalysis doesn't perform Xcode check on self-hosted runners", async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
env.set(ActionsEnvVars.RUNNER_ENVIRONMENT, "self-hosted");
|
||||
const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]);
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
await checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "26.0.0",
|
||||
env,
|
||||
features,
|
||||
}),
|
||||
createTestConfig({ tempDir: tmpDir, languages: [BuiltInLanguage.go] }),
|
||||
codeql,
|
||||
);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Skipping traced analysis compatibility check for Xcode because we are on a self-hosted runner.",
|
||||
]);
|
||||
}));
|
||||
|
||||
// `addDiagnostic` changes global state and we must stub it, so this test must be serial.
|
||||
test.serial(
|
||||
"checkRunnerSupportsTracedAnalysis doesn't add a diagnostic if Xcode version is supported",
|
||||
@@ -426,6 +397,86 @@ test.serial(
|
||||
}),
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"checkRunnerSupportsTracedAnalysis attempts fallbacks if needed",
|
||||
async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]);
|
||||
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.throws(new Error("Not found"));
|
||||
const which = sinon.stub(io, "which").resolves("/path/to/xcrun");
|
||||
const exec = sinon.stub<[], Promise<number>>().callsFake(async () => {
|
||||
throw new Error("Error to force next fallback");
|
||||
});
|
||||
const runner = sinon.createStubInstance(toolrunner.ToolRunner, { exec });
|
||||
const toolrunnerStub = sinon
|
||||
.stub(toolrunner, "ToolRunner")
|
||||
.callsFake(() => {
|
||||
return runner;
|
||||
});
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic");
|
||||
|
||||
const config = createTestConfig({
|
||||
tempDir: tmpDir,
|
||||
languages: [BuiltInLanguage.swift],
|
||||
});
|
||||
await checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "26.0.0",
|
||||
env,
|
||||
features,
|
||||
}),
|
||||
config,
|
||||
codeql,
|
||||
);
|
||||
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
t.is(which.callCount, 2);
|
||||
t.deepEqual(which.args[0], ["xcrun", true]);
|
||||
t.deepEqual(which.args[1], ["xcrun", true]);
|
||||
|
||||
t.is(toolrunnerStub.callCount, 2);
|
||||
t.is(exec.callCount, 2);
|
||||
|
||||
t.is(toolrunnerStub.args[0][0], "/path/to/xcrun");
|
||||
t.deepEqual(toolrunnerStub.args[0][1], ["xcodebuild", "-version"]);
|
||||
|
||||
t.is(toolrunnerStub.args[1][0], "/path/to/xcrun");
|
||||
t.deepEqual(toolrunnerStub.args[1][1], [
|
||||
"--sdk",
|
||||
"macosx",
|
||||
"--show-sdk-version",
|
||||
]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Unable to determine Xcode version: Not found",
|
||||
"Unable to determine Xcode version from xcodebuild: Error to force next fallback",
|
||||
"Unable to determine Xcode SDK version: Error to force next fallback",
|
||||
]);
|
||||
checkUnexpectedLogMessages(t, logger.messages, [
|
||||
"Traced analysis is not supported on Xcode 27",
|
||||
]);
|
||||
|
||||
t.is(addDiagnostic.callCount, 0);
|
||||
}),
|
||||
);
|
||||
|
||||
// `addDiagnostic` changes global state and we must stub it, so this test must be serial.
|
||||
test.serial(
|
||||
"checkRunnerSupportsTracedAnalysis logs and adds diagnostic if Xcode version is unsupported",
|
||||
@@ -496,6 +547,104 @@ test.serial(
|
||||
}),
|
||||
);
|
||||
|
||||
// `addDiagnostic` changes global state and we must stub it, so this test must be serial.
|
||||
test.serial(
|
||||
"checkRunnerSupportsTracedAnalysis logs and adds diagnostic if Xcode SDK version is unsupported",
|
||||
async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
const features = createFeatures([Feature.CheckUnsupportedTracedAnalysis]);
|
||||
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.throws(new Error("Not found"));
|
||||
const which = sinon.stub(io, "which").resolves("/path/to/xcrun");
|
||||
|
||||
let stdoutListener: ((data: Buffer) => void) | undefined = undefined;
|
||||
const exec = sinon.stub<[], Promise<number>>().callsFake(async () => {
|
||||
if (stdoutListener !== undefined) {
|
||||
stdoutListener(Buffer.from("Xcode 27.5"));
|
||||
stdoutListener(Buffer.from("Build version 27F9"));
|
||||
return 0;
|
||||
} else {
|
||||
throw new Error("Error to force next fallback");
|
||||
}
|
||||
});
|
||||
const runner = sinon.createStubInstance(toolrunner.ToolRunner, {
|
||||
exec,
|
||||
});
|
||||
const toolrunnerStub = sinon
|
||||
.stub(toolrunner, "ToolRunner")
|
||||
.callsFake((_cmd, args: string[], opts: ExecOptions) => {
|
||||
if (args[0] !== "xcodebuild") {
|
||||
stdoutListener = opts.listeners?.stdout;
|
||||
}
|
||||
return runner;
|
||||
});
|
||||
|
||||
const codeql = await getCodeQLWithTracedStub(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic");
|
||||
|
||||
const config = createTestConfig({
|
||||
tempDir: tmpDir,
|
||||
languages: [BuiltInLanguage.swift],
|
||||
});
|
||||
await checkRunnerSupportsTracedAnalysis(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "26.0.0",
|
||||
env,
|
||||
features,
|
||||
}),
|
||||
config,
|
||||
codeql,
|
||||
);
|
||||
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
t.is(which.callCount, 2);
|
||||
t.is(toolrunnerStub.callCount, 2);
|
||||
t.is(exec.callCount, 2);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Unable to determine Xcode version from xcodebuild",
|
||||
"Traced analysis is not supported on Xcode SDK 27",
|
||||
]);
|
||||
|
||||
t.is(addDiagnostic.callCount, 1);
|
||||
t.like(addDiagnostic.args[0], [
|
||||
config,
|
||||
BuiltInLanguage.swift,
|
||||
{
|
||||
attributes: {
|
||||
languages: [BuiltInLanguage.swift],
|
||||
xcodeSdkVersion: "27.5.0",
|
||||
},
|
||||
severity: "warning",
|
||||
source: {
|
||||
id: "codeql-action/unsupported-traced-analysis-xcode-sdk",
|
||||
name: "Traced analysis is not supported on this version of Xcode SDK",
|
||||
},
|
||||
visibility: {
|
||||
cliSummaryTable: true,
|
||||
statusPage: true,
|
||||
telemetry: true,
|
||||
},
|
||||
} satisfies Partial<diagnostics.DiagnosticMessage>,
|
||||
]);
|
||||
}),
|
||||
);
|
||||
|
||||
// `addDiagnostic` changes global state and we must stub it, so this test must be serial.
|
||||
test.serial(
|
||||
"checkRunnerSupportsTracedAnalysis throws if Xcode version is unsupported and FF is enabled",
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import * as semver from "semver";
|
||||
|
||||
import type { ActionState, Logger } from "../action-common";
|
||||
import { isSelfHostedRunner } from "../actions-util";
|
||||
import type { CodeQL } from "../codeql";
|
||||
import type { ActionConfig } from "../config/action-config";
|
||||
import { addDiagnostic, makeDiagnostic } from "../diagnostics";
|
||||
import { DocUrl } from "../doc-url";
|
||||
import { Feature } from "../feature-flags";
|
||||
import { darwinVersion, xcodeVersion } from "../platform";
|
||||
import {
|
||||
darwinVersion,
|
||||
xcodeVersionFromLink,
|
||||
xcodeSdkVersion,
|
||||
xcodeVersionFromXcodeBuild,
|
||||
} from "../platform";
|
||||
import { ConfigurationError } from "../util";
|
||||
|
||||
import { checkSwiftCompatibility } from "./swift";
|
||||
@@ -18,6 +22,27 @@ export const UNSUPPORTED_DARWIN_FOR_TRACED = 27;
|
||||
/** Xcode 27 and above do not support traced extraction. */
|
||||
export const UNSUPPORTED_XCODE_FOR_TRACED = 27;
|
||||
|
||||
/** Names of products that we check the versions of here. */
|
||||
type ProductName = "macOS" | "Xcode" | "Xcode SDK";
|
||||
|
||||
/** A version along with the product it relates to. */
|
||||
type ProductVersion = {
|
||||
product: ProductName;
|
||||
version: semver.SemVer;
|
||||
};
|
||||
|
||||
/** Gets the appropriate attribute name for the diagnostic based on {@link product}. */
|
||||
function diagnosticAttributeName(product: ProductName): string {
|
||||
switch (product) {
|
||||
case "macOS":
|
||||
return "darwinVersion";
|
||||
case "Xcode":
|
||||
return "xcodeVersion";
|
||||
case "Xcode SDK":
|
||||
return "xcodeSdkVersion";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a diagnostic indicating that `version` of `product` is unsupported for traced analysis.
|
||||
* Depending on `skipUnsupportedTracedAnalysis`, this function then either throws a {@link ConfigurationError}
|
||||
@@ -27,28 +52,30 @@ export const UNSUPPORTED_XCODE_FOR_TRACED = 27;
|
||||
* @param config The CodeQL Action configuration.
|
||||
* @param tracedLanguages Traced languages that are configured for analysis.
|
||||
* @param abortUnsupportedTracedAnalysis Whether this is a fatal error.
|
||||
* @param product The product that the version is unsupported of.
|
||||
* @param version The unsupported version.
|
||||
* @param productVersion A description of the product and its version that is unsupported.
|
||||
*/
|
||||
function handleUnsupportedVersion(
|
||||
logger: Logger,
|
||||
config: ActionConfig<"dbLocation" | "tempDir">,
|
||||
tracedLanguages: string[],
|
||||
abortUnsupportedTracedAnalysis: boolean,
|
||||
product: "macOS" | "Xcode",
|
||||
version: semver.SemVer,
|
||||
productVersion: ProductVersion,
|
||||
) {
|
||||
const { product, version } = productVersion;
|
||||
const unsupportedVersion =
|
||||
product === "macOS"
|
||||
? UNSUPPORTED_DARWIN_FOR_TRACED
|
||||
: UNSUPPORTED_XCODE_FOR_TRACED;
|
||||
: // We use the same constant for both Xcode and the Xcode SDK since we treat them
|
||||
// as equivalent indicators for whether traced analysis is unsupported.
|
||||
UNSUPPORTED_XCODE_FOR_TRACED;
|
||||
|
||||
const baseMessage = [
|
||||
`Traced analysis is not supported on ${product} ${unsupportedVersion} or above.`,
|
||||
`Configure your analysis to run on macOS ${UNSUPPORTED_DARWIN_FOR_TRACED - 1} or below`,
|
||||
`and Xcode ${UNSUPPORTED_XCODE_FOR_TRACED - 1} or below.`,
|
||||
].join(" ");
|
||||
|
||||
const attributeName = product === "macOS" ? "darwinVersion" : "xcodeVersion";
|
||||
const attributeName = diagnosticAttributeName(product);
|
||||
|
||||
// Create a diagnostic that will show up on the TSP.
|
||||
for (const language of tracedLanguages) {
|
||||
@@ -56,7 +83,7 @@ function handleUnsupportedVersion(
|
||||
config,
|
||||
language,
|
||||
makeDiagnostic(
|
||||
`codeql-action/unsupported-traced-analysis-${product.toLowerCase()}`,
|
||||
`codeql-action/unsupported-traced-analysis-${product.toLowerCase().replaceAll(" ", "-")}`,
|
||||
`Traced analysis is not supported on this version of ${product}`,
|
||||
{
|
||||
attributes: {
|
||||
@@ -177,8 +204,7 @@ export async function checkRunnerSupportsTracedAnalysis(
|
||||
config,
|
||||
tracedLanguages,
|
||||
abortUnsupportedTracedAnalysis,
|
||||
"macOS",
|
||||
version,
|
||||
{ product: "macOS", version },
|
||||
);
|
||||
|
||||
// Return early so that we don't end up producing more-or-less the same log message/diagnostic
|
||||
@@ -186,32 +212,39 @@ export async function checkRunnerSupportsTracedAnalysis(
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip if we are on a self-hosted runner since the current Xcode version detection
|
||||
// is only validated on hosted runners.
|
||||
if (isSelfHostedRunner(action.env)) {
|
||||
action.logger.debug(
|
||||
"Skipping traced analysis compatibility check for Xcode because we are on a self-hosted runner.",
|
||||
);
|
||||
return;
|
||||
// Determining whether the Xcode version is supported only makes sense on macOS, so we only do it
|
||||
// after determining that we are running on macOS. We first try to obtain the version of Xcode itself
|
||||
// starting with the cheapest approach and then call out to an external program. If neither works, we try
|
||||
// to obtain the version from the SDK instead. Since either Xcode or the SDK at version 27 or above is
|
||||
// incompatible, either is fine as we only check the major version below.
|
||||
const xcodeVer =
|
||||
xcodeVersionFromLink(action.logger) ??
|
||||
(await xcodeVersionFromXcodeBuild(action.logger));
|
||||
let xcodeProduct: ProductVersion | undefined = undefined;
|
||||
|
||||
if (xcodeVer !== undefined) {
|
||||
xcodeProduct = { product: "Xcode", version: xcodeVer };
|
||||
} else {
|
||||
// Fallback to checking the SDK version, which may be available even if a full Xcode installation is not.
|
||||
const xcodeSdkVer = await xcodeSdkVersion(action.logger);
|
||||
xcodeProduct =
|
||||
xcodeSdkVer !== undefined
|
||||
? { product: "Xcode SDK", version: xcodeSdkVer }
|
||||
: undefined;
|
||||
}
|
||||
|
||||
// Determining whether the Xcode version is supported only makes sense on macOS, so we only do it
|
||||
// after determining that we are running on macOS.
|
||||
const xcodeVer = xcodeVersion(action.logger);
|
||||
|
||||
if (
|
||||
xcodeVer !== undefined &&
|
||||
xcodeVer.major >= UNSUPPORTED_XCODE_FOR_TRACED
|
||||
xcodeProduct !== undefined &&
|
||||
xcodeProduct.version.major >= UNSUPPORTED_XCODE_FOR_TRACED
|
||||
) {
|
||||
handleUnsupportedVersion(
|
||||
action.logger,
|
||||
config,
|
||||
tracedLanguages,
|
||||
abortUnsupportedTracedAnalysis,
|
||||
"Xcode",
|
||||
xcodeVer,
|
||||
xcodeProduct,
|
||||
);
|
||||
} else if (xcodeVer === undefined) {
|
||||
} else if (xcodeProduct === undefined) {
|
||||
action.logger.info(
|
||||
"Unable to determine Xcode version. Skipping Xcode compatibility check.",
|
||||
);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import fs from "fs";
|
||||
|
||||
import type { ExecOptions } from "@actions/exec/lib/interfaces";
|
||||
import * as toolrunner from "@actions/exec/lib/toolrunner";
|
||||
import * as io from "@actions/io";
|
||||
import test from "ava";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
@@ -8,7 +11,9 @@ import {
|
||||
getBundlePlatform,
|
||||
darwinVersion,
|
||||
XCODE_SELECT_LINK_PATH,
|
||||
xcodeVersion,
|
||||
xcodeVersionFromLink,
|
||||
xcodeSdkVersion,
|
||||
xcodeVersionFromXcodeBuild,
|
||||
} from "./platform";
|
||||
import {
|
||||
checkExpectedLogMessages,
|
||||
@@ -71,46 +76,52 @@ test("darwinVersion returns semver if parsing succeeds", (t) => {
|
||||
}
|
||||
});
|
||||
|
||||
test.serial("xcodeVersion returns undefined if symlink doesn't exist", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
test.serial(
|
||||
"xcodeVersionFromLink returns undefined if symlink doesn't exist",
|
||||
(t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.throws(new Error("ENOENT: no such file or directory"));
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.throws(new Error("ENOENT: no such file or directory"));
|
||||
|
||||
t.is(xcodeVersion(logger), undefined);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
t.is(xcodeVersionFromLink(logger), undefined);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Unable to determine Xcode version: ENOENT: no such file or directory",
|
||||
]);
|
||||
});
|
||||
|
||||
test.serial("xcodeVersion returns undefined if file is not a symlink", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.throws(new Error("EINVAL: invalid argument"));
|
||||
|
||||
t.is(xcodeVersion(logger), undefined);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Unable to determine Xcode version: EINVAL: invalid argument",
|
||||
]);
|
||||
});
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Unable to determine Xcode version: ENOENT: no such file or directory",
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"xcodeVersion returns undefined if resolving the symlink returns nothing",
|
||||
"xcodeVersionFromLink returns undefined if file is not a symlink",
|
||||
(t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.throws(new Error("EINVAL: invalid argument"));
|
||||
|
||||
t.is(xcodeVersionFromLink(logger), undefined);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Unable to determine Xcode version: EINVAL: invalid argument",
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"xcodeVersionFromLink returns undefined if resolving the symlink returns nothing",
|
||||
(t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const readlinkSync = sinon.stub(fs, "readlinkSync").returns("");
|
||||
|
||||
t.is(xcodeVersion(logger), undefined);
|
||||
t.is(xcodeVersionFromLink(logger), undefined);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
@@ -121,7 +132,7 @@ test.serial(
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"xcodeVersion returns undefined if resolved path doesn't include pattern",
|
||||
"xcodeVersionFromLink returns undefined if resolved path doesn't include pattern",
|
||||
(t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
@@ -129,7 +140,7 @@ test.serial(
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode.app/Contents/Developer");
|
||||
|
||||
t.is(xcodeVersion(logger), undefined);
|
||||
t.is(xcodeVersionFromLink(logger), undefined);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
@@ -139,30 +150,33 @@ test.serial(
|
||||
},
|
||||
);
|
||||
|
||||
test.serial("xcodeVersion returns undefined if match can't be parsed", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
test.serial(
|
||||
"xcodeVersionFromLink returns undefined if match can't be parsed",
|
||||
(t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_00.0.app/Contents/Developer");
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_00.0.app/Contents/Developer");
|
||||
|
||||
t.is(xcodeVersion(logger), undefined);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
t.is(xcodeVersionFromLink(logger), undefined);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Couldn't parse '00.0' as a semantic version.",
|
||||
]);
|
||||
});
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Couldn't parse '00.0' as a semantic version.",
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
test.serial("xcodeVersion returns version from resolved path", (t) => {
|
||||
test.serial("xcodeVersionFromLink returns version from resolved path", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_16.4.app/Contents/Developer");
|
||||
|
||||
const result = xcodeVersion(logger);
|
||||
const result = xcodeVersionFromLink(logger);
|
||||
|
||||
if (t.truthy(result)) {
|
||||
t.is(result.major, 16);
|
||||
@@ -173,26 +187,29 @@ test.serial("xcodeVersion returns version from resolved path", (t) => {
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
});
|
||||
|
||||
test.serial("xcodeVersion returns major version from resolved path", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
test.serial(
|
||||
"xcodeVersionFromLink returns major version from resolved path",
|
||||
(t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_16.app/Contents/Developer");
|
||||
const readlinkSync = sinon
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_16.app/Contents/Developer");
|
||||
|
||||
const result = xcodeVersion(logger);
|
||||
const result = xcodeVersionFromLink(logger);
|
||||
|
||||
if (t.truthy(result)) {
|
||||
t.is(result.major, 16);
|
||||
t.is(result.minor, 0);
|
||||
}
|
||||
if (t.truthy(result)) {
|
||||
t.is(result.major, 16);
|
||||
t.is(result.minor, 0);
|
||||
}
|
||||
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
});
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"xcodeVersion allows more version components in resolved path",
|
||||
"xcodeVersionFromLink allows more version components in resolved path",
|
||||
(t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
@@ -200,7 +217,7 @@ test.serial(
|
||||
.stub(fs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_16.5.9.app/Contents/Developer");
|
||||
|
||||
const result = xcodeVersion(logger);
|
||||
const result = xcodeVersionFromLink(logger);
|
||||
|
||||
if (t.truthy(result)) {
|
||||
t.is(result.major, 16);
|
||||
@@ -211,3 +228,135 @@ test.serial(
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"xcodeVersionFromXcodeBuild returns undefined for non-zero exit code",
|
||||
async (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const which = sinon.stub(io, "which").resolves("/path/to/xcrun");
|
||||
const exec = sinon.stub<[], Promise<number>>().resolves(1);
|
||||
const runner = sinon.createStubInstance(toolrunner.ToolRunner, { exec });
|
||||
const toolrunnerStub = sinon.stub(toolrunner, "ToolRunner").returns(runner);
|
||||
|
||||
await t.notThrowsAsync(async () => {
|
||||
const result = await xcodeVersionFromXcodeBuild(logger);
|
||||
|
||||
t.is(result, undefined);
|
||||
|
||||
t.is(which.callCount, 1);
|
||||
t.deepEqual(which.args[0], ["xcrun", true]);
|
||||
|
||||
t.is(toolrunnerStub.callCount, 1);
|
||||
t.is(exec.callCount, 1);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"xcodebuild returned exit code 1",
|
||||
]);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"xcodeVersionFromXcodeBuild extracts version from xcrun stdout",
|
||||
async (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const which = sinon.stub(io, "which").resolves("/path/to/xcrun");
|
||||
|
||||
let stdoutListener: ((data: Buffer) => void) | undefined = undefined;
|
||||
const exec = sinon.stub<[], Promise<number>>().callsFake(async () => {
|
||||
if (stdoutListener !== undefined) {
|
||||
stdoutListener(Buffer.from("Xcode 26.5"));
|
||||
stdoutListener(Buffer.from("Build version 26F9"));
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
const runner = sinon.createStubInstance(toolrunner.ToolRunner, { exec });
|
||||
|
||||
const toolrunnerStub = sinon
|
||||
.stub(toolrunner, "ToolRunner")
|
||||
.callsFake((_cmd, _args, opts: ExecOptions) => {
|
||||
stdoutListener = opts.listeners?.stdout;
|
||||
return runner;
|
||||
});
|
||||
|
||||
await t.notThrowsAsync(async () => {
|
||||
const result = await xcodeVersionFromXcodeBuild(logger);
|
||||
|
||||
t.not(result, undefined);
|
||||
t.is(result?.major, 26);
|
||||
t.is(result?.minor, 5);
|
||||
|
||||
t.is(which.callCount, 1);
|
||||
t.deepEqual(which.args[0], ["xcrun", true]);
|
||||
|
||||
t.is(toolrunnerStub.callCount, 1);
|
||||
t.is(exec.callCount, 1);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"xcodeSdkVersion returns undefined for non-zero exit code",
|
||||
async (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const which = sinon.stub(io, "which").resolves("/path/to/xcrun");
|
||||
const exec = sinon.stub<[], Promise<number>>().resolves(1);
|
||||
const runner = sinon.createStubInstance(toolrunner.ToolRunner, { exec });
|
||||
const toolrunnerStub = sinon.stub(toolrunner, "ToolRunner").returns(runner);
|
||||
|
||||
await t.notThrowsAsync(async () => {
|
||||
const result = await xcodeSdkVersion(logger);
|
||||
|
||||
t.is(result, undefined);
|
||||
|
||||
t.is(which.callCount, 1);
|
||||
t.deepEqual(which.args[0], ["xcrun", true]);
|
||||
|
||||
t.is(toolrunnerStub.callCount, 1);
|
||||
t.is(exec.callCount, 1);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"xcrun returned exit code 1",
|
||||
]);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial("xcodeSdkVersion extracts version from xcrun stdout", async (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const which = sinon.stub(io, "which").resolves("/path/to/xcrun");
|
||||
|
||||
let stdoutListener: ((data: Buffer) => void) | undefined = undefined;
|
||||
const exec = sinon.stub<[], Promise<number>>().callsFake(async () => {
|
||||
if (stdoutListener !== undefined) {
|
||||
stdoutListener(Buffer.from("26.5"));
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
const runner = sinon.createStubInstance(toolrunner.ToolRunner, { exec });
|
||||
|
||||
const toolrunnerStub = sinon
|
||||
.stub(toolrunner, "ToolRunner")
|
||||
.callsFake((_cmd, _args, opts: ExecOptions) => {
|
||||
stdoutListener = opts.listeners?.stdout;
|
||||
return runner;
|
||||
});
|
||||
|
||||
await t.notThrowsAsync(async () => {
|
||||
const result = await xcodeSdkVersion(logger);
|
||||
|
||||
t.not(result, undefined);
|
||||
t.is(result?.major, 26);
|
||||
t.is(result?.minor, 5);
|
||||
|
||||
t.is(which.callCount, 1);
|
||||
t.deepEqual(which.args[0], ["xcrun", true]);
|
||||
|
||||
t.is(toolrunnerStub.callCount, 1);
|
||||
t.is(exec.callCount, 1);
|
||||
});
|
||||
});
|
||||
|
||||
138
src/platform.ts
138
src/platform.ts
@@ -1,5 +1,7 @@
|
||||
import fs from "fs";
|
||||
|
||||
import * as toolrunner from "@actions/exec/lib/toolrunner";
|
||||
import * as io from "@actions/io";
|
||||
import * as semver from "semver";
|
||||
|
||||
import type { ActionState, Logger } from "./action-common";
|
||||
@@ -68,12 +70,15 @@ export const XCODE_APP_FILENAME_PATTERN = new RegExp(
|
||||
);
|
||||
|
||||
/**
|
||||
* Tries to determine the version of Xcode that is installed.
|
||||
* Tries to determine the version of Xcode that is installed from the resolved symbolic link
|
||||
* at {@link XCODE_SELECT_LINK_PATH}.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @returns The Xcode version or `undefined` if it couldn't be determined.
|
||||
*/
|
||||
export function xcodeVersion(logger: Logger): semver.SemVer | undefined {
|
||||
export function xcodeVersionFromLink(
|
||||
logger: Logger,
|
||||
): semver.SemVer | undefined {
|
||||
try {
|
||||
// Read what the symbolic link points to. This will throw if `XCODE_SELECT_LINK_PATH` does not
|
||||
// exist (`ENOENT`) or is not a symbolic link (`EINVAL`).
|
||||
@@ -109,3 +114,132 @@ export function xcodeVersion(logger: Logger): semver.SemVer | undefined {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to determine the version of Xcode that is installed by running `xcrun xcodebuild -version`.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @returns The Xcode version or `undefined` if it couldn't be determined.
|
||||
*/
|
||||
export async function xcodeVersionFromXcodeBuild(
|
||||
logger: Logger,
|
||||
): Promise<semver.SemVer | undefined> {
|
||||
try {
|
||||
const xcrun = await io.which("xcrun", true);
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
|
||||
const exitCode = await new toolrunner.ToolRunner(
|
||||
xcrun,
|
||||
["xcodebuild", "-version"],
|
||||
{
|
||||
silent: true,
|
||||
ignoreReturnCode: true,
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
stdout += data.toString("utf-8");
|
||||
},
|
||||
stderr: (data: Buffer) => {
|
||||
stderr += data.toString("utf-8");
|
||||
},
|
||||
},
|
||||
},
|
||||
).exec();
|
||||
|
||||
if (exitCode !== 0) {
|
||||
logger.debug(`xcodebuild returned exit code ${exitCode}`);
|
||||
logger.debug(`stdout:\n${stdout}`);
|
||||
logger.debug(`stderr:\n${stderr}`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// The output contains a couple of lines, but we only care about the product version.
|
||||
const match = stdout.match(/^Xcode (\d+(\.\d+)?)/);
|
||||
|
||||
if (match === null) {
|
||||
logger.debug(
|
||||
`Output doesn't appear to contain the Xcode product version.`,
|
||||
);
|
||||
logger.debug(`stdout:\n${stdout}`);
|
||||
logger.debug(`stderr:\n${stderr}`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// We expect the output to only be a version string. Try to parse it into a semver.
|
||||
const version = semver.coerce(match[1].trim());
|
||||
|
||||
if (version === null) {
|
||||
logger.debug(
|
||||
`xcodebuild's output couldn't be parsed as a version:\n${stdout}`,
|
||||
);
|
||||
logger.debug(`stderr:\n${stderr}`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return version;
|
||||
} catch (err) {
|
||||
logger.debug(
|
||||
`Unable to determine Xcode version from xcodebuild: ${getErrorMessage(err)}`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to determine the version of the Xcode SDK that is installed by running
|
||||
* `xcrun --sdk macosx --show-sdk-version`.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @returns The Xcode SDK version or `undefined` if it couldn't be determined.
|
||||
*/
|
||||
export async function xcodeSdkVersion(
|
||||
logger: Logger,
|
||||
): Promise<semver.SemVer | undefined> {
|
||||
try {
|
||||
const xcrun = await io.which("xcrun", true);
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
|
||||
const exitCode = await new toolrunner.ToolRunner(
|
||||
xcrun,
|
||||
["--sdk", "macosx", "--show-sdk-version"],
|
||||
{
|
||||
silent: true,
|
||||
ignoreReturnCode: true,
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
stdout += data.toString("utf-8");
|
||||
},
|
||||
stderr: (data: Buffer) => {
|
||||
stderr += data.toString("utf-8");
|
||||
},
|
||||
},
|
||||
},
|
||||
).exec();
|
||||
|
||||
if (exitCode !== 0) {
|
||||
logger.debug(`xcrun returned exit code ${exitCode}`);
|
||||
logger.debug(`stdout:\n${stdout}`);
|
||||
logger.debug(`stderr:\n${stderr}`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// We expect the output to only be a version string. Try to parse it into a semver.
|
||||
const version = semver.coerce(stdout.trim());
|
||||
|
||||
if (version === null) {
|
||||
logger.debug(
|
||||
`xcrun's output couldn't be parsed as a version:\n${stdout}`,
|
||||
);
|
||||
logger.debug(`stderr:\n${stderr}`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return version;
|
||||
} catch (err) {
|
||||
logger.debug(
|
||||
`Unable to determine Xcode SDK version: ${getErrorMessage(err)}`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user