Skip to content

feat: drop support for macOS Sierra and below #3982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lib/commands/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export class DebugIOSCommand implements ICommand {
private $platformService: IPlatformService,
private $options: IOptions,
private $injector: IInjector,
private $sysInfo: ISysInfo,
private $projectData: IProjectData,
$iosDeviceOperations: IIOSDeviceOperations,
$iOSSimulatorLogProvider: Mobile.IiOSSimulatorLogProvider) {
Expand All @@ -161,6 +162,12 @@ export class DebugIOSCommand implements ICommand {
this.$errors.fail(`Timeout option specifies the seconds NativeScript CLI will wait to find the inspector socket port from device's logs. Must be a number.`);
}

if (this.$options.inspector) {
const macOSWarning = await this.$sysInfo.getMacOSWarningMessage();
if (macOSWarning && macOSWarning.severity === SystemWarningsSeverity.high) {
this.$errors.fail(`You cannot use NativeScript Inspector on this OS. To use it, please update your OS.`);
}
}
const result = await this.debugPlatformCommand.canExecute(args);
return result;
}
Expand Down
12 changes: 9 additions & 3 deletions lib/common/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,12 @@ interface IDeviceLiveSyncService extends IDeviceLiveSyncServiceBase {
afterInstallApplicationAction?(deviceAppData: Mobile.IDeviceAppData, localToDevicePaths: Mobile.ILocalToDevicePathData[]): Promise<boolean>;
}

interface ISystemWarning {
message: string;
severity: SystemWarningsSeverity;
toString?: () => string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need .toString method? Can we just use warning.message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to mention this in the PR description - the toString is required for a minimal backwards compatibility. With the old code, you were able to use the result of getSystemWarnings() and join it with EOL for example and print it. In case we do not have the toString implementation here, the join operation will use the default toString, which returns [Object object].

}

interface ISysInfo {
getSysInfo(config?: NativeScriptDoctor.ISysInfoConfig): Promise<NativeScriptDoctor.ISysInfoData>;
/**
Expand All @@ -1163,15 +1169,15 @@ interface ISysInfo {

/**
* Gets all global warnings for the current environment, for example Node.js version compatibility, OS compatibility, etc.
* @return {Promise<string[]>} All warnings. Empty array is returned in case the system is setup correctly.
* @return {Promise<ISystemWarning[]>} All warnings. Empty array is returned in case the system is setup correctly.
*/
getSystemWarnings(): Promise<string[]>;
getSystemWarnings(): Promise<ISystemWarning[]>;

/**
* Gets warning message for current macOS version.
* @return {Promise<string>} Message in case the current macOS version is deprecated, null otherwise.
*/
getMacOSWarningMessage(): Promise<string>;
getMacOSWarningMessage(): Promise<ISystemWarning>;

/**
* Returns the value of engines.node key from CLI's package.json file.
Expand Down
1 change: 1 addition & 0 deletions lib/common/definitions/logger.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ interface ILogger {
prepare(item: any): string;
printInfoMessageOnSameLine(message: string): void;
printMsgWithTimeout(message: string, timeout: number): Promise<void>;
printOnStderr(formatStr?: any, ...args: any[]): void;
}
12 changes: 1 addition & 11 deletions lib/common/host-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,7 @@ export class HostInfo implements IHostInfo {
try {
const systemProfileOutput = await this.$childProcess.exec(systemProfileCommand);

// Output of command is similar to:
/*
Software:

System Software Overview:

System Version: macOS 10.13.3 (17D47)
Kernel Version: Darwin 17.4.0
Time since boot: 68 days 22:12
*/
const versionRegExp = /System Version:\s+?macOS\s+?(\d+\.\d+)\.\d+\s+/g;
const versionRegExp = /System Version:\s+?macOS\s+?(\d+\.\d+)(\.\d+)?\s+/g;
const regExpMatchers = versionRegExp.exec(systemProfileOutput);
const macOSVersion = regExpMatchers && regExpMatchers[1];
if (macOSVersion) {
Expand Down
6 changes: 6 additions & 0 deletions lib/common/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ export class Logger implements ILogger {
this.write(formattedMessage);
}

public printOnStderr(...args: string[]): void {
if (process.stderr) {
process.stderr.write(util.format.apply(null, args));
}
}

private getPasswordEncodedArguments(args: string[]): string[] {
return _.map(args, argument => {
if (typeof argument === 'string' && !!argument.match(/password/i)) {
Expand Down
21 changes: 21 additions & 0 deletions lib/common/test/unit-tests/host-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,27 @@ describe("hostInfo", () => {
assert.equal(calledCommand, "system_profiler SPSoftwareDataType -detailLevel mini");
});

it("returns correct macOS version based on system_profile, when version has two numbers only", async () => {
const testInjector = createTestInjector();
const hostInfo = testInjector.resolve<IHostInfo>("hostInfo");
const childProcess = testInjector.resolve<IChildProcess>("childProcess");
let calledCommand = "";
childProcess.exec = async (command: string, options?: any, execOptions?: IExecOptions): Promise<any> => {
calledCommand = command;
return `Software:

System Software Overview:

System Version: macOS 10.14 (18A391)
Kernel Version: Darwin 18.0.0
Time since boot: 1 day 5:52`;
};

const macOSVersion = await hostInfo.getMacOSVersion();
assert.deepEqual(macOSVersion, "10.14");
assert.equal(calledCommand, "system_profiler SPSoftwareDataType -detailLevel mini");
});

it("returns correct macOS version when system_profile call throws", async () => {
const testInjector = createTestInjector();
const hostInfo = testInjector.resolve<IHostInfo>("hostInfo");
Expand Down
4 changes: 4 additions & 0 deletions lib/common/test/unit-tests/stubs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export class CommonLoggerStub implements ILogger {
printMarkdown(message: string): void {
this.output += message;
}

printOnStderr(...args: string[]): void {
// nothing to do here
}
}

export class ErrorsStub implements IErrors {
Expand Down
11 changes: 7 additions & 4 deletions lib/common/verify-node-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ export function verifyNodeVersion(): void {
}

var nodeWarning = getNodeWarning();
if (nodeWarning) {
console.warn((os.EOL + nodeWarning + os.EOL).yellow.bold);
if (nodeWarning && nodeWarning.message) {
console.warn((`${os.EOL}${nodeWarning.message}${os.EOL}`).yellow.bold);
}
}

export function getNodeWarning(): string {
export function getNodeWarning(): ISystemWarning {
var verificationOpts = getNodeVersionOpts();
var cliName = verificationOpts.cliName;
var supportedVersionsRange = verificationOpts.supportedVersionsRange;
Expand All @@ -78,6 +78,9 @@ export function getNodeWarning(): string {
}
}

return warningMessage;
return {
message: warningMessage,
severity: SystemWarningsSeverity.medium
};
}
/* tslint:enable */
3 changes: 2 additions & 1 deletion lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,10 @@ export class AssetConstants {
export class MacOSVersions {
public static Sierra = "10.12";
public static HighSierra = "10.13";
public static Mojave = "10.14";
}

export const MacOSDeprecationStringFormat = "Support for macOS %s is deprecated and will be removed in one of the next releases of NativeScript. Please, upgrade to the latest macOS version.";
export const MacOSDeprecationStringFormat = "NativeScript does not support macOS %s and some functionality may not work. Please, upgrade to the latest macOS version.";
export const PROGRESS_PRIVACY_POLICY_URL = "https://www.progress.com/legal/privacy-policy";
export class SubscribeForNewsletterMessages {
public static AgreeToReceiveEmailMsg = "I agree".green.bold + " to receive email communications from Progress Software or its Partners (`https://www.progress.com/partners/partner-directory`)," +
Expand Down
4 changes: 4 additions & 0 deletions lib/definitions/system-warnings.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare const enum SystemWarningsSeverity {
medium = "medium",
high = "high"
}
8 changes: 6 additions & 2 deletions lib/nativescript-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ import { settlePromises } from "./common/helpers";
const $sysInfo = $injector.resolve<ISysInfo>("sysInfo");
const macOSWarning = await $sysInfo.getMacOSWarningMessage();
if (macOSWarning) {
const message = EOL + macOSWarning + EOL ;
logger.warn(message);
const message = `${EOL}${macOSWarning.message}${EOL}`;
if (macOSWarning.severity === SystemWarningsSeverity.high) {
logger.printOnStderr(message.red.bold);
} else {
logger.warn(message);
}
}

const commandDispatcher: ICommandDispatcher = $injector.resolve("commandDispatcher");
Expand Down
13 changes: 9 additions & 4 deletions lib/sys-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,17 @@ export class SysInfo implements ISysInfo {
}

@exported("sysInfo")
public async getSystemWarnings(): Promise<string[]> {
const warnings: string[] = [];
public async getSystemWarnings(): Promise<ISystemWarning[]> {
const warnings: ISystemWarning[] = [];
const macOSWarningMessage = await this.getMacOSWarningMessage();
if (macOSWarningMessage) {
macOSWarningMessage.toString = function() { return this.message; };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

macOSWarningMessage.toString = () => this.message

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will not work - the current class does not have message property and in case I use lambda, the current this will be used inside it. That's why I need function.

warnings.push(macOSWarningMessage);
}

const nodeWarning = getNodeWarning();
if (nodeWarning) {
nodeWarning.toString = function() { return this.message; };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nodeWarning.toString = () => this.message

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will not work - the current class does not have message property and in case I use lambda, the current this will be used inside it. That's why I need function.

warnings.push(nodeWarning);
}

Expand All @@ -57,10 +59,13 @@ export class SysInfo implements ISysInfo {
return jsonContent && jsonContent.engines && jsonContent.engines.node;
}

public async getMacOSWarningMessage(): Promise<string> {
public async getMacOSWarningMessage(): Promise<ISystemWarning> {
const macOSVersion = await this.$hostInfo.getMacOSVersion();
if (macOSVersion && macOSVersion < MacOSVersions.HighSierra) {
return format(MacOSDeprecationStringFormat, macOSVersion);
return {
message: format(MacOSDeprecationStringFormat, macOSVersion),
severity: SystemWarningsSeverity.high
};
}

return null;
Expand Down
4 changes: 4 additions & 0 deletions test/stubs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export class LoggerStub implements ILogger {
}

printMarkdown(message: string): void { }

printOnStderr(...args: string[]): void {
// nothing to do here
}
}

export class ProcessServiceStub implements IProcessService {
Expand Down
24 changes: 14 additions & 10 deletions test/sys-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ describe("sysInfo", () => {
};

describe("getSystemWarnings", () => {
const getSystemWarnings = async (opts?: { nodeJsWarning?: string, macOSDeprecatedVersion?: string }): Promise<string[]> => {
sandbox.stub(verifyNodeVersion, "getNodeWarning").returns(opts && opts.nodeJsWarning);
const getSystemWarnings = async (opts?: { nodeJsWarning?: string, macOSDeprecatedVersion?: string }): Promise<ISystemWarning[]> => {
sandbox.stub(verifyNodeVersion, "getNodeWarning").returns(opts && opts.nodeJsWarning ? { message: opts.nodeJsWarning, severity: SystemWarningsSeverity.medium } : null);

const testInjector = createTestInjector();
const $hostInfo = testInjector.resolve<IHostInfo>("hostInfo");
Expand All @@ -50,28 +50,31 @@ describe("sysInfo", () => {

it("returns correct single warning when macOS version is deprecated", async () => {
const macOSDeprecatedVersion = MacOSVersions.Sierra;
const macOSWarning = format(MacOSDeprecationStringFormat, macOSDeprecatedVersion);
const macOSWarning = { message: format(MacOSDeprecationStringFormat, macOSDeprecatedVersion), severity: SystemWarningsSeverity.high };
const warnings = await getSystemWarnings({ macOSDeprecatedVersion });
_.each(warnings, warning => delete warning.toString);
assert.deepEqual(warnings, [macOSWarning]);
});

it("returns correct single warning when Node.js version is deprecated", async () => {
const nodeJsWarning = "Node.js Warning";
const warnings = await getSystemWarnings({ nodeJsWarning });
const nodeJsWarning = { message: "Node.js Warning", severity: SystemWarningsSeverity.medium };
const warnings = await getSystemWarnings({ nodeJsWarning: nodeJsWarning.message });
_.each(warnings, warning => delete warning.toString);
assert.deepEqual(warnings, [nodeJsWarning]);
});

it("returns correct warnings when both Node.js and macOS versions are deprecated", async () => {
const macOSDeprecatedVersion = MacOSVersions.Sierra;
const macOSWarning = format(MacOSDeprecationStringFormat, macOSDeprecatedVersion);
const nodeJsWarning = "Node.js Warning";
const warnings = await getSystemWarnings({ macOSDeprecatedVersion, nodeJsWarning });
const macOSWarning = { message: format(MacOSDeprecationStringFormat, macOSDeprecatedVersion), severity: SystemWarningsSeverity.high };
const nodeJsWarning = { message: "Node.js Warning", severity: SystemWarningsSeverity.medium };
const warnings = await getSystemWarnings({ macOSDeprecatedVersion, nodeJsWarning: nodeJsWarning.message });
_.each(warnings, warning => delete warning.toString);
assert.deepEqual(warnings, [macOSWarning, nodeJsWarning]);
});
});

describe("getMacOSWarningMessage", () => {
const getMacOSWarning = async (macOSDeprecatedVersion?: string): Promise<string> => {
const getMacOSWarning = async (macOSDeprecatedVersion?: string): Promise<ISystemWarning> => {
sandbox.stub(verifyNodeVersion, "getNodeWarning").returns(null);

const testInjector = createTestInjector();
Expand All @@ -89,8 +92,9 @@ describe("sysInfo", () => {

it("returns correct single warning when macOS version is deprecated", async () => {
const macOSDeprecatedVersion = MacOSVersions.Sierra;
const macOSWarning = format(MacOSDeprecationStringFormat, macOSDeprecatedVersion);
const macOSWarning: ISystemWarning = { message: format(MacOSDeprecationStringFormat, macOSDeprecatedVersion), severity: SystemWarningsSeverity.high };
const warning = await getMacOSWarning(macOSDeprecatedVersion);
delete warning.toString;
assert.deepEqual(warning, macOSWarning);
});
});
Expand Down