Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit 4f3d807

Browse files
Merge pull request #263 from Microsoft/gradle
Adding gradle.properties support to release-react
2 parents 0d3ed6d + 07a96eb commit 4f3d807

File tree

2 files changed

+62
-24
lines changed

2 files changed

+62
-24
lines changed

cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"plist": "1.2.0",
3838
"progress": "^1.1.8",
3939
"prompt": "^0.2.14",
40+
"properties": "^1.2.1",
4041
"q": "~1.4.1",
4142
"recursive-fs": "0.1.4",
4243
"rimraf": "^2.5.1",

cli/script/command-executor.ts

Lines changed: 61 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ var packageJson = require("../package.json");
3333
var parseXml = Q.denodeify(require("xml2js").parseString);
3434
var progress = require("progress");
3535
import Promise = Q.Promise;
36+
var properties = require("properties");
3637

3738
const ACTIVE_METRICS_KEY: string = "Active";
3839
const CLI_HEADERS: Headers = {
@@ -858,14 +859,14 @@ function getPackageMetricsString(obj: Package): string {
858859
}
859860

860861
function getReactNativeProjectAppVersion(command: cli.IReleaseReactCommand, projectName: string): Promise<string> {
861-
const missingPatchVersionRegex: RegExp = /^\d+\.\d+$/;
862+
const fileExists = (file: string): boolean => {
863+
try { return fs.statSync(file).isFile() }
864+
catch (e) { return false }
865+
};
862866

867+
const isValidVersion = (version: string): boolean => !!semver.valid(version) || /^\d+\.\d+$/.test(version);
868+
863869
if (command.platform === "ios") {
864-
const fileExists = (file: string): boolean => {
865-
try { return fs.statSync(file).isFile() }
866-
catch (e) { return false }
867-
};
868-
869870
let resolvedPlistFile: string = command.plistFile;
870871
if (resolvedPlistFile) {
871872
// If a plist file path is explicitly provided, then we don't
@@ -888,7 +889,7 @@ function getReactNativeProjectAppVersion(command: cli.IReleaseReactCommand, proj
888889
throw new Error(`Unable to find either of the following plist files in order to infer your app's binary version: "${knownLocations.join("\", \"")}".`);
889890
}
890891
}
891-
console.log(resolvedPlistFile);
892+
892893
const plistContents = fs.readFileSync(resolvedPlistFile).toString();
893894

894895
try {
@@ -898,7 +899,7 @@ function getReactNativeProjectAppVersion(command: cli.IReleaseReactCommand, proj
898899
}
899900

900901
if (parsedPlist && parsedPlist.CFBundleShortVersionString) {
901-
if (semver.valid(parsedPlist.CFBundleShortVersionString) || missingPatchVersionRegex.test(parsedPlist.CFBundleShortVersionString)) {
902+
if (isValidVersion(parsedPlist.CFBundleShortVersionString)) {
902903
return Q(parsedPlist.CFBundleShortVersionString);
903904
} else {
904905
throw new Error(`The "CFBundleShortVersionString" key in the "${resolvedPlistFile}" needs to have at least a major and minor version, for example "2.0" or "1.0.3".`);
@@ -907,30 +908,66 @@ function getReactNativeProjectAppVersion(command: cli.IReleaseReactCommand, proj
907908
throw new Error(`The "CFBundleShortVersionString" key doesn't exist within the "${resolvedPlistFile}" file.`);
908909
}
909910
} else if (command.platform === "android") {
910-
var buildGradlePath: string = path.join("android", "app", "build.gradle");
911+
const buildGradlePath: string = path.join("android", "app", "build.gradle");
911912
if (fileDoesNotExistOrIsDirectory(buildGradlePath)) {
912913
throw new Error("Unable to find or read \"build.gradle\" in the \"android/app\" folder.");
913914
}
914-
915+
915916
return g2js.parseFile(buildGradlePath)
916-
.catch((err: Error) => {
917-
throw new Error("Unable to parse the \"android/app/build.gradle\" file, it could be malformed.");
917+
.catch(() => {
918+
throw new Error(`Unable to parse the "android/app/build.gradle" file. Please ensure it is a well-formed Gradle file.`);
918919
})
919920
.then((buildGradle: any) => {
920-
if (buildGradle.android && buildGradle.android.defaultConfig && buildGradle.android.defaultConfig.versionName) {
921-
if (typeof buildGradle.android.defaultConfig.versionName !== "string") {
922-
throw new Error(`The "android.defaultConfig.versionName" property value in "android/app/build.gradle" is not a valid string. If this is expected, consider using the --targetBinaryVersion option to specify the value manually.`);
923-
}
921+
if (!buildGradle.android || !buildGradle.android.defaultConfig || !buildGradle.android.defaultConfig.versionName) {
922+
throw new Error(`The "android/app/build.gradle" file doesn't specify a value for the "android.defaultConfig.versionName" property.`);
923+
}
924924

925-
var appVersion: string = buildGradle.android.defaultConfig.versionName.replace(/"/g, "").trim();
926-
if (semver.valid(appVersion) || missingPatchVersionRegex.test(appVersion)) {
927-
return appVersion;
928-
} else {
929-
throw new Error("The \"android.defaultConfig.versionName\" property in \"android/app/build.gradle\" needs to have at least a major and minor version, for example \"2.0\" or \"1.0.3\".");
930-
}
931-
} else {
932-
throw new Error("The \"android/app/build.gradle\" file does not include a value for android.defaultConfig.versionName.");
925+
if (typeof buildGradle.android.defaultConfig.versionName !== "string") {
926+
throw new Error(`The "android.defaultConfig.versionName" property value in "android/app/build.gradle" is not a valid string. If this is expected, consider using the --targetBinaryVersion option to specify the value manually.`);
933927
}
928+
929+
let appVersion: string = buildGradle.android.defaultConfig.versionName.replace(/"/g, "").trim();
930+
931+
if (isValidVersion(appVersion)) {
932+
// The versionName property is a valid semver string,
933+
// so we can safely use that and move on.
934+
return appVersion;
935+
} else if (/^\d.*/.test(appVersion)) {
936+
// The versionName property isn't a valid semver string,
937+
// but it starts with a number, and therefore, it can't
938+
// be a valid Gradle property reference.
939+
throw new Error(`The "android.defaultConfig.versionName" property in "android/app/build.gradle" needs to specify a valid semver string, containing both a major and minor version (e.g. 1.3.2, 1.1).`);
940+
}
941+
942+
// The version property isn't a valid semver string
943+
// so we assume it is a reference to a property variable.
944+
const propertyName = appVersion.replace("project.", "");
945+
const propertiesFileName = "gradle.properties";
946+
947+
const knownLocations = [
948+
path.join("android", "app", propertiesFileName),
949+
path.join("android", propertiesFileName)
950+
];
951+
952+
const propertiesFile: string = (<any>knownLocations).find(fileExists);
953+
const propertiesContent: string = fs.readFileSync(propertiesFile).toString();
954+
955+
try {
956+
const parsedProperties: any = properties.parse(propertiesContent);
957+
appVersion = parsedProperties[propertyName];
958+
} catch (e) {
959+
throw new Error(`Unable to parse "${propertiesFile}". Please ensure it is a well-formed properties file.`);
960+
}
961+
962+
if (!appVersion) {
963+
throw new Error(`No property named "${propertyName}" exists in the "${propertiesFile}" file.`);
964+
}
965+
966+
if (!isValidVersion(appVersion)) {
967+
throw new Error(`The "${propertyName}" property in "${propertiesFile}" needs to specify a valid semver string, containing both a major and minor version (e.g. 1.3.2, 1.1).`);
968+
}
969+
970+
return appVersion.toString();
934971
});
935972
} else {
936973
var appxManifestFileName: string = "Package.appxmanifest";

0 commit comments

Comments
 (0)