Skip to content

Commit ddd8328

Browse files
Fix isValidNativeScript project (#2630)
* Get latest application package for current specified configuration When we try to get the latest application package for device/emulator, we check the build output directory and get latest available .apk/.ipa. However this is not always correct as sometimes we do not build the app. Consider the following case: * tns build android --release * tns build android * tns build android --release At the last point, the build will not be executed, as there are no changes. However the last built .apk is from the debug build (we have release .apk, but it's older). So in case we try to get the last build output from last operation, CLI will return the debug.apk Fix this by checking the current build configuration and get the latest result by using it. For iOS respect the expected output - is it for device or for simulator as the output is different. * Fix isValidNativeScript project The isValidNativeScript project method is used in Fusion. However the implementation is not correct. Fix it to have correct behavior. In order to fix it, modify projectData.initialize method - there's obsolete code for migration from .tnsproject to package.json - we do not need it anymore, so remove it. Also fix a case where failing builds do not fail the build process (incorrect argument passed to childProcess.spawnFromEvent). Update documentation for PublicAPI. * Throw correct error when build for iOS in non-interactive terminal Also in case CLI's executed in non-interactive terminal and there's no DEVELOPMENT_TEAM set, tns build ios --for-device fails with message "Console is not interactive and no default action specified" which does not give any info to the users. So in this case add more descriptive error message. * Fix local builds when CLI is required as lib When CLI is required as library, the `$options` dependency is not populated. However the projectChangesService relies on it in order to determine if the project should be prepared/built. When CLI is required as library and you change only the build configuration (debug/release), the project is not rebuilt. However when you use the CLI and try the same, a new full build is triggered. Fix this by parsing required boolean flags to projectChangesService and exclude `$options` from its implementation. This way local builds will work in the same manner both from command line and when required as library. Steps to reproduce the problem: * use CLI as lib * create local build for android in debug configuration * create local build for android in release configuration - you'll notice gradle clean is not called at all and also in the `<project dir>/platforms/android/build/outputs/apks/` there are both debug and release apks. This should never happen when changing configurations. * Pass buildConfig when getting path to last build output Pass the whole buildConfig object when getting the path to the last build output. This required changes in debug services and TestExecutionService. Also change the args of cleanProject method - the `options` passed to `gradle` are now determined in the method itself instead of passing them from the caller. This way we'll not require "android-23" (the default one set in build.gradle) when we miss to pass the required options.
1 parent 62a3872 commit ddd8328

27 files changed

+248
-333
lines changed

PublicAPI.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,32 @@ tns.projectService.createProject(projectSettings)
113113
</tr>
114114
</table>
115115

116+
* `isValidNativeScriptProject(projectDir: string): boolean` - Checks if the specified path is a valid NativeScript project. Returns `true` in case the directory is a valid project, `false` otherwise.
117+
118+
Sample usage:
119+
<table>
120+
<tr>
121+
<td>
122+
JavaScript
123+
</td>
124+
<td>
125+
TypeScript
126+
</td>
127+
</tr>
128+
<tr>
129+
<td>
130+
<pre lang="javascript">
131+
const isValidProject = tns.projectService.isValidNativeScriptProject("/tmp/myProject");
132+
</pre>
133+
</td>
134+
<td>
135+
<pre lang="typescript">
136+
const isValidProject = tns.projectService.isValidNativeScriptProject("/tmp/myProject");
137+
</pre>
138+
</td>
139+
</tr>
140+
</table>
141+
116142
## How to add a new method to Public API
117143
CLI is designed as command line tool and when it is used as a library, it does not give you access to all of the methods. This is mainly implementation detail. Most of the CLI's code is created to work in command line, not as a library, so before adding method to public API, most probably it will require some modification.
118144
For example the `$options` injected module contains information about all `--` options passed on the terminal. When the CLI is used as a library, the options are not populated. Before adding method to public API, make sure its implementation does not rely on `$options`.

lib/commands/appstore-upload.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export class PublishIOS implements ICommand {
7373
// This is not very correct as if we build multiple targets we will try to sign all of them using the signing identity here.
7474
await this.$platformService.preparePlatform(platform, appFilesUpdaterOptions, this.$options.platformTemplate, this.$projectData, { provision: this.$options.provision, sdk: this.$options.sdk });
7575
await this.$platformService.buildPlatform(platform, iOSBuildConfig, this.$projectData);
76-
ipaFilePath = this.$platformService.lastOutputPath(platform, { isForDevice: iOSBuildConfig.buildForDevice }, this.$projectData);
76+
ipaFilePath = this.$platformService.lastOutputPath(platform, iOSBuildConfig, this.$projectData);
7777
} else {
7878
this.$logger.info("No .ipa, mobile provision or certificate set. Perfect! Now we'll build .xcarchive and let Xcode pick the distribution certificate and provisioning profile for you when exporting .ipa for AppStore submission.");
7979
await this.$platformService.preparePlatform(platform, appFilesUpdaterOptions, this.$options.platformTemplate, this.$projectData, { provision: this.$options.provision, sdk: this.$options.sdk });

lib/commands/build.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export class BuildCommandBase {
2626
};
2727
await this.$platformService.buildPlatform(platform, buildConfig, this.$projectData);
2828
if (this.$options.copyTo) {
29-
this.$platformService.copyLastOutput(platform, this.$options.copyTo, { isForDevice: this.$options.forDevice }, this.$projectData);
29+
this.$platformService.copyLastOutput(platform, this.$options.copyTo, buildConfig, this.$projectData);
3030
}
3131
}
3232
}

lib/commands/debug.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@
1616
}
1717

1818
public async execute(args: string[]): Promise<void> {
19-
if (this.$options.start) {
20-
return this.debugService.debug(this.$projectData);
21-
}
22-
23-
const appFilesUpdaterOptions: IAppFilesUpdaterOptions = { bundle: this.$options.bundle, release: this.$options.release };
2419
const deployOptions: IDeployPlatformOptions = {
2520
clean: this.$options.clean,
2621
device: this.$options.device,
@@ -31,6 +26,15 @@
3126
provision: this.$options.provision,
3227
teamId: this.$options.teamId
3328
};
29+
30+
const buildConfig: IBuildConfig = _.merge({ buildForDevice: this.$options.forDevice }, deployOptions);
31+
32+
if (this.$options.start) {
33+
return this.debugService.debug(this.$projectData, buildConfig);
34+
}
35+
36+
const appFilesUpdaterOptions: IAppFilesUpdaterOptions = { bundle: this.$options.bundle, release: this.$options.release };
37+
3438
await this.$platformService.deployPlatform(this.$devicesService.platform, appFilesUpdaterOptions, deployOptions, this.$projectData, { provision: this.$options.provision, sdk: this.$options.sdk });
3539
this.$config.debugLivesync = true;
3640
let applicationReloadAction = async (deviceAppData: Mobile.IDeviceAppData): Promise<void> => {
@@ -45,7 +49,7 @@
4549

4650
await deviceAppData.device.applicationManager.stopApplication(applicationId);
4751

48-
await this.debugService.debug(this.$projectData);
52+
await this.debugService.debug(this.$projectData, buildConfig);
4953
};
5054
return this.$usbLiveSyncService.liveSync(this.$devicesService.platform, this.$projectData, applicationReloadAction);
5155
}

lib/common

lib/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const TESTING_FRAMEWORKS = ['jasmine', 'mocha', 'qunit'];
1515
export const TEST_RUNNER_NAME = "nativescript-unit-test-runner";
1616
export const LIVESYNC_EXCLUDED_FILE_PATTERNS = ["**/*.js.map", "**/*.ts"];
1717
export const XML_FILE_EXTENSION = ".xml";
18+
export const PLATFORMS_DIR_NAME = "platforms";
1819

1920
export class PackageVersion {
2021
static NEXT = "next";

lib/definitions/debug.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
interface IDebugService {
2-
debug(projectData: IProjectData): Promise<void>;
3-
debugStart(projectData: IProjectData): Promise<void>;
2+
debug(projectData: IProjectData, buildConfig: IBuildConfig): Promise<void>;
3+
debugStart(projectData: IProjectData, buildConfig: IBuildConfig): Promise<void>;
44
debugStop(): Promise<void>
55
platform: string;
66
}

lib/definitions/platform.d.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
interface IPlatformService extends NodeJS.EventEmitter {
22
cleanPlatforms(platforms: string[], platformTemplate: string, projectData: IProjectData, platformSpecificData: IPlatformSpecificData, framework?: string): Promise<void>;
3-
3+
44
addPlatforms(platforms: string[], platformTemplate: string, projectData: IProjectData, platformSpecificData: IPlatformSpecificData, frameworkPath?: string): Promise<void>;
55

66
/**
@@ -143,28 +143,37 @@ interface IPlatformService extends NodeJS.EventEmitter {
143143
/**
144144
* Returns information about the latest built application for device in the current project.
145145
* @param {IPlatformData} platformData Data describing the current platform.
146+
* @param {IBuildConfig} buildConfig Defines if the build is for release configuration.
146147
* @returns {IApplicationPackage} Information about latest built application.
147148
*/
148-
getLatestApplicationPackageForDevice(platformData: IPlatformData): IApplicationPackage;
149+
getLatestApplicationPackageForDevice(platformData: IPlatformData, buildConfig: IBuildConfig): IApplicationPackage;
149150

150151
/**
151152
* Returns information about the latest built application for simulator in the current project.
152153
* @param {IPlatformData} platformData Data describing the current platform.
154+
* @param {IBuildConfig} buildConfig Defines if the build is for release configuration.
153155
* @returns {IApplicationPackage} Information about latest built application.
154156
*/
155-
getLatestApplicationPackageForEmulator(platformData: IPlatformData): IApplicationPackage;
157+
getLatestApplicationPackageForEmulator(platformData: IPlatformData, buildConfig: IBuildConfig): IApplicationPackage;
156158

157159
/**
158160
* Copies latest build output to a specified location.
159161
* @param {string} platform Mobile platform - Android, iOS.
160162
* @param {string} targetPath Destination where the build artifact should be copied.
161-
* @param {{isForDevice: boolean}} settings Defines if the searched artifact should be for simulator.
163+
* @param {IBuildConfig} buildConfig Defines if the searched artifact should be for simulator and is it built for release.
162164
* @param {IProjectData} projectData DTO with information about the project.
163165
* @returns {void}
164166
*/
165-
copyLastOutput(platform: string, targetPath: string, settings: {isForDevice: boolean}, projectData: IProjectData): void;
167+
copyLastOutput(platform: string, targetPath: string, buildConfig: IBuildConfig, projectData: IProjectData): void;
166168

167-
lastOutputPath(platform: string, settings: { isForDevice: boolean }, projectData: IProjectData): string;
169+
/**
170+
* Gets the latest build output.
171+
* @param {string} platform Mobile platform - Android, iOS.
172+
* @param {IBuildConfig} buildConfig Defines if the searched artifact should be for simulator and is it built for release.
173+
* @param {IProjectData} projectData DTO with information about the project.
174+
* @returns {string} The path to latest built artifact.
175+
*/
176+
lastOutputPath(platform: string, buildConfig: IBuildConfig, projectData: IProjectData): string;
168177

169178
/**
170179
* Reads contents of a file on device.
@@ -209,8 +218,7 @@ interface IPlatformData {
209218
appDestinationDirectoryPath: string;
210219
deviceBuildOutputPath: string;
211220
emulatorBuildOutputPath?: string;
212-
validPackageNamesForDevice: string[];
213-
validPackageNamesForEmulator?: string[];
221+
getValidPackageNames(buildOptions: { isReleaseBuild?: boolean, isForDevice?: boolean }): string[];
214222
frameworkFilesExtensions: string[];
215223
frameworkDirectoriesExtensions?: string[];
216224
frameworkDirectoriesNames?: string[];

lib/definitions/project-changes.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ interface IProjectChangesInfo {
1919
changesRequireBuild: boolean;
2020
}
2121

22+
interface IProjectChangesOptions extends IAppFilesUpdaterOptions, IProvision {}
23+
2224
interface IProjectChangesService {
23-
checkForChanges(platform: string, projectData: IProjectData): IProjectChangesInfo;
25+
checkForChanges(platform: string, projectData: IProjectData, buildOptions: IProjectChangesOptions): IProjectChangesInfo;
2426
getPrepareInfo(platform: string, projectData: IProjectData): IPrepareInfo;
2527
savePrepareInfo(platform: string, projectData: IProjectData): void;
2628
getPrepareInfoFilePath(platform: string, projectData: IProjectData): string;

lib/definitions/project.d.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,10 @@ interface IPlatformProjectService extends NodeJS.EventEmitter {
254254
/**
255255
* Removes build artifacts specific to the platform
256256
* @param {string} projectRoot The root directory of the native project.
257-
* @param {string[]} options Options that can be passed to clean command.
258257
* @param {IProjectData} projectData DTO with information about the project.
259258
* @returns {void}
260259
*/
261-
cleanProject(projectRoot: string, options: string[], projectData: IProjectData): Promise<void>
260+
cleanProject(projectRoot: string, projectData: IProjectData): Promise<void>
262261
}
263262

264263
interface IAndroidProjectPropertiesManager {

0 commit comments

Comments
 (0)