mirror of
https://github.com/github/codeql-action.git
synced 2026-10-21 02:01:27 +00:00
Check if Xcode version is unsupported
This commit is contained in:
126
lib/entry-points.js
generated
126
lib/entry-points.js
generated
@@ -186034,11 +186034,83 @@ async function getToolsInput(action, repositoryProperties) {
|
||||
|
||||
// src/languages/swift.ts
|
||||
var semver12 = __toESM(require_semver2());
|
||||
var XCODE_SELECT_LINK_PATH = "/private/var/db/xcode_select_link";
|
||||
var XCODE_APP_FILENAME_PATTERN = new RegExp(
|
||||
/(?<filename>Xcode_(?<majorMinor>\d+.\d+).app)/
|
||||
);
|
||||
var SWIFT_TRACED_UNSUPPORTED_MACOS = 27;
|
||||
var SWIFT_TRACED_UNSUPPORTED_XCODE = 27;
|
||||
function xcodeVersion(logger2, fs33) {
|
||||
try {
|
||||
const stats = fs33.statSync(XCODE_SELECT_LINK_PATH);
|
||||
if (!stats.isSymbolicLink()) {
|
||||
logger2.warning(
|
||||
`${XCODE_SELECT_LINK_PATH} exists, but is not a symbolic link.`
|
||||
);
|
||||
return void 0;
|
||||
}
|
||||
const xcodePath = fs33.readlinkSync(XCODE_SELECT_LINK_PATH);
|
||||
if (xcodePath === "") {
|
||||
logger2.warning(
|
||||
`Resolving ${XCODE_SELECT_LINK_PATH} unexpectedly returned nothing.`
|
||||
);
|
||||
return void 0;
|
||||
}
|
||||
const matchResult = xcodePath.match(XCODE_APP_FILENAME_PATTERN);
|
||||
if (matchResult?.groups === void 0) {
|
||||
logger2.warning(
|
||||
`Xcode path '${xcodePath}' does not contain expected pattern.`
|
||||
);
|
||||
return void 0;
|
||||
}
|
||||
const majorMinor = matchResult.groups["majorMinor"];
|
||||
const version = semver12.coerce(majorMinor);
|
||||
if (version === null) {
|
||||
logger2.warning(`Couldn't parse '${majorMinor}' as a semantic version.`);
|
||||
return void 0;
|
||||
}
|
||||
return version;
|
||||
} catch (err) {
|
||||
logger2.warning(
|
||||
`Unable to determine Xcode version: ${getErrorMessage(err)}`
|
||||
);
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
function handleUnsupportedVersion(logger2, config, skipUnsupportedTracedAnalysis, product, version) {
|
||||
const baseMessage = [
|
||||
`Traced Swift analysis is not supported on ${product} ${SWIFT_TRACED_UNSUPPORTED_MACOS} or above.`,
|
||||
`Configure your analysis to run on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS - 1} or below`,
|
||||
`and XCode ${SWIFT_TRACED_UNSUPPORTED_XCODE - 1} or below.`
|
||||
].join(" ");
|
||||
const attributeName = product === "macOS" ? "macOSVersion" : "xcodeVersion";
|
||||
addDiagnostic(
|
||||
config,
|
||||
"swift" /* swift */,
|
||||
makeDiagnostic(
|
||||
`codeql-action/unsupported-traced-swift-analysis-${product.toLowerCase()}`,
|
||||
`Traced Swift analysis is not supported on this version of ${product}`,
|
||||
{
|
||||
attributes: {
|
||||
languages: config.languages,
|
||||
[attributeName]: version.toString()
|
||||
},
|
||||
markdownMessage: baseMessage,
|
||||
severity: skipUnsupportedTracedAnalysis ? "error" : "warning",
|
||||
visibility: {
|
||||
cliSummaryTable: true,
|
||||
statusPage: true,
|
||||
telemetry: true
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
if (skipUnsupportedTracedAnalysis) {
|
||||
throw new ConfigurationError(baseMessage);
|
||||
} else {
|
||||
logger2.warning(baseMessage);
|
||||
}
|
||||
}
|
||||
async function isSwiftCompatible(action, config, codeql) {
|
||||
if (!config.languages.includes("swift" /* swift */)) {
|
||||
return;
|
||||
@@ -186052,47 +186124,31 @@ async function isSwiftCompatible(action, config, codeql) {
|
||||
`Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.`
|
||||
);
|
||||
}
|
||||
const skipUnsupportedTracedAnalysis = await action.features.getValue(
|
||||
"swift_skip_unsupported_traced_analysis" /* SwiftSkipUnsupportedTracedAnalysis */
|
||||
);
|
||||
if (typeof version === "string") {
|
||||
action.logger.warning(
|
||||
`Unable to determine version of macOS, got: ${version}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
const skipUnsupportedTracedAnalysis = await action.features.getValue(
|
||||
"swift_skip_unsupported_traced_analysis" /* SwiftSkipUnsupportedTracedAnalysis */
|
||||
);
|
||||
if (version.major >= SWIFT_TRACED_UNSUPPORTED_MACOS) {
|
||||
const baseMessage = [
|
||||
`Traced Swift analysis is not supported on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS} or above.`,
|
||||
`Configure your analysis to run on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS - 1} or below`,
|
||||
`and XCode ${SWIFT_TRACED_UNSUPPORTED_XCODE - 1} or below.`
|
||||
].join(" ");
|
||||
addDiagnostic(
|
||||
} else if (version.major >= SWIFT_TRACED_UNSUPPORTED_MACOS) {
|
||||
handleUnsupportedVersion(
|
||||
action.logger,
|
||||
config,
|
||||
"swift" /* swift */,
|
||||
makeDiagnostic(
|
||||
"codeql-action/unsupported-traced-swift-analysis-macos",
|
||||
"Traced Swift analysis is not supported on this version of macOS",
|
||||
{
|
||||
attributes: {
|
||||
languages: config.languages,
|
||||
macOSVersion: version.toString()
|
||||
},
|
||||
markdownMessage: baseMessage,
|
||||
severity: skipUnsupportedTracedAnalysis ? "error" : "warning",
|
||||
visibility: {
|
||||
cliSummaryTable: true,
|
||||
statusPage: true,
|
||||
telemetry: true
|
||||
}
|
||||
}
|
||||
)
|
||||
skipUnsupportedTracedAnalysis,
|
||||
"macOS",
|
||||
version
|
||||
);
|
||||
}
|
||||
const xcodeVer = xcodeVersion(action.logger, action.fs);
|
||||
if (xcodeVer !== void 0 && xcodeVer.major >= SWIFT_TRACED_UNSUPPORTED_XCODE) {
|
||||
handleUnsupportedVersion(
|
||||
action.logger,
|
||||
config,
|
||||
skipUnsupportedTracedAnalysis,
|
||||
"Xcode",
|
||||
xcodeVer
|
||||
);
|
||||
if (skipUnsupportedTracedAnalysis) {
|
||||
throw new ConfigurationError(baseMessage);
|
||||
} else {
|
||||
action.logger.warning(baseMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import { Feature } from "../feature-flags";
|
||||
import { FileSystem } from "../fs";
|
||||
import {
|
||||
checkExpectedLogMessages,
|
||||
checkUnexpectedLogMessages,
|
||||
createFeatures,
|
||||
createTestConfig,
|
||||
getTestEnv,
|
||||
@@ -33,16 +34,41 @@ setupTests(test);
|
||||
|
||||
type RequiredFS = FileSystem<"statSync" | "readlinkSync">;
|
||||
|
||||
test("xcodeVersion returns undefined if symlink doesn't exist", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
/**
|
||||
* Sets up a suitable mock `FileSystem` for use with `xcodeVersion`.
|
||||
*
|
||||
* @param statSyncResult The result of `statSync`.
|
||||
* @param readlinkSyncResult The result of `readlinkSync`.
|
||||
*
|
||||
* @returns The mocked `FileSystem` and stubs.
|
||||
*/
|
||||
function mockFs(
|
||||
statSyncResult: boolean | Error,
|
||||
readlinkSyncResult: string = "",
|
||||
) {
|
||||
const stubbedFs: RequiredFS = {
|
||||
statSync: fs.statSync,
|
||||
readlinkSync: fs.readlinkSync,
|
||||
};
|
||||
const statSync = sinon
|
||||
.stub(stubbedFs, "statSync")
|
||||
.throws(new Error("ENOENT"));
|
||||
const statSync = sinon.stub(stubbedFs, "statSync");
|
||||
|
||||
if (typeof statSyncResult === "boolean") {
|
||||
statSync.returns({ isSymbolicLink: () => statSyncResult } as fs.Stats);
|
||||
} else {
|
||||
statSync.throws(new Error("ENOENT"));
|
||||
}
|
||||
|
||||
const readlinkSync = sinon
|
||||
.stub(stubbedFs, "readlinkSync")
|
||||
.returns(readlinkSyncResult);
|
||||
|
||||
return { stubbedFs, statSync, readlinkSync };
|
||||
}
|
||||
|
||||
test("xcodeVersion returns undefined if symlink doesn't exist", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const { stubbedFs, statSync } = mockFs(new Error("ENOENT"));
|
||||
|
||||
t.is(xcodeVersion(logger, stubbedFs), undefined);
|
||||
t.is(statSync.callCount, 1);
|
||||
@@ -56,13 +82,7 @@ test("xcodeVersion returns undefined if symlink doesn't exist", (t) => {
|
||||
test("xcodeVersion returns undefined if file is not a symlink", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const stubbedFs: RequiredFS = {
|
||||
statSync: fs.statSync,
|
||||
readlinkSync: fs.readlinkSync,
|
||||
};
|
||||
const statSync = sinon
|
||||
.stub(stubbedFs, "statSync")
|
||||
.returns({ isSymbolicLink: () => false } as fs.Stats);
|
||||
const { stubbedFs, statSync } = mockFs(false);
|
||||
|
||||
t.is(xcodeVersion(logger, stubbedFs), undefined);
|
||||
t.is(statSync.callCount, 1);
|
||||
@@ -76,14 +96,7 @@ test("xcodeVersion returns undefined if file is not a symlink", (t) => {
|
||||
test("xcodeVersion returns undefined if resolving the symlink returns nothing", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const stubbedFs: RequiredFS = {
|
||||
statSync: fs.statSync,
|
||||
readlinkSync: fs.readlinkSync,
|
||||
};
|
||||
const statSync = sinon
|
||||
.stub(stubbedFs, "statSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon.stub(stubbedFs, "readlinkSync").returns("");
|
||||
const { stubbedFs, statSync, readlinkSync } = mockFs(true);
|
||||
|
||||
t.is(xcodeVersion(logger, stubbedFs), undefined);
|
||||
t.is(statSync.callCount, 1);
|
||||
@@ -99,16 +112,10 @@ test("xcodeVersion returns undefined if resolving the symlink returns nothing",
|
||||
test("xcodeVersion returns undefined if resolved path doesn't include pattern", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const stubbedFs: RequiredFS = {
|
||||
statSync: fs.statSync,
|
||||
readlinkSync: fs.readlinkSync,
|
||||
};
|
||||
const statSync = sinon
|
||||
.stub(stubbedFs, "statSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon
|
||||
.stub(stubbedFs, "readlinkSync")
|
||||
.returns("/Applications/Xcode.app/Contents/Developer");
|
||||
const { stubbedFs, statSync, readlinkSync } = mockFs(
|
||||
true,
|
||||
"/Applications/Xcode.app/Contents/Developer",
|
||||
);
|
||||
|
||||
t.is(xcodeVersion(logger, stubbedFs), undefined);
|
||||
t.is(statSync.callCount, 1);
|
||||
@@ -124,16 +131,10 @@ test("xcodeVersion returns undefined if resolved path doesn't include pattern",
|
||||
test("xcodeVersion returns undefined if match can't be parsed", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const stubbedFs: RequiredFS = {
|
||||
statSync: fs.statSync,
|
||||
readlinkSync: fs.readlinkSync,
|
||||
};
|
||||
const statSync = sinon
|
||||
.stub(stubbedFs, "statSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon
|
||||
.stub(stubbedFs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_00.0.app/Contents/Developer");
|
||||
const { stubbedFs, statSync, readlinkSync } = mockFs(
|
||||
true,
|
||||
"/Applications/Xcode_00.0.app/Contents/Developer",
|
||||
);
|
||||
|
||||
t.is(xcodeVersion(logger, stubbedFs), undefined);
|
||||
t.is(statSync.callCount, 1);
|
||||
@@ -149,16 +150,10 @@ test("xcodeVersion returns undefined if match can't be parsed", (t) => {
|
||||
test("xcodeVersion returns version from resolved path", (t) => {
|
||||
const logger = new RecordingLogger();
|
||||
|
||||
const stubbedFs: RequiredFS = {
|
||||
statSync: fs.statSync,
|
||||
readlinkSync: fs.readlinkSync,
|
||||
};
|
||||
const statSync = sinon
|
||||
.stub(stubbedFs, "statSync")
|
||||
.returns({ isSymbolicLink: () => true } as fs.Stats);
|
||||
const readlinkSync = sinon
|
||||
.stub(stubbedFs, "readlinkSync")
|
||||
.returns("/Applications/Xcode_16.4.app/Contents/Developer");
|
||||
const { stubbedFs, statSync, readlinkSync } = mockFs(
|
||||
true,
|
||||
"/Applications/Xcode_16.4.app/Contents/Developer",
|
||||
);
|
||||
|
||||
const result = xcodeVersion(logger, stubbedFs);
|
||||
|
||||
@@ -402,3 +397,193 @@ test.serial(
|
||||
]);
|
||||
}),
|
||||
);
|
||||
|
||||
// `addDiagnostic` changes global state and we must stub it, so this test must be serial.
|
||||
test.serial(
|
||||
"isSwiftCompatible doesn't add a diagnostic if Xcode version is supported",
|
||||
async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
|
||||
const { stubbedFs, statSync, readlinkSync } = mockFs(
|
||||
true,
|
||||
"/Applications/Xcode_26.0.app/Contents/Developer",
|
||||
);
|
||||
|
||||
const codeql = await getCodeQLForTesting(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic");
|
||||
|
||||
const config = createTestConfig({ languages: [BuiltInLanguage.swift] });
|
||||
await isSwiftCompatible(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "26.0.0",
|
||||
env,
|
||||
fs: stubbedFs as FileSystem,
|
||||
}),
|
||||
config,
|
||||
codeql,
|
||||
);
|
||||
|
||||
t.is(statSync.callCount, 1);
|
||||
t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
checkUnexpectedLogMessages(t, logger.messages, [
|
||||
"Traced Swift 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(
|
||||
"isSwiftCompatible logs and adds diagnostic if Xcode version is unsupported",
|
||||
async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
|
||||
const { stubbedFs, statSync, readlinkSync } = mockFs(
|
||||
true,
|
||||
"/Applications/Xcode_27.0.app/Contents/Developer",
|
||||
);
|
||||
|
||||
const codeql = await getCodeQLForTesting(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic");
|
||||
|
||||
const config = createTestConfig({ languages: [BuiltInLanguage.swift] });
|
||||
await isSwiftCompatible(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "26.0.0",
|
||||
env,
|
||||
fs: stubbedFs as FileSystem,
|
||||
}),
|
||||
config,
|
||||
codeql,
|
||||
);
|
||||
|
||||
t.is(statSync.callCount, 1);
|
||||
t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
checkExpectedLogMessages(t, logger.messages, [
|
||||
"Traced Swift analysis is not supported on Xcode 27",
|
||||
]);
|
||||
|
||||
t.is(addDiagnostic.callCount, 1);
|
||||
t.like(addDiagnostic.args[0], [
|
||||
config,
|
||||
BuiltInLanguage.swift,
|
||||
{
|
||||
attributes: {
|
||||
languages: [BuiltInLanguage.swift],
|
||||
xcodeVersion: "27.0.0",
|
||||
},
|
||||
severity: "warning",
|
||||
source: {
|
||||
id: "codeql-action/unsupported-traced-swift-analysis-xcode",
|
||||
name: "Traced Swift analysis is not supported on this version of Xcode",
|
||||
},
|
||||
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(
|
||||
"isSwiftCompatible throws if Xcode version is unsupported and FF is enabled",
|
||||
async (t) =>
|
||||
withTmpDir(async (tmpDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const env = getTestEnv();
|
||||
env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir);
|
||||
|
||||
const { stubbedFs, statSync, readlinkSync } = mockFs(
|
||||
true,
|
||||
"/Applications/Xcode_27.0.app/Contents/Developer",
|
||||
);
|
||||
|
||||
const features = createFeatures([
|
||||
Feature.SwiftSkipUnsupportedTracedAnalysis,
|
||||
]);
|
||||
|
||||
const codeql = await getCodeQLForTesting(
|
||||
"codeql-for-testing",
|
||||
logger,
|
||||
env,
|
||||
);
|
||||
sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0"));
|
||||
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addDiagnostic");
|
||||
|
||||
const config = createTestConfig({ languages: [BuiltInLanguage.swift] });
|
||||
await t.throwsAsync(
|
||||
isSwiftCompatible(
|
||||
initAllState({
|
||||
logger,
|
||||
platform: "darwin",
|
||||
osRelease: "26.0.0",
|
||||
env,
|
||||
features,
|
||||
fs: stubbedFs as FileSystem,
|
||||
}),
|
||||
config,
|
||||
codeql,
|
||||
),
|
||||
);
|
||||
|
||||
t.is(statSync.callCount, 1);
|
||||
t.deepEqual(statSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
t.is(readlinkSync.callCount, 1);
|
||||
t.deepEqual(readlinkSync.args[0], [XCODE_SELECT_LINK_PATH]);
|
||||
|
||||
t.is(addDiagnostic.callCount, 1);
|
||||
t.like(addDiagnostic.args[0], [
|
||||
config,
|
||||
BuiltInLanguage.swift,
|
||||
{
|
||||
attributes: {
|
||||
languages: [BuiltInLanguage.swift],
|
||||
xcodeVersion: "27.0.0",
|
||||
},
|
||||
severity: "error",
|
||||
source: {
|
||||
id: "codeql-action/unsupported-traced-swift-analysis-xcode",
|
||||
name: "Traced Swift analysis is not supported on this version of Xcode",
|
||||
},
|
||||
visibility: {
|
||||
cliSummaryTable: true,
|
||||
statusPage: true,
|
||||
telemetry: true,
|
||||
},
|
||||
} satisfies Partial<diagnostics.DiagnosticMessage>,
|
||||
]);
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import * as nodefs from "fs";
|
||||
|
||||
import * as semver from "semver";
|
||||
|
||||
import { ActionState, Logger } from "../action-common";
|
||||
@@ -36,7 +34,7 @@ export const SWIFT_TRACED_UNSUPPORTED_XCODE = 27;
|
||||
*/
|
||||
export function xcodeVersion(
|
||||
logger: Logger,
|
||||
fs: FileSystem<"statSync" | "readlinkSync"> = nodefs,
|
||||
fs: FileSystem<"statSync" | "readlinkSync">,
|
||||
): semver.SemVer | undefined {
|
||||
try {
|
||||
// Stat the expected symbolic link to check that it exists and is a symbolic link.
|
||||
@@ -87,6 +85,66 @@ export function xcodeVersion(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a diagnostic indicating that `version` of `product` is unsupported for traced Swift analysis.
|
||||
* Depending on `skipUnsupportedTracedAnalysis`, this function then either throws a {@link ConfigurationError}
|
||||
* or logs the problem as a warning.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @param config The CodeQL Action configuration.
|
||||
* @param skipUnsupportedTracedAnalysis Whether this is a fatal error.
|
||||
* @param product The product that the version is unsupported of.
|
||||
* @param version The unsupported version.
|
||||
*/
|
||||
function handleUnsupportedVersion(
|
||||
logger: Logger,
|
||||
config: Config,
|
||||
skipUnsupportedTracedAnalysis: boolean,
|
||||
product: "macOS" | "Xcode",
|
||||
version: semver.SemVer,
|
||||
) {
|
||||
const baseMessage = [
|
||||
`Traced Swift analysis is not supported on ${product} ${SWIFT_TRACED_UNSUPPORTED_MACOS} or above.`,
|
||||
`Configure your analysis to run on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS - 1} or below`,
|
||||
`and XCode ${SWIFT_TRACED_UNSUPPORTED_XCODE - 1} or below.`,
|
||||
].join(" ");
|
||||
|
||||
const attributeName = product === "macOS" ? "macOSVersion" : "xcodeVersion";
|
||||
|
||||
// Create a diagnostic that will show up on the TSP.
|
||||
addDiagnostic(
|
||||
config,
|
||||
BuiltInLanguage.swift,
|
||||
makeDiagnostic(
|
||||
`codeql-action/unsupported-traced-swift-analysis-${product.toLowerCase()}`,
|
||||
`Traced Swift analysis is not supported on this version of ${product}`,
|
||||
{
|
||||
attributes: {
|
||||
languages: config.languages,
|
||||
[attributeName]: version.toString(),
|
||||
},
|
||||
markdownMessage: baseMessage,
|
||||
severity: skipUnsupportedTracedAnalysis ? "error" : "warning",
|
||||
visibility: {
|
||||
cliSummaryTable: true,
|
||||
statusPage: true,
|
||||
telemetry: true,
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Throw an error to abort the analysis if the FF is enabled or log the message.
|
||||
if (skipUnsupportedTracedAnalysis) {
|
||||
// ConfigurationErrors are converted to the "aborted" status by the exception handler
|
||||
// in `init-action.ts` that guards the call to `isSwiftCompatible`.
|
||||
throw new ConfigurationError(baseMessage);
|
||||
} else {
|
||||
// This will also show up as a workflow annotation.
|
||||
logger.warning(baseMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether we can run a Swift analysis on the current runner.
|
||||
*
|
||||
@@ -122,55 +180,39 @@ export async function isSwiftCompatible(
|
||||
`Swift analysis is only supported on macOS runner images. Please migrate to a macOS runner.`,
|
||||
);
|
||||
}
|
||||
// If we got a string, we are on macOS but couldn't parse the version string.
|
||||
if (typeof version === "string") {
|
||||
action.logger.warning(
|
||||
`Unable to determine version of macOS, got: ${version}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const skipUnsupportedTracedAnalysis = await action.features.getValue(
|
||||
Feature.SwiftSkipUnsupportedTracedAnalysis,
|
||||
);
|
||||
if (version.major >= SWIFT_TRACED_UNSUPPORTED_MACOS) {
|
||||
const baseMessage = [
|
||||
`Traced Swift analysis is not supported on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS} or above.`,
|
||||
`Configure your analysis to run on macOS ${SWIFT_TRACED_UNSUPPORTED_MACOS - 1} or below`,
|
||||
`and XCode ${SWIFT_TRACED_UNSUPPORTED_XCODE - 1} or below.`,
|
||||
].join(" ");
|
||||
|
||||
// Create a diagnostic that will show up on the TSP.
|
||||
addDiagnostic(
|
||||
config,
|
||||
BuiltInLanguage.swift,
|
||||
makeDiagnostic(
|
||||
"codeql-action/unsupported-traced-swift-analysis-macos",
|
||||
"Traced Swift analysis is not supported on this version of macOS",
|
||||
{
|
||||
attributes: {
|
||||
languages: config.languages,
|
||||
macOSVersion: version.toString(),
|
||||
},
|
||||
markdownMessage: baseMessage,
|
||||
severity: skipUnsupportedTracedAnalysis ? "error" : "warning",
|
||||
visibility: {
|
||||
cliSummaryTable: true,
|
||||
statusPage: true,
|
||||
telemetry: true,
|
||||
},
|
||||
},
|
||||
),
|
||||
if (typeof version === "string") {
|
||||
// If we got a string, we are on macOS but couldn't parse the version string.
|
||||
action.logger.warning(
|
||||
`Unable to determine version of macOS, got: ${version}`,
|
||||
);
|
||||
} else if (version.major >= SWIFT_TRACED_UNSUPPORTED_MACOS) {
|
||||
handleUnsupportedVersion(
|
||||
action.logger,
|
||||
config,
|
||||
skipUnsupportedTracedAnalysis,
|
||||
"macOS",
|
||||
version,
|
||||
);
|
||||
}
|
||||
|
||||
// Throw an error to abort the analysis if the FF is enabled or log the message.
|
||||
if (skipUnsupportedTracedAnalysis) {
|
||||
// ConfigurationErrors are converted to the "aborted" status by the exception handler
|
||||
// in `init-action.ts` that guards the call to `isSwiftCompatible`.
|
||||
throw new ConfigurationError(baseMessage);
|
||||
} else {
|
||||
// This will also show up as a workflow annotation.
|
||||
action.logger.warning(baseMessage);
|
||||
}
|
||||
// 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, action.fs);
|
||||
|
||||
if (
|
||||
xcodeVer !== undefined &&
|
||||
xcodeVer.major >= SWIFT_TRACED_UNSUPPORTED_XCODE
|
||||
) {
|
||||
handleUnsupportedVersion(
|
||||
action.logger,
|
||||
config,
|
||||
skipUnsupportedTracedAnalysis,
|
||||
"Xcode",
|
||||
xcodeVer,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user