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

Commit 5dfefc1

Browse files
sergey-akhalkovRichard Hua
authored andcommitted
Check that app and deployment exist before releasing an update (#399)
* command-executor: check for app and deployment exist before releasing an update * Remove catch block * Add getDeployment() mock so that unit tests work * Release commands now return rejected promises instead of throwing - do not assert exceptions are thrown during unit tests
1 parent 1bbf9a1 commit 5dfefc1

File tree

2 files changed

+150
-128
lines changed

2 files changed

+150
-128
lines changed

cli/script/command-executor.ts

Lines changed: 105 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,58 +1155,63 @@ export var release = (command: cli.IReleaseCommand): Promise<void> => {
11551155
}
11561156

11571157
export var releaseCordova = (command: cli.IReleaseCordovaCommand): Promise<void> => {
1158-
var platform: string = command.platform.toLowerCase();
1159-
var projectRoot: string = process.cwd();
1160-
var platformFolder: string = path.join(projectRoot, "platforms", platform);
1161-
var platformCordova: string = path.join(platformFolder, "cordova");
1162-
var outputFolder: string;
1163-
1164-
if (platform === "ios") {
1165-
outputFolder = path.join(platformFolder, "www");
1166-
} else if (platform === "android") {
1167-
outputFolder = path.join(platformFolder, "assets", "www");
1168-
} else {
1169-
throw new Error("Platform must be either \"ios\" or \"android\".");
1170-
}
1158+
var releaseCommand: cli.IReleaseCommand = <any>command;
1159+
// Check for app and deployment exist before releasing an update.
1160+
// This validation helps to save about 1 minute or more in case user has typed wrong app or deployment name.
1161+
return sdk.getDeployment(command.appName, command.deploymentName)
1162+
.then((): any => {
1163+
var platform: string = command.platform.toLowerCase();
1164+
var projectRoot: string = process.cwd();
1165+
var platformFolder: string = path.join(projectRoot, "platforms", platform);
1166+
var platformCordova: string = path.join(platformFolder, "cordova");
1167+
var outputFolder: string;
1168+
1169+
if (platform === "ios") {
1170+
outputFolder = path.join(platformFolder, "www");
1171+
} else if (platform === "android") {
1172+
outputFolder = path.join(platformFolder, "assets", "www");
1173+
} else {
1174+
throw new Error("Platform must be either \"ios\" or \"android\".");
1175+
}
11711176

1172-
var cordovaCommand: string = command.build ? "build" : "prepare";
1173-
var cordovaCLI: string = "cordova";
1177+
var cordovaCommand: string = command.build ? "build" : "prepare";
1178+
var cordovaCLI: string = "cordova";
11741179

1175-
// Check whether the Cordova or PhoneGap CLIs are
1176-
// installed, and if not, fail early
1177-
try {
1178-
which.sync(cordovaCLI);
1179-
} catch (e) {
1180-
try {
1181-
cordovaCLI = "phonegap";
1182-
which.sync(cordovaCLI);
1183-
} catch (e) {
1184-
throw new Error(`Unable to ${cordovaCommand} project. Please ensure that either the Cordova or PhoneGap CLI is installed.`);
1185-
}
1186-
}
1180+
// Check whether the Cordova or PhoneGap CLIs are
1181+
// installed, and if not, fail early
1182+
try {
1183+
which.sync(cordovaCLI);
1184+
} catch (e) {
1185+
try {
1186+
cordovaCLI = "phonegap";
1187+
which.sync(cordovaCLI);
1188+
} catch (e) {
1189+
throw new Error(`Unable to ${cordovaCommand} project. Please ensure that either the Cordova or PhoneGap CLI is installed.`);
1190+
}
1191+
}
11871192

1188-
log(chalk.cyan(`Running "${cordovaCLI} ${cordovaCommand}" command:\n`));
1189-
try {
1190-
execSync([cordovaCLI, cordovaCommand, platform, "--verbose"].join(" "), { stdio: "inherit" });
1191-
} catch (error) {
1192-
throw new Error(`Unable to ${cordovaCommand} project. Please ensure that the CWD represents a Cordova project and that the "${platform}" platform was added by running "${cordovaCLI} platform add ${platform}".`);
1193-
}
1193+
log(chalk.cyan(`Running "${cordovaCLI} ${cordovaCommand}" command:\n`));
1194+
try {
1195+
execSync([cordovaCLI, cordovaCommand, platform, "--verbose"].join(" "), { stdio: "inherit" });
1196+
} catch (error) {
1197+
throw new Error(`Unable to ${cordovaCommand} project. Please ensure that the CWD represents a Cordova project and that the "${platform}" platform was added by running "${cordovaCLI} platform add ${platform}".`);
1198+
}
11941199

1195-
try {
1196-
var configString: string = fs.readFileSync(path.join(projectRoot, "config.xml"), { encoding: "utf8" });
1197-
} catch (error) {
1198-
throw new Error(`Unable to find or read "config.xml" in the CWD. The "release-cordova" command must be executed in a Cordova project folder.`);
1199-
}
1200+
try {
1201+
var configString: string = fs.readFileSync(path.join(projectRoot, "config.xml"), { encoding: "utf8" });
1202+
} catch (error) {
1203+
throw new Error(`Unable to find or read "config.xml" in the CWD. The "release-cordova" command must be executed in a Cordova project folder.`);
1204+
}
12001205

1201-
var configPromise: Promise<any> = parseXml(configString);
1202-
var releaseCommand: cli.IReleaseCommand = <any>command;
1206+
var configPromise: Promise<any> = parseXml(configString);
12031207

1204-
releaseCommand.package = outputFolder;
1205-
releaseCommand.type = cli.CommandType.release;
1208+
releaseCommand.package = outputFolder;
1209+
releaseCommand.type = cli.CommandType.release;
12061210

1207-
return configPromise
1208-
.catch((err: any) => {
1209-
throw new Error(`Unable to parse "config.xml" in the CWD. Ensure that the contents of "config.xml" is valid XML.`);
1211+
return configPromise
1212+
.catch((err: any) => {
1213+
throw new Error(`Unable to parse "config.xml" in the CWD. Ensure that the contents of "config.xml" is valid XML.`);
1214+
});
12101215
})
12111216
.then((parsedConfig: any) => {
12121217
var config: any = parsedConfig.widget;
@@ -1232,65 +1237,70 @@ export var releaseReact = (command: cli.IReleaseReactCommand): Promise<void> =>
12321237
var outputFolder: string = command.outputDir || path.join(os.tmpdir(), "CodePush");
12331238
var platform: string = command.platform = command.platform.toLowerCase();
12341239
var releaseCommand: cli.IReleaseCommand = <any>command;
1235-
releaseCommand.package = outputFolder;
1236-
1237-
switch (platform) {
1238-
case "android":
1239-
case "ios":
1240-
case "windows":
1241-
if (!bundleName) {
1242-
bundleName = platform === "ios"
1243-
? "main.jsbundle"
1244-
: `index.${platform}.bundle`;
1245-
}
1240+
// Check for app and deployment exist before releasing an update.
1241+
// This validation helps to save about 1 minute or more in case user has typed wrong app or deployment name.
1242+
return sdk.getDeployment(command.appName, command.deploymentName)
1243+
.then((): any => {
1244+
releaseCommand.package = outputFolder;
1245+
1246+
switch (platform) {
1247+
case "android":
1248+
case "ios":
1249+
case "windows":
1250+
if (!bundleName) {
1251+
bundleName = platform === "ios"
1252+
? "main.jsbundle"
1253+
: `index.${platform}.bundle`;
1254+
}
12461255

1247-
break;
1248-
default:
1249-
throw new Error("Platform must be either \"android\", \"ios\" or \"windows\".");
1250-
}
1256+
break;
1257+
default:
1258+
throw new Error("Platform must be either \"android\", \"ios\" or \"windows\".");
1259+
}
12511260

1252-
try {
1253-
var projectPackageJson: any = require(path.join(process.cwd(), "package.json"));
1254-
var projectName: string = projectPackageJson.name;
1255-
if (!projectName) {
1256-
throw new Error("The \"package.json\" file in the CWD does not have the \"name\" field set.");
1257-
}
1261+
try {
1262+
var projectPackageJson: any = require(path.join(process.cwd(), "package.json"));
1263+
var projectName: string = projectPackageJson.name;
1264+
if (!projectName) {
1265+
throw new Error("The \"package.json\" file in the CWD does not have the \"name\" field set.");
1266+
}
12581267

1259-
if (!projectPackageJson.dependencies["react-native"]) {
1260-
throw new Error("The project in the CWD is not a React Native project.");
1261-
}
1262-
} catch (error) {
1263-
throw new Error("Unable to find or read \"package.json\" in the CWD. The \"release-react\" command must be executed in a React Native project folder.");
1264-
}
1268+
if (!projectPackageJson.dependencies["react-native"]) {
1269+
throw new Error("The project in the CWD is not a React Native project.");
1270+
}
1271+
} catch (error) {
1272+
throw new Error("Unable to find or read \"package.json\" in the CWD. The \"release-react\" command must be executed in a React Native project folder.");
1273+
}
12651274

1266-
if (!entryFile) {
1267-
entryFile = `index.${platform}.js`;
1268-
if (fileDoesNotExistOrIsDirectory(entryFile)) {
1269-
entryFile = "index.js";
1270-
}
1275+
if (!entryFile) {
1276+
entryFile = `index.${platform}.js`;
1277+
if (fileDoesNotExistOrIsDirectory(entryFile)) {
1278+
entryFile = "index.js";
1279+
}
12711280

1272-
if (fileDoesNotExistOrIsDirectory(entryFile)) {
1273-
throw new Error(`Entry file "index.${platform}.js" or "index.js" does not exist.`);
1274-
}
1275-
} else {
1276-
if (fileDoesNotExistOrIsDirectory(entryFile)) {
1277-
throw new Error(`Entry file "${entryFile}" does not exist.`);
1278-
}
1279-
}
1281+
if (fileDoesNotExistOrIsDirectory(entryFile)) {
1282+
throw new Error(`Entry file "index.${platform}.js" or "index.js" does not exist.`);
1283+
}
1284+
} else {
1285+
if (fileDoesNotExistOrIsDirectory(entryFile)) {
1286+
throw new Error(`Entry file "${entryFile}" does not exist.`);
1287+
}
1288+
}
12801289

1281-
if (command.appStoreVersion) {
1282-
throwForInvalidSemverRange(command.appStoreVersion);
1283-
}
1290+
if (command.appStoreVersion) {
1291+
throwForInvalidSemverRange(command.appStoreVersion);
1292+
}
12841293

1285-
var appVersionPromise: Promise<string> = command.appStoreVersion
1286-
? Q(command.appStoreVersion)
1287-
: getReactNativeProjectAppVersion(command, projectName);
1294+
var appVersionPromise: Promise<string> = command.appStoreVersion
1295+
? Q(command.appStoreVersion)
1296+
: getReactNativeProjectAppVersion(command, projectName);
12881297

1289-
if (command.outputDir) {
1290-
command.sourcemapOutput = path.join(command.outputDir, bundleName + ".map");
1291-
}
1298+
if (command.outputDir) {
1299+
command.sourcemapOutput = path.join(command.outputDir, bundleName + ".map");
1300+
}
12921301

1293-
return appVersionPromise
1302+
return appVersionPromise;
1303+
})
12941304
.then((appVersion: string) => {
12951305
releaseCommand.appStoreVersion = appVersion;
12961306
return createEmptyTempReleaseFolder(outputFolder);

0 commit comments

Comments
 (0)