diff --git a/lib/entry-points.js b/lib/entry-points.js index e6254b7ad..6d44a156e 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -185952,10 +185952,13 @@ async function getToolsInput(action, repositoryProperties) { } // src/languages/swift.ts -function isSwiftCompatible(action, config) { +async function isSwiftCompatible(action, config, codeql) { if (!config.languages.includes("swift" /* swift */)) { return; } + if (await codeql.supportsFeature("swiftSupportsAllPlatforms" /* SwiftSupportsAllPlatforms */)) { + return; + } const version = macOSVersion(action); if (version === void 0) { throw new ConfigurationError( @@ -186488,7 +186491,7 @@ async function run3(actionState) { enableFileCoverageInformation: fileCoverageResult.enabled, logger: logger2 }); - isSwiftCompatible(actionState, config); + await isSwiftCompatible(actionState, config, codeql); if (repositoryPropertiesResult.isFailure()) { addNoLanguageDiagnostic( config, diff --git a/src/init-action.ts b/src/init-action.ts index 48c429e14..6c62adfbb 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -419,7 +419,7 @@ async function run( logger, }); - isSwiftCompatible(actionState, config); + await isSwiftCompatible(actionState, config, codeql); if (repositoryPropertiesResult.isFailure()) { addNoLanguageDiagnostic( diff --git a/src/languages/swift.test.ts b/src/languages/swift.test.ts index ecbaae76f..745f631b5 100644 --- a/src/languages/swift.test.ts +++ b/src/languages/swift.test.ts @@ -1,59 +1,130 @@ import test from "ava"; +import * as sinon from "sinon"; +import { getCodeQLForTesting } from "../codeql"; +import { ActionsEnvVars } from "../environment"; import { checkExpectedLogMessages, createTestConfig, + getTestEnv, initAllState, + makeVersionInfo, RecordingLogger, } from "../testing-utils"; +import { ToolsFeature } from "../tools-features"; +import { withTmpDir } from "../util"; import { isSwiftCompatible } from "./swift"; import { BuiltInLanguage } from "."; -test("isSwiftCompatible doesn't throw for non-Swift languages", (t) => { +test("isSwiftCompatible doesn't throw for non-Swift languages", async (t) => { for (const language of Object.values(BuiltInLanguage)) { if (language === BuiltInLanguage.swift) { continue; } - t.notThrows(() => + const codeql = await getCodeQLForTesting(); + await t.notThrowsAsync( isSwiftCompatible( initAllState(), createTestConfig({ languages: [language] }), + codeql, ), ); } }); -test("isSwiftCompatible doesn't throw for Swift on darwin", (t) => { - t.notThrows(() => { - isSwiftCompatible( - initAllState({ platform: "darwin" }), - createTestConfig({ languages: [BuiltInLanguage.swift] }), +test("isSwiftCompatible doesn't throw for Swift if CLI supports swiftSupportsAllPlatforms", async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLForTesting("codeql-for-testing", logger, env); + const supportsFeature = sinon + .stub(codeql, "supportsFeature") + .withArgs(ToolsFeature.SwiftSupportsAllPlatforms) + .resolves(true); + + await t.notThrowsAsync( + isSwiftCompatible( + initAllState({ platform: "darwin", env, logger }), + createTestConfig({ languages: [BuiltInLanguage.swift] }), + codeql, + ), ); - }); -}); + + t.is(supportsFeature.callCount, 1); + t.deepEqual(supportsFeature.args[0], [ + ToolsFeature.SwiftSupportsAllPlatforms, + ]); + })); + +test("isSwiftCompatible doesn't throw for Swift on darwin", async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLForTesting("codeql-for-testing", logger, env); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + await t.notThrowsAsync( + isSwiftCompatible( + initAllState({ platform: "darwin", env, logger }), + createTestConfig({ languages: [BuiltInLanguage.swift] }), + codeql, + ), + ); + })); const nonDarwinPlatforms: NodeJS.Platform[] = ["linux", "win32"]; for (const nonDarwinPlatform of nonDarwinPlatforms) { - test(`isSwiftCompatible throws for Swift on ${nonDarwinPlatform}`, (t) => { - t.throws(() => { - isSwiftCompatible( - initAllState({ platform: nonDarwinPlatform }), - createTestConfig({ languages: [BuiltInLanguage.swift] }), + test(`isSwiftCompatible throws for Swift on ${nonDarwinPlatform}`, async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLForTesting( + "codeql-for-testing", + logger, + env, ); - }); - }); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + await t.throwsAsync( + isSwiftCompatible( + initAllState({ platform: nonDarwinPlatform, env, logger }), + createTestConfig({ languages: [BuiltInLanguage.swift] }), + codeql, + ), + ); + })); } -test("isSwiftCompatible warns if version string is not a semver", (t) => { - const logger = new RecordingLogger(); - isSwiftCompatible( - initAllState({ logger, platform: "darwin", osRelease: "unexpected" }), - createTestConfig({ languages: [BuiltInLanguage.swift] }), - ); - checkExpectedLogMessages(t, logger.messages, [ - "Unable to determine version of macOS, got: unexpected", - ]); -}); +test("isSwiftCompatible warns if version string is not a semver", async (t) => + withTmpDir(async (tmpDir) => { + const logger = new RecordingLogger(); + const env = getTestEnv(); + env.set(ActionsEnvVars.RUNNER_TEMP, tmpDir); + + const codeql = await getCodeQLForTesting("codeql-for-testing", logger, env); + sinon.stub(codeql, "getVersion").resolves(makeVersionInfo("2.27.0")); + + await isSwiftCompatible( + initAllState({ + logger, + platform: "darwin", + osRelease: "unexpected", + env, + }), + createTestConfig({ languages: [BuiltInLanguage.swift] }), + codeql, + ); + + checkExpectedLogMessages(t, logger.messages, [ + "Unable to determine version of macOS, got: unexpected", + ]); + })); diff --git a/src/languages/swift.ts b/src/languages/swift.ts index fa6517c6d..3b6d70959 100644 --- a/src/languages/swift.ts +++ b/src/languages/swift.ts @@ -1,6 +1,8 @@ import { ActionState } from "../action-common"; +import { CodeQL } from "../codeql"; import { Config } from "../config-utils"; import { macOSVersion } from "../platform"; +import { ToolsFeature } from "../tools-features"; import { ConfigurationError } from "../util"; import { BuiltInLanguage } from "."; @@ -14,15 +16,23 @@ import { BuiltInLanguage } from "."; * @throws {ConfigurationError} If Swift analysis is not possible on the current runner. * @returns True if we can run a Swift analysis. */ -export function isSwiftCompatible( +export async function isSwiftCompatible( action: ActionState<["Base", "Logger"]>, config: Config, + codeql: CodeQL, ) { // The checks are not relevant if we are not trying to analyse Swift. if (!config.languages.includes(BuiltInLanguage.swift)) { return; } + // Skip the checks if the `swiftSupportsAllPlatforms` feature is supported by the CLI. + // This is a forward-looking measure that allows a future CLI update to disable these + // platform checks in the Action when they shouldn't be enforced anymore. + if (await codeql.supportsFeature(ToolsFeature.SwiftSupportsAllPlatforms)) { + return; + } + // Try to get the macOS version. const version = macOSVersion(action); diff --git a/src/testing-utils.ts b/src/testing-utils.ts index 27e439649..e8d3db706 100644 --- a/src/testing-utils.ts +++ b/src/testing-utils.ts @@ -35,6 +35,7 @@ import { Logger } from "./logging"; import { OverlayDatabaseMode } from "./overlay/overlay-database-mode"; import { getBundlePlatform } from "./platform"; import { ActionName } from "./status-report"; +import { ToolsFeature } from "./tools-features"; import { DEFAULT_DEBUG_ARTIFACT_NAME, DEFAULT_DEBUG_DATABASE_NAME, @@ -876,7 +877,7 @@ export function mockLanguagesInRepo(languages: string[]) { */ export const makeVersionInfo = ( version: string, - features?: { [name: string]: boolean }, + features?: { [key in ToolsFeature]?: boolean }, overlayVersion?: number, ): VersionInfo => ({ version,