-
-
Notifications
You must be signed in to change notification settings - Fork 197
Kddimitrov/aab build #4084
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
Kddimitrov/aab build #4084
Conversation
8f3cc2a
to
cdb1ae1
Compare
cdb1ae1
to
d5432f7
Compare
const gradleArgs = this.getGradleBuildOptions(buildConfig, projectData); | ||
const baseTask = buildConfig.androidBundle ? "bundle" : "assemble"; | ||
const platformData = this.getPlatformData(projectData); | ||
const outputPath = buildConfig.androidBundle ? platformData.bundleBuildOutputPath : platformData.deviceBuildOutputPath; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use this._platformData
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because we can't mock it inside tests - _platformData is private. Initially I used this._platformData
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And _platformData
is not used anywhere else inside the service. Everywhere we use this.getPlatformData
, but we should change that or at least cache the platformData
based on the projectData
.
if (this.$logger.getLevel() === "TRACE") { | ||
gradleArgs.unshift("--stacktrace"); | ||
gradleArgs.unshift("--debug"); | ||
} | ||
if (buildConfig.release) { | ||
gradleArgs.unshift("assembleRelease"); | ||
task = baseTask + "Release"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
task = `${baseTask}Release`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we have a linter rule if we won't use string concatenation at all?
} else { | ||
gradleArgs.unshift("assembleDebug"); | ||
task = baseTask + "Debug"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
task = `${baseTask}Debug`
lib/services/platform-service.ts
Outdated
@@ -256,7 +256,11 @@ export class PlatformService extends EventEmitter implements IPlatformService { | |||
return true; | |||
} | |||
|
|||
public async validateOptions(provision: true | string, teamId: true | string, projectData: IProjectData, platform?: string): Promise<boolean> { | |||
public async validateOptions(provision: true | string, teamId: true | string, projectData: IProjectData, platform?: string, aab?: boolean): Promise<boolean> { | |||
if (platform && this.$mobileHelper.isiOSPlatform(platform) && aab) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (platform && !this.$mobileHelper.isAndroidPlatform(platform) && aab)
is better because if we add new platform the above check will be fine.
lib/constants.ts
Outdated
@@ -241,3 +243,8 @@ export class BundleValidatorMessages { | |||
public static MissingBundlePlugin = "Passing --bundle requires a bundling plugin. No bundling plugin found or the specified bundling plugin is invalid."; | |||
public static NotSupportedVersion = `The NativeScript CLI requires nativescript-dev-webpack %s or later to work properly. After updating nativescript-dev-webpack you need to ensure "webpack.config.js" file is up to date with the one in the new version of nativescript-dev-webpack. You can automatically update it using "./node_modules/.bin/update-ns-webpack --configs" command.`; | |||
} | |||
|
|||
export class AndroidBundleValidatorMessages { | |||
public static AAB_NOT_SUPPORTED_BY_COMMNAND_MESSAGE = "This command does not support --aab (Android Application Bundle) parameter."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOT_SUPPORTED_AAB_OPTION
maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think AAB_NOT_SUPPORTED_BY_COMMNAND_MESSAGE is better at describing the message. If you see in constants NOT_SUPPORTED_AAB_OPTION and decide to use it in a service the error message will look strange for sidekick for example.
lib/constants.ts
Outdated
|
||
export class AndroidBundleValidatorMessages { | ||
public static AAB_NOT_SUPPORTED_BY_COMMNAND_MESSAGE = "This command does not support --aab (Android Application Bundle) parameter."; | ||
public static RUNTIME_VERSION_TOO_LOW = "Android Application Bundle (--aab) option requires NativeScript Android Runtime (tns-android) version %s and above."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOT_SUPPORTED_RUNTIME_VERSION
?
const androidRuntimeVersion = androidRuntimeInfo ? androidRuntimeInfo.version : ""; | ||
|
||
if (androidRuntimeVersion) { | ||
const shouldSkipCheck = !semver.valid(androidRuntimeVersion) && !semver.validRange(androidRuntimeVersion); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is duplicated with the code in bundle-validator-helper.ts
. So I suggest to extract a helper method
public isVersionSupported(version: string, minSupportedVersion: string): boolean {
const shouldSkipCheck = !semver.valid(version) && !semver.validRange(version);
if(shouldSkipCheck) {
return true;
}
const isVersionSupported = semver.gte(semver.coerce(version), semver.coerce(minSupportedVersion));
return isVersionSupported;
}
const isAndroidBundleSupported = helpers.isVersionSupported(androidRuntimeVersion, AndroidBundleValidatorHelper.MIN_RUNTIME_VERSION);
if (!isAndroidBundleSupported) {
this.$errors.failWithoutHelp(..);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have considered a similar approach, but it seemed strange to extract a method with such specific use case. By specific use case I mean - behavior if the version is not valid(someone might want to error in this case) and gte
(this might be adjusted by the required version, but still requires knowledge about isVersionSupported inner working).
If you insist I will extract it in separate class and extend the others, but I don't think anyone will ever use it elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might extract !semver.valid(androidRuntimeVersion) && !semver.validRange(androidRuntimeVersion);
as a helper method.
lib/commands/build.ts
Outdated
const buildResult = await this.executeCore([this.$platformsData.availablePlatforms.Android]); | ||
|
||
if (this.$options.aab) { | ||
this.$logger.info(`Your .aab file is located at: ${buildResult}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also print the apk output
lib/declarations.d.ts
Outdated
interface IAndroidBuildOptionsSettings extends IAndroidReleaseOptions, IRelease { } | ||
interface IAndroidBuildOptionsSettings extends IAndroidReleaseOptions, IRelease, IAndroidBundle { } | ||
|
||
interface IAndroidBundle { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IAndroidBundle -> IHasAndroidBundle
when this will be merged ? can't wait to test it and see the app sizes for different porpouses. hope this improve size a lot. Thanks @KristianDD |
1 similar comment
when this will be merged ? can't wait to test it and see the app sizes for different porpouses. hope this improve size a lot. Thanks @KristianDD |
this.$errors.failWithoutHelp(util.format(AndroidBundleValidatorMessages.RUNTIME_VERSION_TOO_LOW, AndroidBundleValidatorHelper.MIN_RUNTIME_VERSION)); | ||
} | ||
} | ||
if (androidRuntimeVersion && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool! I really like it. But we can make it even better.
const shouldThrowError = androidRuntimeVersion && this.isValidVersion(androidRuntimeVersion) && this.isVersionLowerThan(androidRuntimeVersion, AndroidBundleValidatorHelper.MIN_RUNTIME_VERSION);
if (shouldThrowError) { ... }
So no need to provide semver.gte
function as a param to another function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isVersionLowerThan
is actually misleading, because it does not imply for gte
comparison, but gt
comparison. I prefer sending a function to be used to compare the values. This makes the helper much more versatile for future use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- "divide and conquer" approach
isVersionLowerThan(..)
isVersionLowerOrEqualThan(..)
isVersionGreaterThan(...)
isVersionGreaterOrEqualThan(...)
If we decide to change the implementation or add additional logic to some of the above functions, the change will affect ONLY the specific function. So we will have simplification + more control over the affected parts.
compareCoerceVersions(androidRuntimeVersion, AndroidBundleValidatorHelper.MIN_RUNTIME_VERSION, semver.gte)
compareCoerceVersions(androidRuntimeVersion, AndroidBundleValidatorHelper.MIN_RUNTIME_VERSION, semver.gt)
compareCoerceVersions(androidRuntimeVersion, AndroidBundleValidatorHelper.MIN_RUNTIME_VERSION, semver.lte)
compareCoerceVersions(androidRuntimeVersion, AndroidBundleValidatorHelper.MIN_RUNTIME_VERSION, semver.lt)
If we decide to change the implementation of compareCoerceVersions
it will affect ALL the calls above.
So we will wonder "how this will affect the case when the function is called for example with semver.gt
" or Will it affect the case when passed function is semver.lte
. So it will be harder to read + less control over the affected parts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if I create a wrapper for each comparison semver
has, it will underneath use the same private method that wraps the same logic (getting the coerce of each version and invoking a function). So changing the private method will affect the same amount of places, but indirectly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rosen-vladimirov @DimitarTachev I would appreciate your input on the matter. If the majority considers it's better to wrap semver
methods I will do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer a few but simple functions. Methods like isVersionLowerThan
are more clear, simple and easy to be unit tested. It's much easier to do one thing and do it well
for such functions. In other words, I prefer sticking to simple functions till we don't need more complex scenario requiring some custom comparisons.
lib/commands/build.ts
Outdated
if (this.$options.copyTo) { | ||
this.$platformService.copyLastOutput(platform, this.$options.copyTo, buildConfig, this.$projectData); | ||
} else { | ||
this.$logger.info(`Your build result is located at: ${outputPath}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not very familiar with the CLI errors, but if you/your is not used a lot, I would recommend changing this to "The build result is located at" instead of "Your..."
lib/services/platform-service.ts
Outdated
public async validateOptions(provision: true | string, teamId: true | string, projectData: IProjectData, platform?: string): Promise<boolean> { | ||
public async validateOptions(provision: true | string, teamId: true | string, projectData: IProjectData, platform?: string, aab?: boolean): Promise<boolean> { | ||
if (platform && !this.$mobileHelper.isAndroidPlatform(platform) && aab) { | ||
this.$errors.failWithoutHelp("Option --aab is supported for Android platform only."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recommend rephrasing this to "The --aab option is supported only for the Android platform" or "The --aab option is supported only for Android builds".
@@ -27,6 +27,7 @@ General | `$ tns build android [--compileSdk <API Level>] [--key-store-path <Fil | |||
* `--copy-to` - Specifies the file path where the built `.apk` will be copied. If it points to a non-existent directory, it will be created. If the specified value is directory, the original file name will be used. | |||
* `--bundle` - Specifies that the `webpack` bundler will be used to bundle the application. | |||
* `--env.*` - Specifies additional flags that the bundler may process. May be passed multiple times. For example: `--env.uglify --env.snapshot`. | |||
* `--aab` - Specifies that the build must produce an Android App Bundle(`.aab`) file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should consider replacing "must" with "will". It sounds better to say what the command will do :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 for the texts
df65d21
to
a6dcfb9
Compare
PR Checklist
What is the current behavior?
You can't generate
.aab
file.What is the new behavior?
You can generate
.aab
file usingtns build android --aab
.Fixes/Implements/Closes #4068