code-push-cli
Version:
Management CLI for the CodePush service
687 lines • 53.9 kB
JavaScript
var yargs = require("yargs");
var cli = require("../definitions/cli");
var chalk = require("chalk");
var updateNotifier = require("update-notifier");
var backslash = require("backslash");
var parseDuration = require("parse-duration");
var packageJson = require("../package.json");
var ROLLOUT_PERCENTAGE_REGEX = /^(100|[1-9][0-9]|[1-9])%?$/;
var USAGE_PREFIX = "Usage: code-push";
// Command categories are: access-key, app, release, deployment, deployment-key, login, logout, register
var isValidCommandCategory = false;
// Commands are the verb following the command category (e.g.: "add" in "app add").
var isValidCommand = false;
var wasHelpShown = false;
function showHelp(showRootDescription) {
if (!wasHelpShown) {
if (showRootDescription) {
console.log(chalk.cyan(" _____ __ " + chalk.green(" ___ __ ")));
console.log(chalk.cyan(" / ___/__ ___/ /__" + chalk.green(" / _ \\__ _____ / / ")));
console.log(chalk.cyan("/ /__/ _ \\/ _ / -_)" + chalk.green(" ___/ // (_-</ _ \\")));
console.log(chalk.cyan("\\___/\\___/\\_,_/\\__/" + chalk.green("_/ \\_,_/___/_//_/")) + " CLI v" + packageJson.version);
console.log(chalk.cyan("======================================"));
console.log("");
console.log("Mobile Center CodePush is a service that enables you to deploy mobile app updates directly to your users' devices.\n");
updateCheck();
}
yargs.showHelp();
wasHelpShown = true;
}
}
exports.showHelp = showHelp;
function updateCheck() {
var notifier = updateNotifier({ pkg: packageJson });
if (notifier.update) {
notifier.notify();
}
}
function accessKeyAdd(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " access-key " + commandName + " <accessKeyName>")
.demand(1, 1) // Require exactly one non-option arguments
.example("access-key " + commandName + " \"VSTS Integration\"", "Creates a new access key with the name \"VSTS Integration\"");
//.example("access-key " + commandName + " \"One time key\" --ttl 5m", "Creates a new access key with the name \"One time key\", which expires in 5 minutes")
//.option("ttl", { default: "60d", demand: false, description: "Duration string which specifies the amount of time that the access key should remain valid for (e.g 5m, 60d, 1y)", type: "string" });
addCommonConfiguration(yargs);
}
function accessKeyPatch(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " access-key " + commandName + " <accessKeyName>")
.demand(1, 1) // Require exactly one non-option arguments
.example("access-key " + commandName + " \"Key for build server\" --name \"Key for CI machine\"", "Renames the access key named \"Key for build server\" to \"Key for CI machine\"")
.example("access-key " + commandName + " \"Key for build server\" --ttl 7d", "Updates the access key named \"Key for build server\" to expire in 7 days")
.option("name", { default: null, demand: false, description: "Display name for the access key", type: "string" })
.option("ttl", { default: null, demand: false, description: "Duration string which specifies the amount of time that the access key should remain valid for (e.g 5m, 60d, 1y)", type: "string" });
addCommonConfiguration(yargs);
}
function accessKeyList(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " access-key " + commandName + " [options]")
.demand(0, 0)
.example("access-key " + commandName, "Lists your access keys in tabular format")
.example("access-key " + commandName + " --format json", "Lists your access keys in JSON format")
.option("format", { default: "table", demand: false, description: "Output format to display your access keys with (\"json\" or \"table\")", type: "string" });
addCommonConfiguration(yargs);
}
function accessKeyRemove(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " access-key " + commandName + " <accessKeyName>")
.demand(1, 1) // Require exactly one non-option arguments
.example("access-key " + commandName + " \"VSTS Integration\"", "Removes the \"VSTS Integration\" access key");
addCommonConfiguration(yargs);
}
function addCommonConfiguration(yargs) {
yargs.wrap(null)
.string("_") // Interpret non-hyphenated arguments as strings (e.g. an app version of '1.10').
.strict() // Validate hyphenated (named) arguments.
.fail(function (msg) { return showHelp(); }); // Suppress the default error message.
}
function appList(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " app " + commandName + " [options]")
.demand(0, 0)
.example("app " + commandName, "List your apps in tabular format")
.example("app " + commandName + " --format json", "List your apps in JSON format")
.option("format", { default: "table", demand: false, description: "Output format to display your apps with (\"json\" or \"table\")", type: "string" });
addCommonConfiguration(yargs);
}
function appRemove(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " app " + commandName + " <appName>")
.demand(1, 1) // Require exactly one non-option arguments
.example("app " + commandName + " MyApp", "Removes app \"MyApp\"");
addCommonConfiguration(yargs);
}
function listCollaborators(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " collaborator " + commandName + " <appName> [options]")
.demand(1, 1) // Require exactly one non-option arguments
.example("collaborator " + commandName + " MyApp", "Lists the collaborators for app \"MyApp\" in tabular format")
.example("collaborator " + commandName + " MyApp --format json", "Lists the collaborators for app \"MyApp\" in JSON format")
.option("format", { default: "table", demand: false, description: "Output format to display collaborators with (\"json\" or \"table\")", type: "string" });
addCommonConfiguration(yargs);
}
function removeCollaborator(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " collaborator " + commandName + " <appName> <email>")
.demand(2, 2) // Require exactly two non-option arguments
.example("collaborator " + commandName + " MyApp foo@bar.com", "Removes foo@bar.com as a collaborator from app \"MyApp\"");
addCommonConfiguration(yargs);
}
function sessionList(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " session " + commandName + " [options]")
.demand(0, 0)
.example("session " + commandName, "Lists your sessions in tabular format")
.example("session " + commandName + " --format json", "Lists your login sessions in JSON format")
.option("format", { default: "table", demand: false, description: "Output format to display your login sessions with (\"json\" or \"table\")", type: "string" });
addCommonConfiguration(yargs);
}
function sessionRemove(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " session " + commandName + " <machineName>")
.demand(1, 1) // Require exactly one non-option arguments
.example("session " + commandName + " \"John's PC\"", "Removes the existing login session from \"John's PC\"");
addCommonConfiguration(yargs);
}
function deploymentHistoryClear(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " deployment " + commandName + " <appName> <deploymentName>")
.demand(2, 2) // Require exactly two non-option arguments
.example("deployment " + commandName + " MyApp MyDeployment", "Clears the release history associated with deployment \"MyDeployment\" from app \"MyApp\"");
addCommonConfiguration(yargs);
}
function deploymentList(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " deployment " + commandName + " <appName> [options]")
.demand(1, 1) // Require exactly one non-option arguments
.example("deployment " + commandName + " MyApp", "Lists the deployments for app \"MyApp\" in tabular format")
.example("deployment " + commandName + " MyApp --format json", "Lists the deployments for app \"MyApp\" in JSON format")
.option("format", { default: "table", demand: false, description: "Output format to display your deployments with (\"json\" or \"table\")", type: "string" })
.option("displayKeys", { alias: "k", default: false, demand: false, description: "Specifies whether to display the deployment keys", type: "boolean" });
addCommonConfiguration(yargs);
}
function deploymentRemove(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " deployment " + commandName + " <appName> <deploymentName>")
.demand(2, 2) // Require exactly two non-option arguments
.example("deployment " + commandName + " MyApp MyDeployment", "Removes deployment \"MyDeployment\" from app \"MyApp\"");
addCommonConfiguration(yargs);
}
function deploymentHistory(commandName, yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " deployment " + commandName + " <appName> <deploymentName> [options]")
.demand(2, 2) // Require exactly two non-option arguments
.example("deployment " + commandName + " MyApp MyDeployment", "Displays the release history for deployment \"MyDeployment\" from app \"MyApp\" in tabular format")
.example("deployment " + commandName + " MyApp MyDeployment --format json", "Displays the release history for deployment \"MyDeployment\" from app \"MyApp\" in JSON format")
.option("format", { default: "table", demand: false, description: "Output format to display the release history with (\"json\" or \"table\")", type: "string" })
.option("displayAuthor", { alias: "a", default: false, demand: false, description: "Specifies whether to display the release author", type: "boolean" });
addCommonConfiguration(yargs);
}
var argv = yargs.usage(USAGE_PREFIX + " <command>")
.demand(1, 1) // Require exactly one non-option argument.
.command("access-key", "View and manage the access keys associated with your account", function (yargs) {
isValidCommandCategory = true;
yargs.usage(USAGE_PREFIX + " access-key <command>")
.demand(2, 2) // Require exactly two non-option arguments.
.command("add", "Create a new access key associated with your account", function (yargs) { return accessKeyAdd("add", yargs); })
.command("remove", "Remove an existing access key", function (yargs) { return accessKeyRemove("remove", yargs); })
.command("rm", "Remove an existing access key", function (yargs) { return accessKeyRemove("rm", yargs); })
.command("list", "List the access keys associated with your account", function (yargs) { return accessKeyList("list", yargs); })
.command("ls", "List the access keys associated with your account", function (yargs) { return accessKeyList("ls", yargs); })
.check(function (argv, aliases) { return isValidCommand; }); // Report unrecognized, non-hyphenated command category.
addCommonConfiguration(yargs);
})
.command("app", "View and manage your CodePush apps", function (yargs) {
isValidCommandCategory = true;
yargs.usage(USAGE_PREFIX + " app <command>")
.demand(2, 2) // Require exactly two non-option arguments.
.command("add", "Add a new app to your account", function (yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " app add <appName> <os> <platform>")
.demand(3, 3) // Require exactly three non-option arguments
.example("app add MyApp ios react-native", "Adds app \"MyApp\", indicating that it's an iOS React Native app")
.example("app add MyApp windows react-native", "Adds app \"MyApp\", indicating that it's a Windows React Native app")
.example("app add MyApp android cordova", "Adds app \"MyApp\", indicating that it's an Android Cordova app");
addCommonConfiguration(yargs);
})
.command("remove", "Remove an app from your account", function (yargs) { return appRemove("remove", yargs); })
.command("rm", "Remove an app from your account", function (yargs) { return appRemove("rm", yargs); })
.command("rename", "Rename an existing app", function (yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " app rename <currentAppName> <newAppName>")
.demand(2, 2) // Require exactly two non-option arguments
.example("app rename CurrentName NewName", "Renames app \"CurrentName\" to \"NewName\"");
addCommonConfiguration(yargs);
})
.command("list", "Lists the apps associated with your account", function (yargs) { return appList("list", yargs); })
.command("ls", "Lists the apps associated with your account", function (yargs) { return appList("ls", yargs); })
.check(function (argv, aliases) { return isValidCommand; }); // Report unrecognized, non-hyphenated command category.
addCommonConfiguration(yargs);
})
.command("collaborator", "View and manage app collaborators", function (yargs) {
isValidCommandCategory = true;
yargs.usage(USAGE_PREFIX + " collaborator <command>")
.demand(2, 2) // Require exactly two non-option arguments.
.command("add", "Add a new collaborator to an app", function (yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " collaborator add <appName> <email>")
.demand(2, 2) // Require exactly two non-option arguments
.example("collaborator add MyApp foo@bar.com", "Adds foo@bar.com as a collaborator to app \"MyApp\"");
addCommonConfiguration(yargs);
})
.command("remove", "Remove a collaborator from an app", function (yargs) { return removeCollaborator("remove", yargs); })
.command("rm", "Remove a collaborator from an app", function (yargs) { return removeCollaborator("rm", yargs); })
.command("list", "List the collaborators for an app", function (yargs) { return listCollaborators("list", yargs); })
.command("ls", "List the collaborators for an app", function (yargs) { return listCollaborators("ls", yargs); })
.check(function (argv, aliases) { return isValidCommand; }); // Report unrecognized, non-hyphenated command category.
addCommonConfiguration(yargs);
})
.command("debug", "View the CodePush debug logs for a running app", function (yargs) {
isValidCommandCategory = true;
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " debug <platform>")
.demand(1, 1) // Require exactly one non-option arguments
.example("debug android", "View the CodePush debug logs for an Android emulator or device")
.example("debug ios", "View the CodePush debug logs for the iOS simulator");
addCommonConfiguration(yargs);
})
.command("deployment", "View and manage your app deployments", function (yargs) {
isValidCommandCategory = true;
yargs.usage(USAGE_PREFIX + " deployment <command>")
.demand(2, 2) // Require exactly two non-option arguments.
.command("add", "Add a new deployment to an app", function (yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " deployment add <appName> [deploymentName]")
.demand(1, 2) // Require the app name, with deploymentName optional (either deploymentName or --default needs to be specified)
.option("default", { alias: "d", demand: false, description: "Add the default \"Staging\" and \"Production\" deployments", type: "boolean" })
.example("deployment add MyApp --default", "Adds default \"Staging\" and \"Production\" deployments to app \"MyApp\"")
.example("deployment add MyApp MyDeployment", "Adds deployment \"MyDeployment\" to app \"MyApp\"");
addCommonConfiguration(yargs);
})
.command("clear", "Clear the release history associated with a deployment", function (yargs) { return deploymentHistoryClear("clear", yargs); })
.command("remove", "Remove a deployment from an app", function (yargs) { return deploymentRemove("remove", yargs); })
.command("rm", "Remove a deployment from an app", function (yargs) { return deploymentRemove("rm", yargs); })
.command("rename", "Rename an existing deployment", function (yargs) {
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " deployment rename <appName> <currentDeploymentName> <newDeploymentName>")
.demand(3, 3) // Require exactly three non-option arguments
.example("deployment rename MyApp CurrentDeploymentName NewDeploymentName", "Renames deployment \"CurrentDeploymentName\" to \"NewDeploymentName\"");
addCommonConfiguration(yargs);
})
.command("list", "List the deployments associated with an app", function (yargs) { return deploymentList("list", yargs); })
.command("ls", "List the deployments associated with an app", function (yargs) { return deploymentList("ls", yargs); })
.command("history", "Display the release history for a deployment", function (yargs) { return deploymentHistory("history", yargs); })
.command("h", "Display the release history for a deployment", function (yargs) { return deploymentHistory("h", yargs); })
.check(function (argv, aliases) { return isValidCommand; }); // Report unrecognized, non-hyphenated command category.
addCommonConfiguration(yargs);
})
.command("link", "Link an additional authentication provider (e.g. GitHub) to an existing Mobile Center account", function (yargs) {
isValidCommandCategory = true;
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " link")
.demand(0, 1) //set 'max' to one to allow usage of serverUrl undocument parameter for testing
.example("link", "Links an account on the Mobile Center server")
.check(function (argv, aliases) { return isValidCommand; }); // Report unrecognized, non-hyphenated command category.
addCommonConfiguration(yargs);
})
.command("login", "Authenticate in order to begin managing your apps", function (yargs) {
isValidCommandCategory = true;
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " login [options]")
.demand(0, 1) //set 'max' to one to allow usage of serverUrl undocument parameter for testing
.example("login", "Logs in to the Mobile Center server")
.example("login --accessKey mykey", "Logs in on behalf of the user who owns and created the access key \"mykey\"")
.example("login --proxy http://someproxy.com:455", "Logs in with the specified proxy url")
.option("accessKey", { alias: "key", default: null, demand: false, description: "Access key to authenticate against the Mobile Center server with, instead of providing your username and password credentials", type: "string" })
.option("proxy", { default: null, demand: false, description: "URL of the proxy server to use", type: "string" })
.option("noProxy", { default: false, demand: false, description: "Bypass the system-wide proxy settings", type: "boolean" })
.check(function (argv, aliases) { return isValidCommand; }); // Report unrecognized, non-hyphenated command category.
addCommonConfiguration(yargs);
})
.command("logout", "Log out of the current session", function (yargs) {
isValidCommandCategory = true;
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " logout")
.demand(0, 0)
.example("logout", "Logs out and ends your current session");
addCommonConfiguration(yargs);
})
.command("patch", "Update the metadata for an existing release", function (yargs) {
yargs.usage(USAGE_PREFIX + " patch <appName> <deploymentName> [options]")
.demand(2, 2) // Require exactly two non-option arguments
.example("patch MyApp Production --des \"Updated description\" -r 50%", "Updates the description of the latest release for \"MyApp\" app's \"Production\" deployment and updates the rollout value to 50%")
.example("patch MyApp Production -l v3 --des \"Updated description for v3\"", "Updates the description of the release with label v3 for \"MyApp\" app's \"Production\" deployment")
.option("label", { alias: "l", default: null, demand: false, description: "Label of the release to update. Defaults to the latest release within the specified deployment", type: "string" })
.option("description", { alias: "des", default: null, demand: false, description: "Description of the changes made to the app with this release", type: "string" })
.option("disabled", { alias: "x", default: null, demand: false, description: "Specifies whether this release should be immediately downloadable", type: "boolean" })
.option("mandatory", { alias: "m", default: null, demand: false, description: "Specifies whether this release should be considered mandatory", type: "boolean" })
.option("rollout", { alias: "r", default: null, demand: false, description: "Percentage of users this release should be immediately available to. This attribute can only be increased from the current value.", type: "string" })
.option("targetBinaryVersion", { alias: "t", default: null, demand: false, description: "Semver expression that specifies the binary app version(s) this release is targeting (e.g. 1.1.0, ~1.2.3).", type: "string" })
.check(function (argv, aliases) { return isValidRollout(argv); });
addCommonConfiguration(yargs);
})
.command("promote", "Promote the latest release from one app deployment to another", function (yargs) {
yargs.usage(USAGE_PREFIX + " promote <appName> <sourceDeploymentName> <destDeploymentName> [options]")
.demand(3, 3) // Require exactly three non-option arguments
.example("promote MyApp Staging Production", "Promotes the latest release within the \"Staging\" deployment of \"MyApp\" to \"Production\"")
.example("promote MyApp Staging Production --des \"Production rollout\" -r 25", "Promotes the latest release within the \"Staging\" deployment of \"MyApp\" to \"Production\", with an updated description, and targeting only 25% of the users")
.option("description", { alias: "des", default: null, demand: false, description: "Description of the changes made to the app with this release. If omitted, the description from the release being promoted will be used.", type: "string" })
.option("label", { alias: "l", default: null, demand: false, description: "Label of the source release that will be taken. If omitted, the latest release being promoted will be used.", type: "string" })
.option("disabled", { alias: "x", default: null, demand: false, description: "Specifies whether this release should be immediately downloadable. If omitted, the disabled attribute from the release being promoted will be used.", type: "boolean" })
.option("mandatory", { alias: "m", default: null, demand: false, description: "Specifies whether this release should be considered mandatory. If omitted, the mandatory property from the release being promoted will be used.", type: "boolean" })
.option("noDuplicateReleaseError", { default: false, demand: false, description: "When this flag is set, promoting a package that is identical to the latest release on the target deployment will produce a warning instead of an error", type: "boolean" })
.option("rollout", { alias: "r", default: "100%", demand: false, description: "Percentage of users this update should be immediately available to", type: "string" })
.option("targetBinaryVersion", { alias: "t", default: null, demand: false, description: "Semver expression that specifies the binary app version(s) this release is targeting (e.g. 1.1.0, ~1.2.3). If omitted, the target binary version property from the release being promoted will be used.", type: "string" })
.check(function (argv, aliases) { return isValidRollout(argv); });
addCommonConfiguration(yargs);
})
.command("register", "Register a new AppCenter account", function (yargs) {
isValidCommandCategory = true;
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " register")
.demand(0, 1) //set 'max' to one to allow usage of serverUrl undocument parameter for testing
.example("register", "Registers a new Mobile Center account")
.example("register --proxy http://someproxy.com:455", "Registers with the specified proxy url")
.option("proxy", { default: null, demand: false, description: "URL of the proxy server to use", type: "string" })
.option("noProxy", { default: false, demand: false, description: "Bypass the system-wide proxy settings", type: "boolean" })
.check(function (argv, aliases) { return isValidCommand; }); // Report unrecognized, non-hyphenated command category.
addCommonConfiguration(yargs);
})
.command("release", "Release an update to an app deployment", function (yargs) {
yargs.usage(USAGE_PREFIX + " release <appName> <updateContentsPath> <targetBinaryVersion> [options]")
.demand(3, 3) // Require exactly three non-option arguments.
.example("release MyApp app.js \"*\"", "Releases the \"app.js\" file to the \"MyApp\" app's \"Staging\" deployment, targeting any binary version using the \"*\" wildcard range syntax.")
.example("release MyApp ./platforms/ios/www 1.0.3 -d Production -k ~/.ssh/codepush_rsa", "Releases the \"./platforms/ios/www\" folder and all its contents to the \"MyApp\" app's \"Production\" deployment, targeting only the 1.0.3 binary version and signed with the \"codepush_rsa\" private key")
.example("release MyApp ./platforms/ios/www 1.0.3 -d Production -r 20", "Releases the \"./platforms/ios/www\" folder and all its contents to the \"MyApp\" app's \"Production\" deployment, targeting the 1.0.3 binary version and rolling out to about 20% of the users")
.option("deploymentName", { alias: "d", default: "Staging", demand: false, description: "Deployment to release the update to", type: "string" })
.option("description", { alias: "des", default: null, demand: false, description: "Description of the changes made to the app in this release", type: "string" })
.option("disabled", { alias: "x", default: false, demand: false, description: "Specifies whether this release should be immediately downloadable", type: "boolean" })
.option("mandatory", { alias: "m", default: false, demand: false, description: "Specifies whether this release should be considered mandatory", type: "boolean" })
.option("privateKeyPath", { alias: "k", default: false, demand: false, description: "Specifies the location of a RSA private key to sign the release with", type: "string" })
.option("noDuplicateReleaseError", { default: false, demand: false, description: "When this flag is set, releasing a package that is identical to the latest release will produce a warning instead of an error", type: "boolean" })
.option("rollout", { alias: "r", default: "100%", demand: false, description: "Percentage of users this release should be available to", type: "string" })
.check(function (argv, aliases) { return checkValidReleaseOptions(argv); });
addCommonConfiguration(yargs);
})
.command("release-cordova", "Release a Cordova update to an app deployment", function (yargs) {
yargs.usage(USAGE_PREFIX + " release-cordova <appName> <platform> [options]")
.demand(2, 2) // Require exactly two non-option arguments
.example("release-cordova MyApp ios", "Releases the Cordova iOS project in the current working directory to the \"MyApp\" app's \"Staging\" deployment")
.example("release-cordova MyApp android -d Production", "Releases the Cordova Android project in the current working directory to the \"MyApp\" app's \"Production\" deployment")
.option("build", { alias: "b", default: false, demand: false, description: "Invoke \"cordova build\" instead of \"cordova prepare\"", type: "boolean" })
.option("isReleaseBuildType", { alias: "rb", default: false, demand: false, description: "If \"build\" option is true specifies whether perform a release build", type: "boolean" })
.option("deploymentName", { alias: "d", default: "Staging", demand: false, description: "Deployment to release the update to", type: "string" })
.option("description", { alias: "des", default: null, demand: false, description: "Description of the changes made to the app in this release", type: "string" })
.option("disabled", { alias: "x", default: false, demand: false, description: "Specifies whether this release should be immediately downloadable", type: "boolean" })
.option("mandatory", { alias: "m", default: false, demand: false, description: "Specifies whether this release should be considered mandatory", type: "boolean" })
.option("privateKeyPath", { alias: "k", default: false, demand: false, description: "Specifies the location of a RSA private key to sign the release with", type: "string" })
.option("noDuplicateReleaseError", { default: false, demand: false, description: "When this flag is set, releasing a package that is identical to the latest release will produce a warning instead of an error", type: "boolean" })
.option("rollout", { alias: "r", default: "100%", demand: false, description: "Percentage of users this release should be immediately available to", type: "string" })
.option("targetBinaryVersion", { alias: "t", default: null, demand: false, description: "Semver expression that specifies the binary app version(s) this release is targeting (e.g. 1.1.0, ~1.2.3). If omitted, the release will target the exact version specified in the config.xml file.", type: "string" })
.check(function (argv, aliases) { return checkValidReleaseOptions(argv); });
addCommonConfiguration(yargs);
})
.command("release-react", "Release a React Native update to an app deployment", function (yargs) {
yargs.usage(USAGE_PREFIX + " release-react <appName> <platform> [options]")
.demand(2, 2) // Require exactly two non-option arguments
.example("release-react MyApp ios", "Releases the React Native iOS project in the current working directory to the \"MyApp\" app's \"Staging\" deployment")
.example("release-react MyApp android -d Production -k ~/.ssh/codepush_rsa", "Releases the React Native Android project in the current working directory to the \"MyApp\" app's \"Production\" deployment, signed with the \"codepush_rsa\" private key")
.example("release-react MyApp windows --dev", "Releases the development bundle of the React Native Windows project in the current working directory to the \"MyApp\" app's \"Staging\" deployment")
.option("bundleName", { alias: "b", default: null, demand: false, description: "Name of the generated JS bundle file. If unspecified, the standard bundle name will be used, depending on the specified platform: \"main.jsbundle\" (iOS), \"index.android.bundle\" (Android) or \"index.windows.bundle\" (Windows)", type: "string" })
.option("deploymentName", { alias: "d", default: "Staging", demand: false, description: "Deployment to release the update to", type: "string" })
.option("description", { alias: "des", default: null, demand: false, description: "Description of the changes made to the app with this release", type: "string" })
.option("development", { alias: "dev", default: false, demand: false, description: "Specifies whether to generate a dev or release build", type: "boolean" })
.option("disabled", { alias: "x", default: false, demand: false, description: "Specifies whether this release should be immediately downloadable", type: "boolean" })
.option("entryFile", { alias: "e", default: null, demand: false, description: "Path to the app's entry Javascript file. If omitted, \"index.<platform>.js\" and then \"index.js\" will be used (if they exist)", type: "string" })
.option("gradleFile", { alias: "g", default: null, demand: false, description: "Path to the gradle file which specifies the binary version you want to target this release at (android only)." })
.option("mandatory", { alias: "m", default: false, demand: false, description: "Specifies whether this release should be considered mandatory", type: "boolean" })
.option("noDuplicateReleaseError", { default: false, demand: false, description: "When this flag is set, releasing a package that is identical to the latest release will produce a warning instead of an error", type: "boolean" })
.option("plistFile", { alias: "p", default: null, demand: false, description: "Path to the plist file which specifies the binary version you want to target this release at (iOS only)." })
.option("plistFilePrefix", { alias: "pre", default: null, demand: false, description: "Prefix to append to the file name when attempting to find your app's Info.plist file (iOS only)." })
.option("rollout", { alias: "r", default: "100%", demand: false, description: "Percentage of users this release should be immediately available to", type: "string" })
.option("privateKeyPath", { alias: "k", default: false, demand: false, description: "Specifies the location of a RSA private key to sign the release with", type: "string" })
.option("sourcemapOutput", { alias: "s", default: null, demand: false, description: "Path to where the sourcemap for the resulting bundle should be written. If omitted, a sourcemap will not be generated.", type: "string" })
.option("targetBinaryVersion", { alias: "t", default: null, demand: false, description: "Semver expression that specifies the binary app version(s) this release is targeting (e.g. 1.1.0, ~1.2.3). If omitted, the release will target the exact version specified in the \"Info.plist\" (iOS), \"build.gradle\" (Android) or \"Package.appxmanifest\" (Windows) files.", type: "string" })
.option("outputDir", { alias: "o", default: null, demand: false, description: "Path to where the bundle and sourcemap should be written. If omitted, a bundle and sourcemap will not be written.", type: "string" })
.option("config", { alias: "c", default: null, demand: false, description: "Path to the React Native CLI configuration file", type: "string" })
.check(function (argv, aliases) { return checkValidReleaseOptions(argv); });
addCommonConfiguration(yargs);
})
.command("rollback", "Rollback the latest release for an app deployment", function (yargs) {
yargs.usage(USAGE_PREFIX + " rollback <appName> <deploymentName> [options]")
.demand(2, 2) // Require exactly two non-option arguments
.example("rollback MyApp Production", "Performs a rollback on the \"Production\" deployment of \"MyApp\"")
.example("rollback MyApp Production --targetRelease v4", "Performs a rollback on the \"Production\" deployment of \"MyApp\" to the v4 release")
.option("targetRelease", { alias: "r", default: null, demand: false, description: "Label of the release to roll the specified deployment back to (e.g. v4). If omitted, the deployment will roll back to the previous release.", type: "string" });
addCommonConfiguration(yargs);
})
.command("whoami", "Display the account info for the current login session", function (yargs) {
isValidCommandCategory = true;
isValidCommand = true;
yargs.usage(USAGE_PREFIX + " whoami")
.demand(0, 0)
.example("whoami", "Display the account info for the current login session");
addCommonConfiguration(yargs);
})
.alias("v", "version")
.version(packageJson.version)
.wrap(null)
.strict() // Validate hyphenated (named) arguments.
.check(function (argv, aliases) { return isValidCommandCategory; }) // Report unrecognized, non-hyphenated command category.
.fail(function (msg) { return showHelp(true); }) // Suppress the default error message.
.argv;
function createCommand() {
var cmd;
if (!wasHelpShown && argv._ && argv._.length > 0) {
// Create a command object
var arg0 = argv._[0];
var arg1 = argv._[1];
var arg2 = argv._[2];
var arg3 = argv._[3];
var arg4 = argv._[4];
switch (arg0) {
case "access-key":
switch (arg1) {
case "add":
if (arg2) {
cmd = { type: cli.CommandType.accessKeyAdd };
var accessKeyAddCmd = cmd;
accessKeyAddCmd.name = arg2;
/*
var ttlOption: string = argv["ttl"];
if (isDefined(ttlOption)) {
accessKeyAddCmd.ttl = parseDurationMilliseconds(ttlOption);
}
*/
// Mobile Center access keys never expire, so this setting doesn't matter (it just needs to be something)
accessKeyAddCmd.ttl = parseDurationMilliseconds("60d");
}
break;
case "patch":
if (arg2) {
cmd = { type: cli.CommandType.accessKeyPatch };
var accessKeyPatchCmd = cmd;
accessKeyPatchCmd.oldName = arg2;
var newNameOption = argv["name"];
var ttlOption = argv["ttl"];
if (isDefined(newNameOption)) {
accessKeyPatchCmd.newName = newNameOption;
}
if (isDefined(ttlOption)) {
accessKeyPatchCmd.ttl = parseDurationMilliseconds(ttlOption);
}
}
break;
case "list":
case "ls":
cmd = { type: cli.CommandType.accessKeyList };
cmd.format = argv["format"];
break;
case "remove":
case "rm":
if (arg2) {
cmd = { type: cli.CommandType.accessKeyRemove };
cmd.accessKey = arg2;
}
break;
}
break;
case "app":
switch (arg1) {
case "add":
if (arg2) {
cmd = { type: cli.CommandType.appAdd };
var appAddCommand = cmd;
appAddCommand.appName = arg2;
appAddCommand.os = arg3;
appAddCommand.platform = arg4;
}
break;
case "list":
case "ls":
cmd = { type: cli.CommandType.appList };
cmd.format = argv["format"];
break;
case "remove":
case "rm":
if (arg2) {
cmd = { type: cli.CommandType.appRemove };
cmd.appName = arg2;
}
break;
case "rename":
if (arg2 && arg3) {
cmd = { type: cli.CommandType.appRename };
var appRenameCommand = cmd;
appRenameCommand.currentAppName = arg2;
appRenameCommand.newAppName = arg3;
}
break;
case "transfer":
if (arg2 && arg3) {
cmd = { type: cli.CommandType.appTransfer };
var appTransferCommand = cmd;
appTransferCommand.appName = arg2;
appTransferCommand.email = arg3;
}
break;
}
break;
case "collaborator":
switch (arg1) {
case "add":
if (arg2 && arg3) {
cmd = { type: cli.CommandType.collaboratorAdd };
cmd.appName = arg2;
cmd.email = arg3;
}
break;
case "list":
case "ls":
if (arg2) {
cmd = { type: cli.CommandType.collaboratorList };
cmd.appName = arg2;
cmd.format = argv["format"];
}
break;
case "remove":
case "rm":
if (arg2 && arg3) {
cmd = { type: cli.CommandType.collaboratorRemove };
cmd.appName = arg2;
cmd.email = arg3;
}
break;
}
break;
case "debug":
cmd = {
type: cli.CommandType.debug,
platform: arg1
};
break;
case "deployment":
switch (arg1) {
case "add":
if (arg2 && (arg3 || argv["default"])) {
cmd = { type: cli.CommandType.deploymentAdd };
var deploymentAddCommand = cmd;
deploymentAddCommand.appName = arg2;
deploymentAddCommand.deploymentName = arg3;
deploymentAddCommand.default = argv["default"];
}
break;
case "clear":
if (arg2 && arg3) {
cmd = { type: cli.CommandType.deploymentHistoryClear };
var deploymentHistoryClearCommand = cmd;
deploymentHistoryClearCommand.appName = arg2;
deploymentHistoryClearCommand.deploymentName = arg3;
}
break;
case "list":
case "ls":
if (arg2) {
cmd = { type: cli.CommandType.deploymentList };
var deploymentListCommand = cmd;
deploymentListCommand.appName = arg2;
deploymentListCommand.format = argv["format"];
deploymentListCommand.displayKeys = argv["displayKeys"];
}
break;
case "remove":
case "rm":
if (arg2 && arg3) {
cmd = { type: cli.CommandType.deploymentRemove };
var deploymentRemoveCommand = cmd;
deploymentRemoveCommand.appName = arg2;
deploymentRemoveCommand.deploymentName = arg3;
}
break;
case "rename":
if (arg2 && arg3 && arg4) {
cmd = { type: cli.CommandType.deploymentRename };
var deploymentRenameCommand = cmd;
deploymentRenameCommand.appName = arg2;
deploymentRenameCommand.currentDeploymentName = arg3;
deploymentRenameCommand.newDeploymentName = arg4;
}
break;
case "history":
case "h":
if (arg2 && arg3) {
cmd = { type: cli.CommandType.deploymentHistory };
var deploymentHistoryCommand = cmd;
deploymentHistoryCommand.appName = arg2;
deploymentHistoryCommand.deploymentName = arg3;
deploymentHistoryCommand.format = argv["format"];
deploymentHistoryCommand.displayAuthor = argv["displayAuthor"];
}
break;
}
break;
case "link":
cmd = { type: cli.CommandType.link, serverUrl: getServerUrl(arg1) };
break;
case "login":
cmd = { type: cli.CommandType.login };
var loginCommand = cmd;
loginCommand.serverUrl = getServerUrl(arg1);
loginCommand.accessKey = argv["accessKey"];
loginCommand.proxy = argv["proxy"];
loginCommand.noProxy = argv["noProxy"];
break;
case "logout":
cmd = { type: cli.CommandType.logout };
break;
case "patch":
if (arg1 && arg2) {
cmd = { type: cli.CommandType.patch };
var patchCommand = cmd;
patchCommand.appName = arg1;
patchCommand.deploymentName = arg2;
patchCommand.label = argv["label"];
// Description must be set to null to indicate that it is not being patched.
patchCommand.description = argv["description"] ? backslash(argv["description"]) : null;
patchCommand.disabled = argv["disabled"];
patchCommand.mandatory = argv["mandatory"];
patchCommand.rollout = getRolloutValue(argv["rollout"]);
patchCommand.appStoreVersion = argv["targetBinaryVersion"];
}
break;
case "promote":
if (arg1 && arg2 && arg3) {
cmd = { type: cli.CommandType.promote };
var deploymentPromoteCommand = cmd;
deploymentPromoteCommand.appName = arg1;
deploymentPromoteCommand.sourceDeploymentName = arg2;
deploymentPromoteCommand.destDeploymentName = arg3;
deploymentPromoteCommand.description = argv["description"] ? backslash(argv["description"]) : "";
deploymentPromoteCommand.label = argv["label"];
deploymentPromoteCommand.disabled = argv["disabled"];
deploymentPromoteCommand.mandatory = argv["mandatory"];
deploymentPromoteCommand.noDuplicateReleaseError = argv["noDuplicateReleaseError"];
deploymentPromoteCommand.rollout = getRolloutValue(argv["rollout"]);
deploymentPromoteCommand.appStoreVersion = argv["targetBinaryVersion"];
}
break;
case "register":
cmd = { type: cli.CommandType.register };
var registerCommand = cmd;
registerCommand.serverUrl = getServerUrl(arg1);
registerCommand.proxy = argv["proxy"];
registerCommand.noProxy = argv["noProxy"];
break;
case "release":
if (arg1 && arg2 && arg3) {
cmd = { type: cli.CommandType.release };
var releaseCommand = cmd;
releaseCommand.appName = arg1;
releaseCommand.package = arg2;
releaseCommand.appStoreVersion = arg3;
releaseCommand.deploymentName = argv["deploymentName"];
releaseCommand.description = argv["description"] ? backslash(argv["description"]) : "";
releaseCommand.disabled = argv["disabled"];
releaseCommand.mandatory = argv["mandatory"];
releaseCommand.noDuplicateReleaseError = argv["noDuplicateReleaseError"];
releaseCommand.rollout = getRolloutValue(argv["rollout"]);
releaseCommand.privateKeyPath = argv["privateKeyPath"];
}
break;
case "release-cordova":
if (arg1 && arg2) {
cmd = { type: cli.CommandType.releaseCordova };
var releaseCordovaCommand = cmd;
releaseCordovaCommand.appName = arg1;
releaseCordovaCommand.platform = arg2;
releaseCordovaCommand.build = argv["build"];
releaseCordovaCommand.deploymentName = argv["deploymentName"];
releaseCordovaCommand.description = argv["description"] ? backslash(argv["description"]) : "";
releaseCordovaCommand.disabled = argv["disabled"];
releaseCordovaCommand.mandatory = argv["mandatory"];
releaseCordovaCommand.noDuplicateReleaseError = argv["noDuplicateReleaseError"];
releaseCordovaCommand.rollout = getRolloutValue(argv["rollout"]);
releaseCordovaCommand.appStoreVersion = argv["targetBinaryVersion"];
releaseCordovaCommand.isReleaseBuildType = argv["isReleaseBuildType"];
releaseCor