diff --git a/.azurepipelines/build-code-push-1es.yml b/.azurepipelines/build-code-push-1es.yml new file mode 100644 index 00000000..b5051b82 --- /dev/null +++ b/.azurepipelines/build-code-push-1es.yml @@ -0,0 +1,102 @@ +trigger: +- master + +pr: +- master + +resources: + repositories: + - repository: 1ESPipelineTemplates + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release +name: $(Build.SourceBranchName)_$(date:yyyyMMdd)$(rev:.r) + +extends: + ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}: + template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates + ${{ else }}: + template: v1/1ES.Unofficial.PipelineTemplate.yml@1ESPipelineTemplates + parameters: + pool: + name: 1ES-PT-CBL-Mariner-2.0-Gen2 + os: linux + customBuildTags: + - ES365AIMigrationTooling-BulkMigrated + sdl: + sourceAnalysisPool: 1ES-PT-Windows-2022 + stages: + - stage: Stage + jobs: + - job: HostJob + templateContext: + outputs: + - output: pipelineArtifact + displayName: "Publish Artifact: artifacts" + path: '$(Build.ArtifactStagingDirectory)/npm' + artifactName: npm + + steps: + - task: NodeTool@0 + inputs: + versionSpec: '14.x' + displayName: 'Install Node.js' + + - script: | + npm pack + npm install -g code-push*.tgz + displayName: 'Package code-push' + workingDirectory: $(Build.SourcesDirectory) + + - task: DeleteFiles@1 + inputs: + contents: node_modules + displayName: 'Delete node_modules' + + - task: ArchiveFiles@2 + inputs: + rootFolderOrFile: '$(Build.SourcesDirectory)' + includeRootFolder: false + archiveType: 'tar' + archiveFile: '$(Build.ArtifactStagingDirectory)/npm/$(Build.BuildId).tgz' + replaceExistingArchive: true + verbose: true + displayName: 'Prepare npm artifact' + + - stage: APIScan + dependsOn: Stage + pool: + name: 1ES-PT-Windows-2022 + os: windows + variables: + "agent.source.skip": true + jobs: + - job: APIScan + steps: + - task: DownloadPipelineArtifact@2 + displayName: Download Pipeline Artifacts for APIScan + inputs: + artifactName: npm + targetPath: '$(Agent.BuildDirectory)/npm' + - task: ExtractFiles@1 + inputs: + archiveFilePatterns: '$(Agent.BuildDirectory)/npm/*.tgz' + destinationFolder: '$(Agent.BuildDirectory)/npm_extracted' + - task: AzureKeyVault@2 + inputs: + azureSubscription: 'AC - Dev Infra & Build Pool' + KeyVaultName: 'mobile-center-sdk' + SecretsFilter: 'appcenter-sdk-managed-identity-clientid' + RunAsPreJob: false + - task: APIScan@2 + displayName: 'Run APIScan' + inputs: + softwareFolder: '$(Agent.BuildDirectory)\npm_extracted' + softwareName: 'code-push' + softwareVersionNum: '$(Build.BuildId)' + isLargeApp: false + toolVersion: 'Latest' + verbosityLevel: verbose + condition: and(succeeded(), ne(variables['DisableAPIScan'], 'true')) + env: + AzureServicesAuthConnectionString: 'runAs=App;AppId=$(appcenter-sdk-managed-identity-clientid)' \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..ba411809 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @microsoft/appcenter-fte diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 9c7fe28e..fa9037ba 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -2,5 +2,4 @@ Thanks so much for filing an issue or feature request! We will address it as soo 1. This repository is for the CodePush CLI and management SDK. For issues relating to the CodePush client SDK's, please see: * react-native-code-push: https://github.com/Microsoft/react-native-code-push - * cordova-plugin-code-push: https://github.com/Microsoft/cordova-plugin-code-push 2. In your description, please include the version of `code-push-cli` or `code-push` that you are using. diff --git a/.github/policies/resourceManagement.yml b/.github/policies/resourceManagement.yml new file mode 100644 index 00000000..9fc1c5e2 --- /dev/null +++ b/.github/policies/resourceManagement.yml @@ -0,0 +1,64 @@ +id: +name: GitOps.PullRequestIssueManagement +description: GitOps.PullRequestIssueManagement primitive +owner: +resource: repository +disabled: false +where: +configuration: + resourceManagementConfiguration: + scheduledSearches: + - description: + frequencies: + - hourly: + hour: 4 + filters: + - isOpen + - isNotLabeledWith: + label: bug + - isNotLabeledWith: + label: security + - isNotLabeledWith: + label: Stale + - isNotLabeledWith: + label: do not close + - noActivitySince: + days: 60 + - isIssue + - isNotAssigned + actions: + - addLabel: + label: Stale + - addReply: + reply: This issue has been automatically marked as stale because it has not had any activity for 60 days. It will be closed if no further activity occurs within 15 days of this comment. + - description: + frequencies: + - hourly: + hour: 6 + filters: + - isOpen + - isIssue + - hasLabel: + label: Stale + - isNotLabeledWith: + label: bug + - isNotLabeledWith: + label: do not close + - isNotAssigned + - noActivitySince: + days: 15 + actions: + - addReply: + reply: This issue will now be closed because it hasn't had any activity for 15 days after stale. Please feel free to open a new issue if you still have a question/issue or suggestion. + - closeIssue + eventResponderTasks: + - if: + - payloadType: Issue_Comment + - hasLabel: + label: Stale + then: + - removeLabel: + label: Stale + description: +onFailure: +onSuccess: diff --git a/.github/scripts/check-for-declaration.ts b/.github/scripts/check-for-declaration.ts new file mode 100755 index 00000000..46c34a93 --- /dev/null +++ b/.github/scripts/check-for-declaration.ts @@ -0,0 +1,45 @@ +import fs from "fs"; +import path from "path"; + +type ResultType = { + js : Record + ts : Record +} + +const result: ResultType = {js:{} , ts:{}} + +const readThroughDirectory = (directory: string): void => { + const __directoryPath = directory + const files = fs.readdirSync(__directoryPath); + files.forEach((file) => { + const filePath = path.join(__directoryPath, file); + const stats = fs.statSync(filePath); + if (stats.isDirectory()) { + readThroughDirectory(filePath); + return + } + + if(filePath.endsWith('.js')){ + const name = filePath.split('.') + name.pop() + result.js[name.join('.')] = true + } + + if(filePath.endsWith('.d.ts')){ + const name = filePath.split('.') + name.pop() + name.pop() + result.ts[name.join('.')] = true + } + + }); + + Object.keys(result.js).forEach(file => { + if(!result.ts[file]){ + throw new Error(`Declaration File Missing for ${file}.js`) + } + }) + +}; + +readThroughDirectory(path.join(process.env.INIT_CWD ?? '', './bin')) \ No newline at end of file diff --git a/.github/workflows/code-push-ci.yml b/.github/workflows/code-push-ci.yml new file mode 100644 index 00000000..aef064ce --- /dev/null +++ b/.github/workflows/code-push-ci.yml @@ -0,0 +1,24 @@ +name: Сode-push CI + +on: + pull_request: + branches: + - master + +jobs: + Run-tests: + name: Test code-push-sdk + runs-on: macos-13 + steps: + - name: Checkout + uses: actions/checkout@v1 + - name: Setup NodeJs + uses: actions/setup-node@v1 + with: + node-version: "14.x" + - name: Setup dependencies + run: npm run setup + - name: Build + run: npm run build + - name: Run tests + run: npm run test diff --git a/.gitignore b/.gitignore index 8acd4259..cbd13c11 100644 --- a/.gitignore +++ b/.gitignore @@ -29,8 +29,6 @@ node_modules # Build specific exclusions bin/ -definitions/external/ -definitions/generated/ # Environment variables *.env diff --git a/sdk/.npmignore b/.npmignore similarity index 72% rename from sdk/.npmignore rename to .npmignore index c4a04633..9a646a1e 100644 --- a/sdk/.npmignore +++ b/.npmignore @@ -1,4 +1,4 @@ .npmignore .gitignore node_modules/* -definitions/* +test/* diff --git a/.vscode/launch.json b/.vscode/launch.json index a812dc71..6e6f1f86 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,33 +1,23 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { - "name": "Run CLI", + "name": "Tests", "type": "node", "request": "launch", - "protocol": "inspector", - "program": "${workspaceRoot}/cli/bin/script/cli.js", + "preLaunchTask": "Build", + "runtimeExecutable": "npm", + "runtimeArgs": [ + "run", + "test:debugger" + ], + "port": 9229, "stopOnEntry": false, "sourceMaps": true, - "preLaunchTask": "gulp: build", - "args": [ - "--info" - ] - }, - { - "name": "Unit Test", - "type": "node", - "request": "launch", - "protocol": "inspector", - "program": "${workspaceRoot}/node_modules/gulp/bin/gulp.js", - "stopOnEntry": false, - "sourceMaps": true, - "args": [ - "test" - ] + "console": "internalConsole", + "internalConsoleOptions": "openOnSessionStart", + "autoAttachChildProcesses": true, + "timeout": 100000 } ] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 8dff0d56..9bbf37f4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,4 @@ // Place your settings in this file to overwrite default and user settings. { - "files.exclude": { - "cli/bin/": true, - "sdk/bin/": true - } + "typescript.tsdk": "node_modules/typescript/lib" } diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..242cc3e3 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,21 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "label": "Build", + "command": "npm", + "args": [ + "run", + "build" + ], + "presentation": { + "echo": false, + "focus": false + }, + "problemMatcher": [ + "$tsc" + ] + } + ] +} diff --git a/Gulpfile.js b/Gulpfile.js deleted file mode 100644 index 3e7558e3..00000000 --- a/Gulpfile.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; - -var gulp = require("gulp"); -var plugins = require("gulp-load-plugins")(); - -require("require-all")(__dirname + "/gulp"); diff --git a/README.md b/README.md index f2272d69..8c839a73 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,39 @@ +# Archiving this repository + +Visual Studio App Center was retired on March 31, 2025, except for its Analytics and Diagnostics features. You can learn more about the retirement and the Analytics and Diagnostics extension [here](https://aka.ms/appcenter/retire). CodePush, along with other App Center features, was also retired on March 31, 2025. Consequently, we are archiving this repository. + +--- + [![appcenterbanner](https://user-images.githubusercontent.com/31293287/32969262-3cc5d48a-cb99-11e7-91bf-fa57c67a371c.png)](http://microsoft.github.io/code-push/) -# CodePush +#### [Sign up With App Center](https://appcenter.ms/signup?utm_source=CodePush&utm_medium=Azure) to use CodePush + +## CodePush SDK -[CodePush](https://microsoft.github.io/code-push) is a cloud service that enables Cordova and React Native developers to deploy mobile app updates directly to their users' devices. It works by acting as a central repository that developers can publish updates to (JS, HTML, CSS and images), and that apps can query for updates from (using provided client SDKs for [Cordova](https://github.com/Microsoft/cordova-plugin-code-push) and [React Native](https://github.com/Microsoft/react-native-code-push)). This allows you to have a more deterministic and direct engagement model with your userbase, when addressing bugs and/or adding small features that don't require you to re-build a binary and re-distribute it through the respective app stores. +CodePush SDK enables seamless in-app updates and serves as a core component of the [CodePush React Native SDK](https://github.com/Microsoft/react-native-code-push). -This repo includes the [management CLI](https://github.com/Microsoft/code-push/tree/master/cli) and [Node.js management SDK](https://github.com/Microsoft/code-push/tree/master/sdk), which allows you to manage and automate the needs of your Cordova and React Native apps. To get started using CodePush, refer to our [documentation](http://microsoft.github.io/code-push/index.html#getting_started), otherwise, read the following steps if you'd like to build/contribute to the project from source. +To start integrating CodePush into your project, visit our [documentation](https://docs.microsoft.com/en-us/appcenter/distribution/codepush/). If you're interested in contributing or building the SDK from source, follow the steps below. + +## Visual Studio App Center CodePush Standalone Version + +For teams or organizations looking to self-host CodePush, we now offer the [CodePush Standalone Version](https://github.com/microsoft/code-push-server) which is compatible with this SDK. It allows you to set up and manage CodePush as a self-hosted service, giving you more control over your infrastructure and data. Visit the repository for installation instructions, usage guides, and more. ## Dev Setup * Install [Node.js](https://nodejs.org/) * Install [Git](http://www.git-scm.com/) -* Install Gulp: `npm install -g gulp` * Clone the Repository: `git clone https://github.com/Microsoft/code-push.git` ### Building -* Run `npm install` from the root of the repository. -* Run `gulp install` to install the NPM dependencies of each module within the project. -* Run `gulp link` to link CLI and SDK for local development. It is advisable to do this step if you are making changes to the SDK and want the CLI to pick those changes. -* Run `gulp build` to build all of the modules. To build just one of the modules (e.g. cli or sdk), run `gulp build-cli` or `gulp build-sdk`. +* Run `npm run setup` to install the NPM dependencies of management SDK. +* Run `npm run build` to build the management SDK for testing. +* Run `npm run build:release` to build the release version of management SDK. ### Running Tests -To run all tests, run `gulp test` script from the root of the project. - -To test just one of the projects (e.g. cli or sdk), run `gulp test-cli` or `gulp test-sdk` +* To run tests, run `npm run test` from the root of the project. +* You can use debug mode for tests with `.vscode/launch.json` file. ### Coding Conventions @@ -33,3 +42,114 @@ To test just one of the projects (e.g. cli or sdk), run `gulp test-cli` or `gulp * Use `camelCase` for local variables and imported modules, `PascalCase` for types, and `dash-case` for file names This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +# CodePush Management SDK (Node.js) + +A JavaScript library for programmatically managing your CodePush account (e.g. creating apps, promoting releases), which allows authoring Node.js-based build and/or deployment scripts, without needing to shell out to the [App Center CLI](https://github.com/microsoft/appcenter-cli). + +## Getting Started + +1. Create a token to authenticate with the CodePush server using the following [App Center CLI](https://github.com/microsoft/appcenter-cli) command: + + ```shell + appcenter tokens create -d "DESCRIPTION_OF_THE_TOKEN" + ``` + + Please copy your `API Token` and keep it secret. You won't be able to see it again. + +2. Install the management SDK by running `npm install code-push --save` + +3. Import it using one of the following statement: (using ES6 syntax as applicable): + * On commonjs environments: + + ```javascript + const CodePush = require("code-push"); + ``` + + * Using ES6 syntax with tsconfig.json: + + ```javascript + import CodePush from "code-push"; + ``` + +4. Create an instance of the `CodePush` class, passing it the `API Token` you created or retrieved in step #1: + + ```javascript + const codePush = new CodePush("YOUR_API_TOKEN"); + ``` + +5. Begin automating the management of your account! For more details on what you can do with this `codePush` object, refer to the API reference section below. + +## API Reference + +The `code-push` module exports a single class (typically referred to as `CodePush`), which represents a proxy to the CodePush account management REST API. This class has a single constructor for authenticating with the CodePush service, and a collection of instance methods that correspond to the commands in the [App Center CLI](https://github.com/microsoft/appcenter-cli), which allow you to programmatically control every aspect of your CodePush account. + +### Constructors + +* __CodePush(accessKey: string)__ - Creates a new instance of the CodePush management SDK, using the specified access key to authenticated with the server. + +### Methods + +*Note: `access key` here refers to an AppCenter API Token.* + +* __addAccessKey(description: string): Promise<AccessKey>__ - Creates a new access key with the specified description (e.g. "VSTS CI"). + +* __addApp(name: string, os: string, platform: string, manuallyProvisionDeployments: boolean = false): Promise<App>__ - Creates a new CodePush app with the specified name, os, and platform. If the default deployments of "Staging" and "Production" are not desired, pass a value of true for the manuallyProvisionDeployments parameter. + +* __addCollaborator(appName: string, email: string): Promise<void>__ - Adds the specified CodePush user as a collaborator to the specified CodePush app. + +* __addDeployment(appName: string, deploymentName: string): Promise<Deployment>__ - Creates a new deployment with the specified name, and associated with the specified app. + +* __clearDeploymentHistory(appName: string, deploymentName: string): Promise<void>__ - Clears the release history associated with the specified app deployment. + +* __getAccessKey(accessKey: string): Promise<AccessKey>__ - Retrieves the metadata about the specific access key. + +* __getAccessKeys(): Promise<AccessKey[]>__ - Retrieves the list of access keys associated with your CodePush account. + +* __getApp(appName: string): Promise<App>__ - Retrieves the metadata about the specified app. + +* __getApps(): Promise<App[]>__ - Retrieves the list of apps associated with your CodePush account. + +* __getCollaborators(appName: string): Promise<CollaboratorMap>__ - Retrieves the list of collaborators associated with the specified app. + +* __getDeployment(appName: string, deploymentName: string): Promise<Deployment>__ - Retrieves the metadata for the specified app deployment. + +* __getDeploymentHistory(appName: string, deploymentName: string): Promise<Package[]>__ - Retrieves the list of releases that have been made to the specified app deployment. + +* __getDeploymentMetrics(appName: string, deploymentName: string): Promise<DeploymentMetrics>__ - Retrieves the installation metrics for the specified app deployment. + +* __getDeployments(appName: string): Promise<Deployment[]>__ - Retrieves the list of deployments associated with the specified app. + +* __patchRelease(appName: string, deploymentName: string, label: string, updateMetadata: PackageInfo): Promise<void>__ - Updates the specified release's metadata with the given information. + +* __promote(appName: string, sourceDeploymentName: string, destinationDeploymentName: string, updateMetadata: PackageInfo): Promise<Package>__ - Promotes the latest release from one deployment to another for the specified app and updates the release with the given metadata. + +* __release(appName: string, deploymentName: string, updateContentsPath: string, targetBinaryVersion: string, updateMetadata: PackageInfo): Promise<Package>__ - Releases a new update to the specified deployment with the given metadata. + +* __removeAccessKey(accessKey: string): Promise<void>__ - Removes the specified access key from your CodePush account. + +* __removeApp(appName: string): Promise<void>__ - Deletes the specified CodePush app from your account. + +* __removeCollaborator(appName: string, email: string): Promise<void>__ - Removes the specified account as a collaborator from the specified app. + +* __removeDeployment(appName: string, deploymentName: string): Promise<void>__ - Removes the specified deployment from the specified app. + +* __renameApp(oldAppName: string, newAppName: string): Promise<void>__ - Renames an existing app. + +* __renameDeployment(appName: string, oldDeploymentName: string, newDeploymentName: string): Promise<void>__ - Renames an existing deployment within the specified app. + +* __rollback(appName: string, deploymentName: string, targetRelease?: string): Promise<void>__ - Rolls back the latest release within the specified deployment. Optionally allows you to target a specific release in the deployment's history, as opposed to rolling to the previous release. + +* __transferApp(appName: string, email: string): Promise<void>__ - Transfers the ownership of the specified app to the specified account. + +### Error Handling + +When an error occurs in any of the methods, the promise will be rejected with a CodePushError object with the following properties: + +* __message__: A user-friendly message that describes the error. +* __statusCode__: An HTTP response code that identifies the category of error: + * __CodePush.ERROR_GATEWAY_TIMEOUT__: A network error prevented you from connecting to the CodePush server. + * __CodePush.ERROR_INTERNAL_SERVER__: An error occurred internally on the CodePush server. + * __CodePush.ERROR_NOT_FOUND__: The resource you are attempting to retrieve does not exist. + * __CodePush.ERROR_CONFLICT__: The resource you are attempting to create already exists. + * __CodePush.ERROR_UNAUTHORIZED__: The access key you configured is invalid or expired. diff --git a/sdk/SDK.njsproj b/SDK.njsproj similarity index 100% rename from sdk/SDK.njsproj rename to SDK.njsproj diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..46bf9ec0 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + +* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). + + \ No newline at end of file diff --git a/cli/.npmignore b/cli/.npmignore deleted file mode 100644 index a57287c2..00000000 --- a/cli/.npmignore +++ /dev/null @@ -1,5 +0,0 @@ -.npmignore -.gitignore -node_modules/* -definitions/* -!cli.js diff --git a/cli/README-cn.md b/cli/README-cn.md deleted file mode 100644 index 1703525d..00000000 --- a/cli/README-cn.md +++ /dev/null @@ -1,732 +0,0 @@ -# CodePush 命令行 - -#### Note: This translated document is community contributed and maintained, it will not be kept updated or in sync with the [original](./README.md) by the main contributors. Please send a pull request if you find any issues. -#### 注:本翻译文档是由社区贡献和维护,不受[原文](./README.md)的作者持续维护并更新。如果您发现任何问题,请发送pull请求。 - -CodePush是一个云服务,它能让Cordova和React Native的开发者将手机应用的更新直接部署到用户的设备上。 -它担任类似中间仓库的角色,开发者可以把更新(JS,HTML,CSS和图片)发布到这个仓库上,然后那些Apps就能查询到更新了(那些集成了CodePush SDKs的[Cordova](http://github.com/Microsoft/cordova-plugin-code-push)和[React Native](http://github.com/Microsoft/react-native-code-push) 应用)。 - -这就让你可以与你的用户群有一个更确定且直接的交互模式,当你定位到Bug或添加小功能时,就不需要重新构建二进制文件再在各AppStore里重新发布了。 - -![CodePush CLI](https://cloud.githubusercontent.com/assets/116461/14505396/c97bdc78-016d-11e6-89da-3f3557f8b33d.png) - -* [安装](#安装) -* [快速开始](#快速开始) -* [创建账号](#创建账号) -* [身份认证](#身份认证) -* [应用管理](#应用管理) -* [应用合作](#应用合作) -* [部署管理](#部署管理) -* [发布更新](#发布更新) - * [发布更新 (General)](#发布更新-general) - * [发布更新 (React Native)](#发布更新-react-native) - * [发布更新 (Cordova)](#发布更新-cordova) -* [补丁更新](#补丁更新) -* [促进更新](#促进更新) -* [回滚更新](#回滚更新) -* [查看发布历史](#查看发布历史) -* [清除发布历史](#清除发布历史) - -[[English Version]](./README.md) - -## 安装 - -* 安装 [Node.js](https://nodejs.org/) -* 安装 CodePush CLI: `npm install -g code-push-cli` - -## 快速开始 - -1. 使用CodePush CLI创建一个[CodePush 账号](#创建账号) -2. 注册你的CodePush[应用](#应用管理), 并[分享](#应用合作)给你团队的其它开发者 -3. 用[Cordova插件](http://github.com/Microsoft/cordova-plugin-code-push) 或 [React Native插件](http://github.com/Microsoft/react-native-code-push)配置好CodePush并指向你希望的部署环境 -4. [发布](#发布更新)更新 -5. 活的长而成功![详细资料](https://en.wikipedia.org/wiki/Vulcan_salute) - -## 创建账号 - -在你发布应用更新之前,你需要创建一个CodePush帐号。一旦你安装了Cli你就可以简单的使用如下命令来注册: - -``` -code-push register -``` - -这将会启动浏览器,要求验证你的Github或微软帐号。一旦验证成功,它将创建一个CodePush帐号跟你的Github或MSA相连,并生成一个访问密钥(Access Key),你可以拷贝/粘贴到CLI以便登录。 - -*注意:注册成功后,你就已经自动登录了。所以除非你明确登出了,否则你不需要在此机器上再次登录。* - -如果你已有一个帐号,那你还可以把你的帐号跟另一个身份认证提供商关联起来,通过运行: - -(我个人理解:CodePush提供商有Github和Mircosoft,它允许你可以把两个帐号关联起来。) - -``` -code-push link -``` - -注意:为了实现这个(关联)的目的,你在另一个身份认证供应商那边用的Email地址必须与你现存的帐号一致。 - -## 身份认证 - -在CodePush CLI里大多数命令需要身份认证,所以在你开始管理你的帐号之前,你需要使用GitHub或者微软帐号注册和登录。你可以通过执行如下命令做到这些: - -``` -code-push login -``` - -这将会启动浏览器,要求验证你的Github或微软帐号。这将生成一个访问密钥(Access Key),然后你可以拷贝/粘贴到CLI(它会提示你这样做)。这时你就认证成功了,并且可以关掉你的浏览器了。 - - -如果在任何时候你想确认你是否已经登录了,你可以运行如下命令来显示与你当前认证会话相关的e-mail帐号,而且这个身份提供者是连接到(如:GitHub)的。 - -```shell -code-push whoami -``` - -当你从CLI登录后,你的访问密钥(Access Key)就一直保存在你本地磁盘上,所以你不必每次使用帐号是都需要登录。为了终止会话或删除AccessKey,你可以简单的运行如下命令: - -``` -code-push logout -``` - -如果你在一台机器上忘记注销(比如:你朋友的电脑上),你可以使用如下命令列出和删除任何“激活中”的Access Keys。Access Keys列表将显示创建Key的机器名和发生登录的时间。这让你可以简单的认出那些你不想要保存的Keys。 - -``` -code-push access-key ls -code-push access-key rm -``` - -如果你需要额外的Keys,被用来验证CodePush服务而不需要给你的GitHub和/或访问微软凭证,您可以运行下面的命令来创建一个持久的Access Key(连同一个描述): - -``` -code-push access-key add "VSTS Integration" -``` -在创建新的密钥之后,您可以在`login`命令后使用`--accessKey`标志并指定其值,它允许您执行“无头”身份验证,而不是启动一个浏览器。 - -``` -code-push login --accessKey -``` -当使用这种方式登录时,密钥(Access Key)在注销时不会自动失效,它可以一直被使用,除非它从CodePush服务端明确被移除掉。然而,仍然建议一旦你完成了会话就注销掉,以便从本地磁盘移除掉你的授权证书。 - -## 应用管理 - -在你发布更新前,你需要用如下命令在CodePush服务上注册一个App: - -``` -code-push app add -``` - -如果你的App既有iOS又有Android,请*为不同平台创建单独的App*(详情参照下文的注解)。一个平台一个。这样你可以单独的管理和发布更新,从长远来看这会让事情更简单。大部分人的命名约定会在App名加后缀`-IOS`和`-Android`。例如: - -``` -code-push app add MyApp-Android -code-push app add MyApp-iOS -``` - -*注意:在iOS和Android使用相同的app可能会导致安装异常,因为CodePush在iOS和Android的更新包内容会有差异。* - -所有新的Apps自动会出现有个部署环境(`Staging`和`Production`),为了你可以开始发布更新到不同的渠道而不需要做任何其它的事(参考下面的部署指南)。你创建一个App之后,CLI将显示`Staging`和`Production`环境的开发密钥,你就可以使用不同的SDKs(详细请看[Cordova](http://github.com/Microsoft/cordova-plugin-code-push) 和 [React Native](http://github.com/Microsoft/react-native-code-push))来配置你的手机端App了。 - -如果你不喜欢你之前取的名字,你还可以随时重命名它,使用如下命令: - -``` -code-push app rename -``` - -应用的名字从管理方面看只是为了能辨识,因此,必要时可以随时重命名它。它其实不会影响正在运行的应用程序,因为更新的查询都是通过部署密钥的。 - -如果你不想要一个App,你可以从服务端上移除它,命令如下: - -``` -code-push app rm -``` - -做这个移除请务必小心,因为任何配置了它的App都将停止收到更新了。 - -最后,如果你想列出你在CodePush服务上注册的所有Apps,你可以运行如下命令: - -``` -code-push app ls -``` - -## 应用合作 - -如果你讲和其它开发者在一起合作同一个CodePush应用,你可以把他们添加为合作者,使用如下命令: - -```shell -code-push collaborator add -``` - -*注意: 这个期待开发者已经用e-mail[注册](#创建账号)了CodePush,所以在打算分享应用之前确保他们已经准备好了一切。* - -一旦添加了,所有的合作者将立即拥有了最新分享App的如下权限: - -1. 查看App,它的合作者,[部署管理](#部署管理)和[查看发布历史](#查看发布历史)。 -1. [发布](#发布更新)更新到任何应用的部署环境。 -1. [促进](#促进更新)更新在任何应用部署环境之间。 -1. [回滚](#回滚更新)任何应用部署。 -1. [打补丁](#补丁更新)在任何应用部署里。 - -相反的,这就意味着一个合作者不能做任何如下的事情: - -1. 重命名或删除应用。 -1. 转让应用的所有权。 -1. 创建,重命名或删除新的部署环境。 -1. 清除一个部署历史。 -1. 添加或删除合作者。 - -*注意:一个合作的开发者可以移除他/她自己。* - -随着时间的推移,如果有人不再和你一起合作,那你可以解除合作者关系,使用如下命令: - -```shell -code-push collaborator rm -``` - -如果你想列出应用的所有合作者,你可以简单的运行如下命令: - -```shell -code-push collaborator ls -``` - -最后,如果在某刻你(作为App的拥有者)将不再开发App了,你想转让给其他开发者(或客户),你可以运行如下命令: - -```shell -code-push app transfer -``` - -*注意:就像`code-push collaborator add`命令一样,这期望新的拥有者已经用指定的e-mail注册了CodePush。* - -一经确认,该指定的开发者成为App的拥有者,而且立即接收到该角色的相关权限。除了拥有权转移外,其它的任何都没有被修改(比如:部署环境,发布历史,合作者)。这意味着你还仍然是该App的一个合作者,所以如果你想移除你自己,那你可以在成功转让拥有全后简单的运行`code-push collaborator rm`命令。 - -## 部署管理 - -从CodePush的角度来看,一个应用把一个或更多的东西简单命名分组称为“部署(环境)”。 - -While the app represents a conceptual "namespace" or "scope" for a platform-specific version of an app (e.g. the iOS port of Foo app), its deployments represent the actual target for releasing updates (for developers) and synchronizing updates (for end-users). Deployments allow you to have multiple "environments" for each app in-flight at any given time, and help model the reality that apps typically move from a dev's personal environment to a testing/QA/staging environment, before finally making their way into production. - -*注意: 正如你将在下面看到的`release`(发布),`promote`(提升),`rollback`(回滚)命令需要应用名字和部署名字,因为这两个组成一个独特的发布标识(例如:我想发布更新到我的IOS应用给beta环境的测试者们)。* - -当一个用CodePush服务注册的应用,它默认包含两个部署环境:`Staging`和`Production`。这让你可以理解发布更新到一个内部的环境,你可以在推送到终端用户之前彻底的测试每个更新。这个工作流是至关重要的,以确保你的版本准备好给大众,而且这是一个在Web上实践很久的惯例。 - -如果你的App有`Staging`和`Production`环境其实已经满足了你的需求,然后你不需要做任何事情。不过,如果你需要alpha,dev等部署环境,那你可以简单的使用如下命令创建: - -``` -code-push deployment add -``` - -就像Apps一样,你也可以删除或重命名部署环境,分别使用如下命令: - -``` -code-push deployment rm -code-push deployment rename -``` - -你可以在任何时候查看特定应用包含的部署环境列表,你可以简单的运行下面的命令: - -``` -code-push deployment ls [--displayKeys|-k] -``` - -这将不仅显示部署环境列表,而且还有元数据(例如:强制性属性,描述)和最新版本的安装指标: - -![Deployment list](https://cloud.githubusercontent.com/assets/116461/12526883/7730991c-c127-11e5-9196-98e9ceec758f.png) - -*注意: 因为他们很少用和需要屏幕,部署密钥默认是不显示的。如果你需要查看它们,只要在`deployment ls`命令后面加上`-k`标识即可。* - -安装指标有如下意义: - -* **Active(激活)** - 成功安装的数量目前运行这个版本。这个数字将会随着用户更新到或离开这个版本分别增加或减少。 - -* **Total** - 该版本更新收到的所有成功安装的总数。这个数字只会随新用户/设备安装它而增加,所以它是__激活__的超集。 - -* **Pending** - 更新被下载了但还没安装的数量。This would only apply to updates that aren't installed immediately, and helps provide the broader picture of release adoption for apps that rely on app resume and restart to apply an update. - -* **Rollbacks** - 该版本被自动回滚的次数。理想情况下这个数应该为0,而且在这种情况下这个量是不会显示的。然而,如果你发布了一个包含严重问题(Crash)的更新,CodePush插件将在安装时回滚到上一个版本,同时把问题反馈到服务端。这可以让终端用户依旧能用,不被损坏的版本阻塞住,而且能够在CLI里看到这些,你可以鉴定错误的版本并且能在服务器上做出[回滚](#回滚更新)的响应。 - -* **Rollout** - 显示有资格接收更新的百分比。这个属性只会被显示在那些`激活的`的首次展示的版本,所以,首次展示百分比是小于100%。此外, 因为一个部署任何时候只能有一个激活的首次展示,这个标签只会被显示在最新的一次部署里。 - -* **Disabled** - 标示是否该版本被标记成失效的,因此用户是否可下载。这个属性只有在版本真实失效时才显示。 - -当度量(metrics)单元格统计为`No installs recorded`(无安装记录),那是表示这个版本在服务器上没有任何活动记录。这可能要么是因为被插件阻止了,或者用户还没有跟CodePush服务器同步。一旦发生了安装,你将在CLI里看到该版本的度量。 - -## 发布更新 - -一旦你的App被配置了从CodePush服务器查询版本更新,你就可以向它开始发布。为了简易性和灵活性,CodePush CLI包含三种不同的发布命令: - -1. [通用](#发布更新-general) - 使用外部的工具或构建脚本(如:Gulp任务,`react-native bundle`命令)像CodePush服务器发布一个更新。这对装配进目前的工作流而言提供最灵活的方式,因为它严格按CodePush特性的步骤处理,而把App特性的编译过程留给你。 - -2. [React Native](#发布更新-react-native) - 跟通用发布命令一样执行相同的功能,但是还会为你生成的应用更新内容(JS包和资源),而不需要你运行`react-native bundle`,然后执行`code-push release`。 - -3. [Cordova](#发布更新-cordova) - 跟通用发布命令一样执行相同的功能,但也会为你处理准备应用更新的任务,而不需要你运行`cordova prepare`,然后执行`code-push release`。 - -你应该使用哪个命令主要是一种需求或偏好的事。然而,我们通常推荐使用相关的特定平台的命令开始(因为它大大简化了体验),然后当有更大控制必要时用通用的`release`命令。 - -### 发布更新 (General) - -``` -code-push release -[--deploymentName ] -[--description ] -[--disabled ] -[--mandatory] -[--rollout ] -``` - -#### App name (应用名)参数 - -指定将发布更新的CodePush 应用名。这个与最初你调用`code-push app add`(如:"MyApp-Android")的名字保持一致。如果你想查一下,可以运行`code-push app ls`命令看看应用的列表。 - -#### Update contents (更新内容)参数 - -指定应用更新的代码和资源位置。你可以提供要么一个单独文件(如:React Native的JS bundle文件),或者一个文件夹路径(如:Cordova应用的`/platforms/ios/www`文件夹)。注意你不需要为了部署更新而对文件或文件夹进行Zip压缩,因为CLI会帮你自动ZIP压缩。 - -重要的是你指定的路径是跟特定平台相关的,准备/打包你的应用。下面表格概括了在发布前你应该运行哪个命令,以及你以后可以参考的`updateContents` 参数路径: - -| 平台 | 准备命令(Prepare command ) | 包的路径 (相对项目的根目录) | -|-------------------------------------|--------------------------------------------|-------------------------------------------------------------------------------------------------------------| -| Cordova (Android) | `cordova prepare android` | `./platforms/android/assets/www` 目录 | -| Cordova (iOS) | `cordova prepare ios` | `./platforms/ios/www ` 目录 | -| React Native wo/assets (Android) | `react-native bundle --platform android --entry-file --bundle-output --dev false` | `--bundle-output` 参数的值 | -| React Native w/assets (Android) | `react-native bundle --platform android --entry-file --bundle-output / --assets-dest --dev false` | `--assets-dest` 参数的值,应该是一个包含资源和JS bundle的新创建的目录。| -| React Native wo/assets (iOS) | `react-native bundle --platform ios --entry-file --bundle-output --dev false` | `--bundle-output` 参数的值 | -| React Native w/assets (iOS) | `react-native bundle --platform ios --entry-file --bundle-output / --assets-dest --dev false` | `--assets-dest` 参数的值,应该是一个包含资源和JS bundle的新创建的目录。| - -#### Target binary version (目标二进制版本)参数 - -这是你想发布更新的特定仓库/二进制版本,这样只有那个版本上的用户才会接收到更新,而那些运行较老/新版本用户则不会。这样很有用,原因如下: - -1. 如果有用户运行一个很老的版本,有可能在CodePush的更新里有个破坏性的更新,这跟他们现在运行的版本不兼容。 - -2. 如果用户正在运行一个新的二进制版本,那么假定,他们正在运行并更新CodePush 更新(可能不兼容)。 - -如果你想更新应用商店里二进制文件的多个版本,我们允许你指定参数像这样[语义版本范围表达式](https://github.com/npm/node-semver#advanced-range-syntax)。这样, 任何在版本号范围内(如:`semver.satisfies(version, range)` returns `true`)的客户端设备都能获得更新。 - -如下是有效的版本号范围表达式的例子: - -| 范围表达式 | 谁获得更新 | -|------------------|----------------------------------------------------------------------------------------| -| `1.2.3` | 只有`1.2.3`版本 | -| `*` | 所有版本 | -| `1.2.x` | 主版本为1,小版本为2的任何版本 | -| `1.2.3 - 1.2.7` | 在 `1.2.3` (包含) 和 `1.2.7` (包含) 之间的版本 | -| `>=1.2.3 <1.2.7` | 在 `1.2.3` (包含) 和 `1.2.7` (不包含)之间的版本 | -| `~1.2.3` | 相当于`>=1.2.3 <1.3.0` | -| `^1.2.3` | 相当于`>=1.2.3 <2.0.0` | - -*注意:如果语义表达式以特殊字符开始如`>`,`^`或***,如果你没有用引号括起来的话命令可能执行不对,因为shell在CLI里不支持右边的值。所以,当调用`release`命令时最好能把你的`targetBinaryVersion`参数用双引号括起来,如:`code-push release MyApp updateContents ">1.2.3"`。* - -*注意:根据语义版本规范,版本范围仅对非预发布版本生效:(https://github.com/npm/node-semver#prerelease-tags) 。当你想要发布更新到一个预发布的版本上时,则需要明确指定你想要升级的版本号(比如`1.2.3-beta`)。* - -如下表格分别概括了每个应用类型的CodePush更新的语义版本范围的版本值: - -| 平台 | 应用商店版本来源 | -|------------------------|------------------------------------------------------------------------------| -| Cordova | 在`config.xml`文件里的`` 属性 | -| React Native (Android) | 在`build.gradle`文件里 `android.defaultConfig.versionName` 属性 | -| React Native (iOS) | 在`Info.plist`文件里的`CFBundleShortVersionString` 键 | -| React Native (Windows) | 在`Package.appxmanifest`文件的 `` 键 | - -*注意:如果在元数据文件里的应用版本号漏掉补丁版本值,如`2.0`,它将被当成补丁版本值为`0`,如:`2.0 当成 2.0.0`.* - -#### Deployment name (部署环境名)参数 - -这是你想发布更新到的那个指定部署环境名。默认为`Staging`(临时环境),但是当你准备部署到`Production`(生产环境)或一个你自定义的部署环境时,你只要指明设置这个参数即可。 - -*注意:这个参数可以用"--deploymentName" 或 "-d"来设置。* - -#### Description (描述)参数 - -给部署提供一个可选的"更新日志"。当被检测到有更新时这个值就会完整的传到客户端,所以你的应用可以选择显示给终端用户(如:通过一个`哪些新东西?`的对话框)。这个字符串可以接受控制字符如`\n` 和 `\t`,以便你可以包含空白格式在你的描述里来提高可读性。 - -*注意:这个参数可以用"--description" 或 "--des"来设置。* - -#### Mandatory (强制性)参数 - -这个标识该更新是否是强制性的(如:包含一个严重的安全修复)。这个属性简单的传到客户端,然后客户端决定是否要强制更新。 - -*注意: 这个参数是简单的一个"标记",所以,没有该标记表示版本更新可选,如果有标记则表示版本是强制更新的。你可以给它赋值(如:`--mandatory true`),但其实简单的`--mandatory`就已能标识强制更新了。* - -强制属性是唯一的,因为服务端必要时将动态修改它,为了确保你对终端用户的版本更新语义上的维护。例如:设想你的应用有如下3个更新: - -| 版本 | 强制? | -|---------|------------| -| v1 | No | -| v2 | Yes | -| v3 | No | - -如果用户当前是`v1`版本,然后从服务端查询更新,将以`v3`(因为这是最新的)响应,但是它将动态将这个版本转变成强制的,因为中间有一个强制更新的版本。这个行为很重要因为`v3`的代码是在`v2`上增加的,所以任何没有获取`v2`版本的都会不管`v2`的强制,而继续让`v3`变成强制更新版本。 - -如果用户当前是`v2`版本,然后从服务器查询更新,响应结果为`v3`,但会留着这个版本作为可选的。这个因为他们已经接受了强制更新,所以没有必要去修改`v3`。这样的行为就是为什么我们说服务器会"动态改变"强制标签,因为随着版本的迭代,新版本的强制属性总会保存你设置的这个值。当有一个版本更新检查要响应给用户时,它只会在相邻的版本上改变。 - -如果你从没发布一个强制的更新,那么上面的行为不会应用到你,因为服务器从不改变一个可选的版本为强制版本,除非有像上面阐述的那样掺杂了强制版本。此外,如果一个版本标记成强制了,它决不会被转变成可选的,因为那没有任何意义。为了尊重上面描述的语义,服务器将只会把一个可选的发布改变为强制的。 - -*注意:这个参数可以用`--mandatory` 或 `-m`来设置* - -#### Rollout 参数 - -**重要:为了使这个参数有效,终端用户需要运行CodePush插件的`1.6.0-beta+`版本 (Cordova) 或 `1.9.0-beta+`版本 (React Native)。如果你发布了一个指明了首次展示(Rollout)属性的更新,那么运行老版本的Cordova或ReactNative用户不会更新。因此,直到你已经采取了必要CodePush SDK的版本,否则我们不建议设置一个首次展示(rollout)版本,因为没有人会接受它。** - -这指定了可以接收这次更新的用户百分比(在`1`到`100`之间的数字)。这会是有帮助的,假如你想在每个人广泛获取之前,"飞行"一个新版本给部分的受众(如:25%) ,并且得到异常/崩溃的反馈观察。如果没有设置这个参数,它会设置为`100%`,所以,你只需要在你想实际限制多少用户能接收时去设置它。 - -当借用首次展现(rollout)能力,要记住一些额外注意事项: - -1. 你不可以在最新版本的首次展示是"有效的"(如:首次展示值非空)的部署环境上发布新更新。在你在部署环境上发布进一步更新之前,首次展示属性需要是"完全的"(如:设置`roullout`属性为`100`)。 - -2. 如果你回滚部署环境,它的最新版本的首次展示是"有效的",那首次展示的值将被清除,实际上"禁止"首次展示行为。 - -3. 不像`mandatory`和`description`字段,当从一个部署环境中促进发布时,它将不会传送`rollout`属性,所以,如果你想新的发布(在目标部署环境里)有首次展示的值,那么你需要在调用`promote`命令时明确的设置它。 - -*注意:这个参数可以用 `--rollout` or `-r` 来设置* - -#### Disabled 参数 - -这个指明一个版本更新是否可以被用户下载。如果没有指定,版本更新不会是无效的(如:用户将要下载的那一刻你的应用称为`同步`)。如果你想发布一个更新但不是立即生效,那么这个参数是有价值的,直到你明确用[补丁](#补丁更新)发布,当你要让用户能够下载(如:公告博客上线)。 - -*注意:这个参数可以用 "--disabled" or "-x"来设置* - -### 发布更新 (React Native) - -```shell -code-push release-react -[--bundleName ] -[--deploymentName ] -[--description ] -[--development ] -[--disabled ] -[--entryFile ] -[--gradleFile ] -[--mandatory] -[--noDuplicateReleaseError] -[--outputDir ] -[--plistFile ] -[--plistFilePrefix ] -[--sourcemapOutput ] -[--targetBinaryVersion ] -[--rollout ] -[--privateKeyPath ] -[--config ] -``` -`release-react`命令是React Native特有的[`发布`](#发布更新)命令,支持相同的所有参数(如:`--mandatory`,`--description`),然而通过如下额外的动作简化了发布更新过程: - -1. 运行`react-native bundle`命令去生成将要发布到CodePush服务的[更新](#update-contents-params)(JS Bundle和资源)。它尽可能使用合理的默认值(如:创建一个non-dev构建,假设一个iOS入口文件被命名为“index.ios.js”),但也暴露了有关`react-native bundle`参数使得灵活(如:`--sourcemapOutput`)。 - -2. 通过使用定义在项目文件`info.plist`(IOS)和`build.gradle`(Android)里的版本名,推断[`targetBinaryVersion`](#target-binary-version-目标二进制版本-参数)的值。 - -为了阐述`release-react`命令产生的差异,如下的例子是你可能如何生成和发布一个React Native应用版本更新,通过使用`release`命令: - -```shell -mkdir ./CodePush - -react-native bundle --platform ios \ ---entry-file index.ios.js \ ---bundle-output ./CodePush/main.jsbundle \ ---assets-dest ./CodePush \ ---dev false - -code-push release MyApp ./CodePush 1.0.0 -``` - -用`release-react`命令实现等效的行为只需简单的如下的命令,这个通常更,这是通常更少出错: - -```shell -code-push release-react MyApp ios -``` - -*注意:我们相信`release-react`命令对大多数React Native的开发者是有价值的,所以如果你发现它不够灵活或者缺少关键功能,不要犹豫请[让我们知道](mailto:codepushfeed@microsoft.com),以便我们可以提高它。* - -#### App name 参数 - -这个参数跟[上面章节](#App-name-应用名-参数)描述的一样。 - -#### Platform 参数 - -指定当前的更新是哪个平台的,可以是`android`, `ios`, 或`windows`(不区分大小写)。 - -#### Deployment name 参数 - -相同的参数跟 [上面的章节](#deployment-name-参数)描述一样。 - -#### Description 参数 - -相同的参数跟 [上面的章节](#description-参数)描述一样。 - -#### Mandatory 参数 - -相同的参数跟 [上面的章节](#mandatory-参数)描述一样。 - -#### Rollout 参数 - -相同的参数跟 [上面的章节](#rollout-参数)描述一样。如果没有指定,版本将对所有用户有效可下载。 - -#### Target binary version 参数 - -相同的参数跟 [上面的章节](#target-binary-version-参数)描述一样。如果没有指定,默认使用`Info.plist` (iOS) and `build.gradle` (Android)文件里指定的精确版本号。 - -#### Disabled 参数 - -相同的参数跟 [上面的章节](#disabled-参数))描述一样。 - -#### Development 参数 - -这个指明是否要生成一个非最小化,开发的JS bundle文件。如果没有指明,默认是`false`,禁用警告提示并且bundle文件是最小化的。 - -*注意:这个参数可以配置成`--development` 或`--dev`* - -#### Entry file 参数 - -指明相对应用根目录的路径入口JavaScript 文件。如果没有指定,默认是:如果存在`index.ios.js`(IOS), `index.android.js`(Android), 或者`index.windows.bundle`(Windows),否则`index.js`。 - -*注意:参数可以配置成`--entryFile`或`-e`* - -#### Bundle name 参数 - -指明生成JS Bundle的文件名。如果没有指定,特定平台将会用的标准bundle名字:`main.jsbundle` (iOS), `index.android.bundle` (Android) and `index.windows.bundle` (Windows). - -*注意:参数可以配置成`--bundleName`或`-b`* - -#### Sourcemap output 参数 - -指明生成的JS bundle 的sourcemap写入的相对路径。如果没有指定,sourcemaps文件不会生成。 - -*注意:参数可以配置成`--sourcemapOutput`或`-s`* - -### 发布更新 (Cordova) - -```shell -code-push release-cordova -[--deploymentName ] -[--description ] -[--mandatory] -[--targetBinaryVersion ] -[--rollout ] -[--build] -``` - -这个`release-cordova` 命令是Cordova特有的[`发布`](#发布更新)命令,支持相同的所有参数(如:`--mandatory`,`--description`),然而通过如下额外的动作简化了发布更新过程: - -1. 运行`cordova prepare`命令去生成将要发布到CodePush服务的[更新内容](#update-contents-更新内容-参数) (`www` 文件夹) 。 - -2. 通过使用定义在项目文件`config.xml`文件里的版本名,推断[`targetBinaryVersion`](#target-binary-version-目标二进制版本-参数) 的值。 - -为了阐述`release-cordova`命令产生的差异,如下的例子是你可能如何生成和发布一个Cordova应用版本更新,通过使用`release`命令: - - -```shell -cordova prepare ios -code-push release MyApp ./platforms/ios/www 1.0.0 -``` - -用`release-cordova`命令实现等效的行为只需简单的如下的命令,这个通常更,这是通常更少出错: - -```shell -code-push release-cordova MyApp ios -``` - -注意:我们相信`release-cordova`命令对大多数Cordova的开发者是有价值的,所以如果你发现它不够灵活或者缺少关键功能,不要犹豫请[让我们知道](mailto:codepushfeed@microsoft.com),以便我们可以提高它。 - -#### App name 参数 - -这个参数跟[上面章节](#App-name-应用名-参数)描述的一样。 - -#### Platform 参数 - -指定当前的更新是哪个平台的,可以是`ios`或`android`(不区分大小写)。 - -#### Deployment name 参数 - -相同的参数跟 [上面的章节](#deployment-name-参数)描述一样。 - -#### Description 参数 - -相同的参数跟 [上面的章节](#description-参数)描述一样。 - -#### Mandatory 参数 - -相同的参数跟 [上面的章节](#mandatory-参数)描述一样。 - -#### Rollout 参数 - -相同的参数跟 [上面的章节](#rollout-参数)描述一样。如果没有指定,版本将对所有用户有效可下载。 - -#### Target binary version 参数 - -相同的参数跟 [上面的章节](#target-binary-version-参数)描述一样。如果没有指定,默认使用项目元数据里指定的(`Info.plist` (iOS) and `build.gradle` (Android)版本号。 - -#### Disabled 参数 - -相同的参数跟 [上面的章节](#disabled-参数))描述一样。 - -#### Build 参数 - -当你生成版本更新的web资源时,指定是否想用`cordova build`来取代`cordova prepare`(默认行为)。这是有价值的,假设你的项目包含构建钩子(如:转换TypeScript),所以CodePush简单的运行`cordova prepare`不够充分的创建和发布更新。如果没有指定,它默认是`false`。 - -*注意:这个参数可以用`--build`或`-b`来设置* - -## 补丁更新 - -在发布更新之后,可能有这样的场景,你需要修改一个或多个相关的属性(如:你忘记给一个严重的Bug修复打上强制标记了,你想增加更新的首次展示百分比)。你可以很容易的用下面的命令行来实现: - -```shell -code-push patch -[--label ] -[--mandatory ] -[--description ] -[--rollout ] -[--disabled ] -[--targetBinaryVersion ] -``` - -抛开`appName` 和 `deploymentName`,所有参数是可选的,所以,你可以用这个命令一次性更新单个或者所有属性。调用`patch`命令而不指定任何属性将不产生任何操作结果。 - -```shell -# Mark the latest production release as mandatory -code-push patch MyApp Production -m - -# Increase the rollout for v23 to 50% -code-push patch MyApp Production -l v23 -rollout 50% -``` - -### Label 参数 - -表明你想在指定的部署环境里更新哪个发布版本(如:`v23`)。如果省略了,那要求的变化将应用到指定的部署环境的最新版本上。为了查看你想更新的版本标签,你可以运行`code-push deployment history`命令并参见`Label`列。 - -*注意:这个参数可以设置成`--label`或`-l`* - -### Mandatory 参数 - -同样的参数跟[上面的章节](#mandatory-参数)描述一致,简单的允许你更改这个版本是否考虑强制更新。注意`--mandatory`和`--mandatory true`是同等的,但是缺少这个标记不等于`--mandatory false`。所以,如果参数省略了,对目标版本的强制性属性来说不会产生任何改变。你需要设置`--mandatory false`去明确的标识版本是可选的。 - -### Description 参数 - -同样的参数跟[上面的章节](#description-参数)描述一致,简单的允许你更改关联版本的描述(如:你在发布时写了个错别字,或者你完全忘记添加一个描述了)。如果参数省略掉了,那么对于目标版本的描述属性来说不会有任何改动。 - -### Disabled 参数 - -同样的参数跟[上面的章节](#disabled-参数)描述一致,简单的允许你去更改发布的版本是否无效。注意`--disabled`和`--disabled true`是等同的,但是缺省这个标识不等于`--disabled false`。所以,如果忽略了该参数,并不会对目标版本的无效(disabled)属性有修改。你需要设置`--disabled false`去明确标识一个以前无效的版本有效。 - -### Rollout 参数 - -同样的参数跟[上面的章节](#rollout-参数)描述一致,简单的允许你去__增加__目标版本首次展示的百分比。这个参数只能设成一个比当前首次展示值要大的数字。此外,如果你想"完全的"首次展示,因此,让版本对每个人有效,你可以简单的设置参数`--rollout 100`,如果省略了这个参数,目标版本的首次展示(rollout)属性不会有任何改动。 - -此外,上面提到的,当你发布版本时没有指定首次展示(rollout)的值时,它相当于是被设置成了`100`。因此,如果你发布一个没有首次展示的更新,那你不可以通过`patch`命令改变rollout属性,因为那样是被认为在降低首次展示(rolltout)百分比。 - -### Target binary version 参数 - -同样的参数跟[上面的章节](#target-binary-version-参数)描述一致,简单的允许你去更改语义版本范围表明兼容哪个版本版本。这个可以很有用,如果你在最初发布时犯了个错(如:你指定`1.0.0`但本意`1.1.0`)或你想增加或减少版本支持的版本范围(如:你发现一个版本总是不能在`1.1.2`版本上正常运行)。如果省略了这个参数,目标版本的版本号属性不会有任何改动。 - -```shell -# 给意境存在的版本添加一个"最大二进制版本"范围 -# by scoping its eligibility to users running >= 1.0.5 -code-push patch MyApp Staging -t "1.0.0 - 1.0.5" -``` - -## 促进更新 - -一旦测试完指定部署环境的版本更新(如:`Staging`),你想把它向下游推进(如:dev->staging, staging->production),你可以简单的用如下命令去从一个部署环境拷贝到另一个: - -``` -code-push promote -[--description ] -[--disabled ] -[--mandatory] -[--rollout ] -[--targetBinaryVersion -code-push rollback MyApp Production -``` - -这个的影响是在部署环境里创建一个包含**精确的代码和资源**的新版本,比最新版本更优先的一个版本。举个例子,想象你发布了如下更新: - -| 版本 | 描述 | 强制 | -|---------|-------------------|-----------| -| v1 | 初始化版本! | Yes | -| v2 | 添加新功能 | No | -| v3 | 修复Bugs | Yes | - -如果你在部署环境里运行`rollback`命令,一个包含`v2`版本内容的新的版本(`v4`)将会被创建。 - -| 版本 | 描述 | 强制 | -|---------|-------------------|-----------| -| v1 | 初始化版本! | Yes | -| v2 | 添加新功能 | No | -| v3 | 修复Bugs | Yes | -| v4 (从v3回滚到v2) | 添加新功能 | No | - -当app执行版本检查时,已经获得`v3`版本的用户现在被"回滚"到`v2`版本。此外,任何仍运行在`v2`版本的用户,因而将不会捕获到`v3`版本,因为他/她们已经在运行最新的版本(这就是为什么我们使用附加在版本标签里的包的hash来做版本检查)。 - - -如果你想回滚部署环境到一个版本而不是前一个版本(如:`v3` -> `v2`),你可以指定一个可选的`--targetRelease`参数: - -``` -code-push rollback MyApp Production --targetRelease v34 -``` - -*注意:由回滚产生的版本将会在`deployment history`命令的输出里被注释,以便助于更容易被辨识出来。* - -## 查看发布历史 - -你可以使用如下命令查看某个应用的部署环境里最多50条最新的发布历史: - -``` -code-push deployment history -``` - -这个历史纪录将显示每个版本的所有的属性(如:标签,强制性),也会标明任何版本是否由提升(promotion)或是回滚操作而来。 - -![Deployment History](https://cloud.githubusercontent.com/assets/696206/11605068/14e440d0-9aab-11e5-8837-69ab09bfb66c.PNG) - -此外,历史记录显示每个版本的安装指标。你可以在文档的上面`deployment ls`命令处查看指标数据的解释明细。 - -默认情况下,历史纪录不会显示各个版本的作者,但是如果你是和其它开发者合作的,而且想看每个更新是谁发布的,那你可以给历史命令传额外的`--displayAuthor`(或`-a`)标记。 - -*注意:历史命令可以使用"h"别名来运行* - -## 清除发布历史 - -你可以用如下命令清除相关的发布历史: - -``` -code-push deployment clear -``` - -运行此命令后,那些已经配置了使用关联的部署密钥的客户端设备将不再接收被清除掉的更新。这个命令是不可逆的,因此不应该使用在生产部署。 diff --git a/cli/README.md b/cli/README.md deleted file mode 100644 index 77311d9b..00000000 --- a/cli/README.md +++ /dev/null @@ -1,986 +0,0 @@ -# CodePush Management CLI - -CodePush is a cloud service that enables Cordova and React Native developers to deploy mobile app updates directly to their users' devices. It works by acting as a central repository that developers can publish updates to (JS, HTML, CSS and images), and that apps can query for updates from (using the provided client SDKs for [Cordova](http://github.com/Microsoft/cordova-plugin-code-push) and [React Native](http://github.com/Microsoft/react-native-code-push)). This allows you to have a more deterministic and direct engagement model with your user base, when addressing bugs and/or adding small features that don't require you to re-build a binary and re-distribute it through the respective app stores. - -![CodePush CLI](https://cloud.githubusercontent.com/assets/245892/26749409/feb439f6-47d7-11e7-98fd-07d750b856d8.png) - - - -* [Installation](#installation) -* [Getting Started](#getting-started) -* [Account Management](#account-management) - * [Authentication](#authentication) - * [Access Keys](#access-keys) - * [Proxy Support](#proxy-support) -* [App Management](#app-management) - * [App Collaboration](#app-collaboration) - * [Ownership Transfer](#ownership-transfer) - * [Deployment Management](#deployment-management) -* [Releasing Updates](#releasing-updates) - * [Releasing Updates (General)](#releasing-updates-general) - * [Releasing Updates (React Native)](#releasing-updates-react-native) - * [Releasing Updates (Cordova)](#releasing-updates-cordova) -* [Debugging CodePush Integration](#debugging-codepush-integration) -* [Patching Update Metadata](#patching-update-metadata) -* [Promoting Updates](#promoting-updates) -* [Rolling Back Updates](#rolling-back-updates) -* [Viewing Release History](#viewing-release-history) -* [Clearing Release History](#clearing-release-history) -* [Code Signing](#code-signing) - -[[Chinese version 中文版]](./README-cn.md) - - - -## Installation - -* Install [Node.js](https://nodejs.org/) -* Install the CodePush CLI: `npm install -g code-push-cli` - -## Getting Started - -1. Create a [CodePush account](#account-creation) push using the CodePush CLI -2. Register your [app](#app-management) with CodePush, and optionally [share it](#app-collaboration) with other developers on your team -3. CodePush-ify your app and point it at the deployment you wish to use ([Cordova](http://github.com/Microsoft/cordova-plugin-code-push) and [React Native](http://github.com/Microsoft/react-native-code-push)) -4. [Release](#releasing-updates) an update for your app -5. Check out the [debug logs](#debugging-codepush-integration) to ensure everything is working as expected -6. Live long and prosper! ([details](https://en.wikipedia.org/wiki/Vulcan_salute)) - -## Account Management - -Before you can begin releasing app updates, you need to create a CodePush account. You can do this by simply running the following command once you've installed the CLI: - -``` -code-push register -``` - -This will launch a browser, asking you to authenticate with either your GitHub or Microsoft account. Once authenticated, it will create a CodePush account "linked" to your GitHub/MSA identity, and generate an access key you can copy/paste into the CLI in order to login. - -*Note: After registering, you are automatically logged-in with the CLI, so until you explicitly log out, you don't need to login again from the same machine.* - -If you have an existing account, you may also link your account to another identity provider (e.g. Microsoft, GitHub) by running: - -``` -code-push link -``` - -*Note: In order to link multiple accounts, the email address associated with each provider must match.* - -### Authentication - -Most commands within the CodePush CLI require authentication, and therefore, before you can begin managing your account, you need to login using the GitHub or Microsoft account you used when registering. You can do this by running the following command: - -```shell -code-push login -``` - -This will launch a browser, asking you to authenticate with either your GitHub or Microsoft account. This will generate an access key that you need to copy/paste into the CLI (it will prompt you for it). You are now successfully authenticated and can safely close your browser window. - -If at any time you want to determine if you're already logged in, you can run the following command to display the e-mail address associated with your current authentication session, which identity providers your account is linked to (e.g. GitHub) and any previously set proxy: - -```shell -code-push whoami -``` - -When you login from the CLI, your access key is persisted to disk for the duration of your session so that you don't have to login every time you attempt to access your account. In order to end your session and delete this access key, simply run the following command: - -```shell -code-push logout -``` - -If you forget to logout from a machine you'd prefer not to leave a running session on (e.g. your friend's laptop), so you can invalidate it by using one of two choices: - -1. via [Mobile Center site](https://mobile.azure.com/settings/apitokens) -2. via [Mobile Center CLI](https://github.com/Microsoft/mobile-center-cli) commands: - -```shell -mobile-center tokens list -mobile-center tokens delete -``` - -### Access Keys - -If you need to be able to authenticate against the CodePush service without launching a browser and/or without needing to use your GitHub and/or Microsoft credentials (e.g. in a CI environment), you can run the following command to create an "access key" (along with a name describing what it is for): - -```shell -code-push access-key add "VSTS Integration" -``` - -After creating the new key, you can specify its value using the `--accessKey` flag of the `login` command, which allows you to perform "headless" authentication, as opposed to launching a browser. - -```shell -code-push login --accessKey -``` - -When logging in via this method, the access key will not be automatically invalidated on logout, and can be used in future sessions until it is explicitly removed from the CodePush server or expires. However, it is still recommended that you log out once your session is complete, in order to remove your credentials from disk. - -### Proxy Support - -By default, the `login` command will automatically look for a system-wide proxy, specified via an `HTTPS_PROXY` or `HTTP_PROXY` environment variable, and use that to connect to the CodePush server. If you'd like to disable this behavior, and have the CLI establish a direct connection to CodePush, simply specify the `--noProxy` parameter when logging in: - -```shell -code-push login --noProxy -``` - -I'd you like to explicitly specify a proxy server that the CodePush CLI should use, without relying on system-wide settings, you can instead pass the `--proxy` parameter when logging in: - -```shell -code-push login --proxy https://foo.com:3454 -``` - -Once you've logged in, any inferred and/or specified proxy settings are persisted along with your user session. This allows you to continue using the CodePush CLI without needing to re-authenticate or re-specify your preferred proxy. If at any time you want to start or stop using a proxy, simply logout, and then log back in with the newly desired settings. - -Additionally, if at any time you want to see what proxy settings (if any) are being used for your current login setting, simply run the `code-push whoami` command, which will display whether you're using, or explicitly bypassing a proxy. - -![ignoredproxy](https://cloud.githubusercontent.com/assets/116461/16537275/5166abf8-3fb3-11e6-930b-fb6a8164c65d.PNG) - -## App Management - -Before you can deploy any updates, you need to register an app with the CodePush service using the following command: - -``` -code-push app add -``` - -If your app targets both iOS and Android, please *create separate apps for each platform* with CodePush (see the note below for details). This way, you can manage and release updates to them separately, which in the long run, also tends to make things simpler. The naming convention that most folks use is to suffix the app name with `-iOS` and `-Android`. For example: - -``` -code-push app add MyApp-Android android cordova -code-push app add MyApp-iOS ios react-native -``` - -*NOTE: Using the same app for iOS and Android may cause installation exceptions because the CodePush update package produced for iOS will have different content from the update produced for Android.* - -All new apps automatically come with two deployments (`Staging` and `Production`) so that you can begin distributing updates to multiple channels without needing to do anything extra (see deployment instructions below). After you create an app, the CLI will output the deployment keys for the `Staging` and `Production` deployments, which you can begin using to configure your mobile clients via their respective SDKs (details for [Cordova](http://github.com/Microsoft/cordova-plugin-code-push) and [React Native](http://github.com/Microsoft/react-native-code-push)). - -If you decide that you don't like the name you gave to an app, you can rename it at any time using the following command: - -``` -code-push app rename -``` - -The app's name is only meant to be recognizable from the management side, and therefore, you can feel free to rename it as necessary. It won't actually impact the running app, since update queries are made via deployment keys. - -If at some point you no longer need an app, you can remove it from the server using the following command: - -``` -code-push app rm -``` - -Do this with caution since any apps that have been configured to use it will obviously stop receiving updates. - -Finally, if you want to list all apps that you've registered with the CodePush server, -you can run the following command: - -``` -code-push app ls -``` - -### App Collaboration - -If you will be working with other developers on the same CodePush app, you can add them as collaborators using the following command: - -```shell -code-push collaborator add -``` - -*NOTE: This expects the developer to have already [registered](#account-creation) with CodePush using the specified e-mail address, so ensure that they have done that before attempting to share the app with them.* - -Once added, all collaborators will immediately have the following permissions with regards to the newly shared app: - -1. View the app, its collaborators, [deployments](#deployment-management) and [release history](#viewing-release-history) -1. [Release](#releasing-updates) updates to any of the app's deployments -1. [Promote](#promoting-updates) an update between any of the app's deployments -1. [Rollback](#rolling-back-undesired-updates) any of the app's deployments -1. [Patch](#updating-existing-releases) any releases within any of the app's deployments - -Inversely, that means that an app collaborator cannot do any of the following: - -1. Rename or delete the app -1. Create, rename or delete new deployments within the app -1. Clear a deployment's release history -1. Add or remove collaborators from the app (*) - -*NOTE: A developer can remove him/herself as a collaborator from an app that was shared with them.* - -Over time, if someone is no longer working on an app with you, you can remove them as a collaborator using the following command: - -```shell -code-push collaborator rm -``` - -If at any time you want to list all collaborators that have been added to an app, you can simply run the following command: - -```shell -code-push collaborator ls -``` - -### Ownership Transfer - -The update to version 2.0.0.0 saw the removal of the `app transfer` command. You may still transfer ownership of your applications by managing the transfer through an organization. This requires that you visit [Mobile Center](https://mobile.azure.com) and execute a few steps. - -1. Go to to [https://mobile.azure.com](https://mobile.azure.com) and create a new organization. -2. Invite the person you to whom you wish to transfer the app to the organization. Once they have accepted the invitation change their access permissions to "Admin". -3. Navigate to your app and click on the "Manage App" button (top right when on the "Getting Started" page for the app). Hit the Transfer button there to transfer the app to the org. Note that currently this operation cannot be reversed, although this will change in the future. -4. Once your invitee has accepted, select the organization that you created and remove yourself from it. - - -### Deployment Management - -From the CodePush perspective, an app is simply a named grouping for one or more things called "deployments". While the app represents a conceptual "namespace" or "scope" for a platform-specific version of an app (e.g. the iOS port of Foo app), its deployments represent the actual target for releasing updates (for developers) and synchronizing updates (for end-users). Deployments allow you to have multiple "environments" for each app in-flight at any given time, and help model the reality that apps typically move from a dev's personal environment to a testing/QA/staging environment, before finally making their way into production. - -*NOTE: As you'll see below, the `release`, `promote` and `rollback` commands require both an app name and a deployment name in order to work, because it is the combination of the two that uniquely identifies a point of distribution (e.g. I want to release an update of my iOS app to my beta testers).* - -Whenever an app is registered using the CLI, the CodePush service includes two deployments by default: `Staging` and `Production`. This allows you to immediately begin releasing updates to an internal environment (Staging), where you can thoroughly test each update before pushing them out to your end-users (Production). This workflow is critical for ensuring your releases are ready for mass-consumption, and is a practice that has been established in the web for a long time. - -If having a staging and production version of your app is enough to meet your needs, then you don't need to do anything else. However, if you want an alpha, dev, etc. deployment, you can easily create them using the following command: - -``` -code-push deployment add -``` - -Just like with apps, you can remove and rename deployments as well, using the following commands respectively: - -``` -code-push deployment rm -code-push deployment rename -``` - -If at any time you'd like to view the list of deployments that a specific app includes, you can simply run the following command: - -``` -code-push deployment ls [--displayKeys|-k] -``` - -This will display not only the list of deployments, but also the update metadata (e.g. mandatory, description) and installation metrics for their latest release: - -![Deployment list](https://cloud.githubusercontent.com/assets/116461/12526883/7730991c-c127-11e5-9196-98e9ceec758f.png) - -*NOTE: Due to their infrequent use and needed screen real estate, deployment keys aren't displayed by default. If you need to view them, simply make sure to pass the `-k` flag to the `deployment ls` command.* - -The install metrics have the following meaning: - -* **Active** - The number of successful installs that are currently running this release (i.e. if the user opened your app, they would see/run this version). This number will increase and decrease as end-users upgrade to and away from this release, respectively. This metric shows both the total of active users, as well as what percentage of your overall audience that represents. This makes it easy to determine the distribution of updates that your users are currently running, as well as answer questions such as "How many of my users have received my latest update?". - -* **Total** - The total number of successful installations that this update has received overall. This number only ever increases as new users/devices install it, and therefore, this is always a superset of the total active count. An update is considered successful once `notifyApplicationReady` (or `sync`) is called after it was installed. Between the moment that an update is downloaded, and it is marked as being successful, it will be reported as a "pending" update (see below for details). - -* **Pending** - The number of times this release has been downloaded, but not yet installed (i.e. the app was restarted to apply the changes). Therefore, this metric increases as updates are downloaded, and decreases as those corresponding downloaded updates are installed. This metric primarily applies to updates that aren't configured to install immediately, and helps provide the broader picture of release adoption for apps that rely on app resume and/or restart to apply an update (e.g. I want to rollback an update and I'm curious if anyone has downloaded it yet). If you've configured updates to install immediately, and are still seeing pending updates being reported, then it's likely that you're not calling `notifyApplicationReady` (or `sync`) on app start, which is the method that initiates sending install reports and marks installed updates as being considered successful. - -* **Rollbacks** - The number of times that this release has been automatically rolled back on the client. Ideally this number should be zero, and in that case, this metric isn't even shown. However, if you released an update that includes a crash as part of the installation process, the CodePush plugin will roll the end-user back to the previous release, and report that issue back to the server. This allows your end-users to remain unblocked in the event of broken releases, and by being able to see this telemetry in the CLI, you can identify erroneous releases and respond to them by [rolling it back](#rolling-back-undesired-updates) on the server. - -* **Rollout** - Indicates the percentage of users that are eligible to receive this update. This property will only be displayed for releases that represent an "active" rollout, and therefore, have a rollout percentage that is less than 100%. Additionally, since a deployment can only have one active rollout at any given time, this label would only be present on the latest release within a deployment. - -* **Disabled** - Indicates whether the release has been marked as disabled or not, and therefore, is downloadable by end users. This property will only be displayed for releases that are actually disabled. - -When the metrics cell reports `No installs recorded`, that indicates that the server hasn't seen any activity for this release. This could either be because it precluded the plugin versions that included telemetry support, or no end-users have synchronized with the CodePush server yet. As soon as an install happens, you will begin to see metrics populate in the CLI for the release. - -## Releasing Updates - -Once your app has been configured to query for updates against the CodePush server, you can begin releasing updates to it. In order to provide both simplicity and flexibility, the CodePush CLI includes three different commands for releasing updates: - -1. [General](#releasing-updates-general) - Releases an update to the CodePush server that was generated by an external tool or build script (e.g. a Gulp task, the `react-native bundle` command). This provides the most flexibility in terms of fitting into existing workflows, since it strictly deals with CodePush-specific step, and leaves the app-specific compilation process to you. - -2. [React Native](#releasing-updates-react-native) - Performs the same functionality as the general release command, but also handles the task of generating the updated app contents for you (JS bundle and assets), instead of requiring you to run both `react-native bundle` and then `code-push release`. - -3. [Cordova](#releasing-updates-cordova) - Performs the same functionality as the general release command, but also handles the task of preparing the app update for you, instead of requiring you to run both `cordova prepare` (or `phonegap prepare`) and then `code-push release`. - -Which of these commands you should use is mostly a matter of requirements and/or preference. However, we generally recommend using the relevant platform-specific command to start (since it greatly simplifies the experience), and then leverage the general-purpose `release` command if/when greater control is needed. - -*NOTE: Only the 50 most recent releases in a deployment can be discovered and downloaded by the clients.* - -### Releasing Updates (General) - -``` -code-push release -[--deploymentName ] -[--description ] -[--disabled ] -[--mandatory] -[--noDuplicateReleaseError] -[--rollout ] -[--privateKeyPath ] -``` - -#### App name parameter - -This specifies the name of the CodePush app that this update is being released for. This value corresponds to the friendly name that you specified when originally calling `code-push app add` (e.g. "MyApp-Android"). If you need to look it up, you can run the `code-push app ls` command to see your list of apps. - -#### Update contents parameter - -This specifies the location of the updated app code and assets you want to release. You can provide either a single file (e.g. a JS bundle for a React Native app), or a path to a directory (e.g. the `/platforms/ios/www` folder for a Cordova app). Note that you don't need to ZIP up multiple files or directories in order to deploy those changes, since the CLI will automatically ZIP them for you. - -It's important that the path you specify refers to the platform-specific, prepared/bundled version of your app. The following table outlines which command you should run before releasing, as well as the location you can subsequently refer to using the `updateContents` parameter: - -| Platform | Prepare command | Package path (relative to project root) | -|----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------| -| Cordova (Android) | `cordova prepare android` | For `cordova-android` version **7 and later**: `./platforms/android/app/src/main/assets/www` directory;
For `cordova-android` version **6 and earlier**: `./platforms/android/assets/www` directory; | -| Cordova (iOS) | `cordova prepare ios` | `./platforms/ios/www ` directory | -| React Native wo/assets (Android) | `react-native bundle --platform android --entry-file --bundle-output --dev false` | Value of the `--bundle-output` option | -| React Native w/assets (Android) | `react-native bundle --platform android --entry-file --bundle-output / --assets-dest --dev false` | Value of the `--assets-dest` option, which should represent a newly created directory that includes your assets and JS bundle | -| React Native wo/assets (iOS) | `react-native bundle --platform ios --entry-file --bundle-output --dev false` | Value of the `--bundle-output` option | -| React Native w/assets (iOS) | `react-native bundle --platform ios --entry-file --bundle-output / --assets-dest --dev false` | Value of the `--assets-dest` option, which should represent a newly created directory that includes your assets and JS bundle | - -#### Target binary version parameter - -This specifies the store/binary version of the application you are releasing the update for, so that only users running that version will receive the update, while users running an older and/or newer version of the app binary will not. This is useful for the following reasons: - -1. If a user is running an older binary version, it's possible that there are breaking changes in the CodePush update that wouldn't be compatible with what they're running. - -2. If a user is running a newer binary version, then it's presumed that what they are running is newer (and potentially incompatible) with the CodePush update. - -If you ever want an update to target multiple versions of the app store binary, we also allow you to specify the parameter as a [semver range expression](https://github.com/npm/node-semver#advanced-range-syntax). That way, any client device running a version of the binary that satisfies the range expression (i.e. `semver.satisfies(version, range)` returns `true`) will get the update. Examples of valid semver range expressions are as follows: - -| Range Expression | Who gets the update | -|------------------|----------------------------------------------------------------------------------------| -| `1.2.3` | Only devices running the specific binary app store version `1.2.3` of your app | -| `*` | Any device configured to consume updates from your CodePush app | -| `1.2.x` | Devices running major version 1, minor version 2 and any patch version of your app | -| `1.2.3 - 1.2.7` | Devices running any binary version between `1.2.3` (inclusive) and `1.2.7` (inclusive) | -| `>=1.2.3 <1.2.7` | Devices running any binary version between `1.2.3` (inclusive) and `1.2.7` (exclusive) | -| `1.2` | Equivalent to `>=1.2.0 <1.3.0` | -| `~1.2.3` | Equivalent to `>=1.2.3 <1.3.0` | -| `^1.2.3` | Equivalent to `>=1.2.3 <2.0.0` | - -*NOTE: If your semver expression starts with a special shell character or operator such as `>`, `^`, or ** -*, the command may not execute correctly if you do not wrap the value in quotes as the shell will not supply the right values to our CLI process. Therefore, it is best to wrap your `targetBinaryVersion` parameter in double quotes when calling the `release` command, e.g. `code-push release MyApp-iOS updateContents ">1.2.3"`.* - -*NOTE: As defined in the semver spec, ranges only work for non pre-release versions: https://github.com/npm/node-semver#prerelease-tags. If you want to update a version with pre-release tags, then you need to write the exact version you want to update (`1.2.3-beta` for example).* - -The following table outlines the version value that CodePush expects your update's semver range to satisfy for each respective app type: - -| Platform | Source of app store version | -|------------------------|------------------------------------------------------------------------------| -| Cordova | The `` attribute in the `config.xml` file | -| React Native (Android) | The `android.defaultConfig.versionName` property in your `build.gradle` file | -| React Native (iOS) | The `CFBundleShortVersionString` key in the `Info.plist` file | -| React Native (Windows) | The `` key in the `Package.appxmanifest` file | - -*NOTE: If the app store version in the metadata files are missing a patch version, e.g. `2.0`, it will be treated as having a patch version of `0`, i.e. `2.0 -> 2.0.0`. The same is true for app store version equal to plain integer number, `1` will be treated as `1.0.0` in this case.* - -#### Deployment name parameter - -This specifies which deployment you want to release the update to. This defaults to `Staging`, but when you're ready to deploy to `Production`, or one of your own custom deployments, just explicitly set this argument. - -*NOTE: The parameter can be set using either "--deploymentName" or "-d".* - -#### Description parameter - -This provides an optional "change log" for the deployment. The value is simply round tripped to the client so that when the update is detected, your app can choose to display it to the end-user (e.g. via a "What's new?" dialog). This string accepts control characters such as `\n` and `\t` so that you can include whitespace formatting within your descriptions for improved readability. - -*NOTE: This parameter can be set using either "--description" or "--des"* - -#### Disabled parameter - -This specifies whether an update should be downloadable by end users or not. If left unspecified, the update will not be disabled (i.e. users will download it the moment your app calls `sync`). This parameter can be valuable if you want to release an update that isn't immediately available, until you expicitly [patch it](#patching-releases) when you want end users to be able to download it (e.g. an announcement blog post went live). - -*NOTE: This parameter can be set using either "--disabled" or "-x"* - -#### Mandatory parameter - -This specifies whether the update should be considered mandatory or not (e.g. it includes a critical security fix). This attribute is simply round tripped to the client, who can then decide if and how they would like to enforce it. - -*NOTE: This parameter is simply a "flag", and therefore, its absence indicates that the release is optional, and its presence indicates that it's mandatory. You can provide a value to it (e.g. `--mandatory true`), however, simply specifying `--mandatory` is sufficient for marking a release as mandatory.* - -The mandatory attribute is unique because the server will dynamically modify it as necessary in order to ensure that the semantics of your releases are maintained for your end-users. For example, imagine that you released the following three updates to your app: - -| Release | Mandatory? | -|---------|------------| -| v1 | No | -| v2 | Yes | -| v3 | No | - -If an end-user is currently running `v1`, and they query the server for an update, it will respond with `v3` (since that is the latest), but it will dynamically convert the release to mandatory, since a mandatory update was released in between. This behavior is important since the code contained in `v3` is incremental to that included in `v2`, and therefore, whatever made `v2` mandatory, continues to make `v3` mandatory for anyone that didn't already acquire `v2`. - -If an end-user is currently running `v2`, and they query the server for an update, it will respond with `v3`, but leave the release as optional. This is because they already received the mandatory update, and therefore, there isn't a need to modify the policy of `v3`. This behavior is why we say that the server will "dynamically convert" the mandatory flag, because as far as the release goes, its mandatory attribute will always be stored using the value you specified when releasing it. It is only changed on-the-fly as necessary when responding to an update check from an end-user. - -If you never release an update that is marked as mandatory, then the above behavior doesn't apply to you, since the server will never change an optional release to mandatory unless there were intermingled mandatory updates as illustrated above. Additionally, if a release is marked as mandatory, it will never be converted to optional, since that wouldn't make any sense. The server will only change an optional release to mandatory in order to respect the semantics described above. - -*NOTE: This parameter can be set using either `--mandatory` or `-m`* - -#### No duplicate release error parameter - -This specifies that if the update is identical to the latest release on the deployment, the CLI should generate a warning instead of an error. This is useful for continuous integration scenarios where it is expected that small modifications may trigger releases where no production code has changed. - -#### Rollout parameter - -**IMPORTANT: In order for this parameter to actually take affect, your end users need to be running version `1.6.0-beta+` (for Cordova) or `1.9.0-beta+` (for React Native) of the CodePush plugin. If you release an update that specifies a rollout property, no end user running an older version of the Cordova or React Native plugins will be eligible for the update. Therefore, until you have adopted the neccessary version of the platform-specific CodePush plugin (as previously mentioned), we would advise not setting a rollout value on your releases, since no one would end up receiving it.** - -This specifies the percentage of users (as an integer between `1` and `100`) that should be eligible to receive this update. It can be helpful if you want to "flight" new releases with a portion of your audience (e.g. 25%), and get feedback and/or watch for exceptions/crashes, before making it broadly available for everyone. If this parameter isn't set, it is set to `100%`, and therefore, you only need to set it if you want to actually limit how many users will receive it. - - When leveraging the rollout capability, there are a few additional considerations to keep in mind: - -1. You cannot release a new update to a deployment whose latest release is an "active" rollout (i.e. its rollout property is non-null). The rollout needs to be "completed" (i.e. setting the `rollout` property to `100`) before you can release further updates to the deployment. - -2. If you rollback a deployment whose latest release is an "active" rollout, the rollout value will be cleared, effectively "deactivating" the rollout behavior - -3. Unlike the `mandatory` and `description` fields, when you promote a release from one deployment to another, it will not propagate the `rollout` property, and therefore, if you want the new release (in the target deployment) to have a rollout value, you need to explicitly set it when you call the `promote` command. - -*NOTE: This parameter can be set using either `--rollout` or `-r`* - -#### Private key path parameter - -This parameter specifies a path to the private key file used to generate the signature of the update. If the private key path parameter is omitted, signature verification in the code-push plugin will be ignored. - -Please refer to the [Code Signing section](#code-signing) for more details on the Code Signing feature. - -* NOTE: This option is supported only for React Native applications on Android and iOS platforms.* - -### Releasing Updates (React Native) - -```shell -code-push release-react -[--bundleName ] -[--deploymentName ] -[--description ] -[--development ] -[--disabled ] -[--entryFile ] -[--gradleFile ] -[--mandatory] -[--noDuplicateReleaseError] -[--outputDir ] -[--plistFile ] -[--plistFilePrefix ] -[--sourcemapOutput ] -[--targetBinaryVersion ] -[--rollout ] -[--privateKeyPath ] -[--config ] -``` - -The `release-react` command is a React Native-specific version of the "vanilla" [`release`](#releasing-app-updates) command, which supports all of the same parameters (e.g. `--mandatory`, `--description`), yet simplifies the process of releasing updates by performing the following additional behavior: - -1. Running the `react-native bundle` command in order to generate the [update contents](#update-contents-parameter) (JS bundle and assets) that will be released to the CodePush server. It uses sensible defaults as much as possible (e.g. creating a non-dev build, assuming an iOS entry file is named `index.ios.js`), but also exposes the relevant `react-native bundle` parameters to enable flexibility (e.g. `--sourcemapOutput`). - -2. Inferring the [`targetBinaryVersion`](#target-binary-version-parameter) of this release by using the version name that is specified in your project's `Info.plist` (for iOS) and `build.gradle` (for Android) files. - -To illustrate the difference that the `release-react` command can make, the following is an example of how you might generate and release an update for a React Native app using the "vanilla" `release` command: - -```shell -mkdir ./CodePush - -react-native bundle --platform ios \ ---entry-file index.ios.js \ ---bundle-output ./CodePush/main.jsbundle \ ---assets-dest ./CodePush \ ---dev false - -code-push release MyApp-iOS ./CodePush 1.0.0 -``` - -Achieving the equivalent behavior with the `release-react` command would simply require the following command, which is generally less error-prone: - -```shell -code-push release-react MyApp-iOS ios -``` - -*NOTE: We believe that the `release-react` command should be valuable for most React Native developers, so if you're finding that it isn't flexible enough or missing a key feature, please don't hesistate to [let us know](mailto:codepushfeed@microsoft.com), so that we can improve it!* - -#### App name parameter - -This is the same parameter as the one described in the [above section](#app-name-parameter). - -#### Platform parameter - -This specifies which platform the current update is targeting, and can be either `android`, `ios` or `windows` (case-insensitive). This value is only used to determine how to properly bundle your update contents and isn't actually sent to the server. - -#### Deployment name parameter - -This is the same parameter as the one described in the [above section](#deployment-name-parameter). - -#### Description parameter - -This is the same parameter as the one described in the [above section](#description-parameter). - -#### Mandatory parameter - -This is the same parameter as the one described in the [above section](#mandatory-parameter). - -#### No duplicate release error parameter - -This is the same parameter as the one described in the [above section](#no-duplicate-release-error-parameter). - -#### Rollout parameter - -This is the same parameter as the one described in the [above section](#rollout-parameter). If left unspecified, the release will be made available to all users. - -#### Target binary version parameter - -This is the same parameter as the one described in the [above section](#target-binary-version-parameter). If left unspecified, this defaults to targeting the exact version specified in the app's `Info.plist` (for iOS) and `build.gradle` (for Android) files. - -#### Bundle name parameter - -This specifies the file name that should be used for the generated JS bundle. If left unspecified, the standard bundle name will be used for the specified platform: `main.jsbundle` (iOS), `index.android.bundle` (Android) and `index.windows.bundle` (Windows). - -*NOTE: This parameter can be set using either --bundleName or -b* - -#### Development parameter - -This specifies whether to generate a unminified, development JS bundle. If left unspecified, this defaults to `false` where warnings are disabled and the bundle is minified. - -*NOTE: This parameter can be set using either --development or --dev* - -#### Disabled parameter - -This is the same parameter as the one described in the [above section](#disabled-parameter). - -#### Entry file parameter - -This specifies the relative path to the app's root/entry JavaScript file. If left unspecified, this defaults to `index.ios.js` (for iOS), `index.android.js` (for Android) or `index.windows.bundle` (for Windows) if that file exists, or `index.js` otherwise. - -*NOTE: This parameter can be set using either --entryFile or -e* - -#### Gradle file parameter (Android only) - -This specifies the relative path to the `build.gradle` file that the CLI should use when attempting to auto-detect the target binary version for the release. This parameter is only meant for advanced scenarios, since the CLI will automatically be able to find your `build.grade` file in "standard" React Native projects. However, if your gradle file is located in an arbitrary location, that the CLI can't discover, then using this parameter allows you to continue releasing CodePush updates, without needing to explicitly set the `--targetBinaryVersion` parameter. Since `build.gradle` is a required file name, specifying the path to the containing folder or the full path to the file itself will both achieve the same effect. - -```shell -code-push release-react MyApp-Android android -p "./foo/bar/" -code-push release-react MyApp-Android android -p "./foo/bar/build.gradle" -``` - -#### Plist file parameter (iOS only) - -This specifies the relative path to the `Info.plist` file that the CLI should use when attempting to auto-detect the target binary version for the release. This parameter is only meant for advanced scenarios, since the CLI will automatically be able to find your `Info.plist` file in "standard" React Native projects, and you can use the `--plistFilePrefix` parameter in order to support per-environment plist files (e.g. `STAGING-Info.plist`). However, if your plist is located in an arbitrary location, that the CLI can't discover, then using this parameter allows you to continue releasing CodePush updates, without needing to explicitly set the `--targetBinaryVersion` parameter. - -```shell -code-push release-react MyApp-iOS ios -p "./foo/bar/MyFile.plist" -``` - -*NOTE: This parameter can be set using either --plistFile or -p* - -#### Private key path parameter - -This is the same parameter as the one described in the [above section](#private-key-path-parameter). - -#### Plist file prefix parameter (iOS only) - -This specifies the file name prefix of the `Info.plist` file that that CLI should use when attempting to auto-detect the target binary version for the release. This can be useful if you've created per-environment plist files (e.g. `DEV-Info.plist`, `STAGING-Info.plist`), and you want to be able to release CodePush updates without needing to explicity set the `--targetBinaryVersion` parameter. By specifying a `--plistFilePrefx`, the CLI will look for a file named `-Info.plist`, instead of simply `Info.plist` (which is the default behavior), in the following locations: `./ios` and `./ios/`. If your plist file isn't located in either of those directories (e.g. your app is a native iOS app with embedded RN views), or uses an entirely different file naming convention, then consider using the `--plistFile` parameter. - -```shell -# Auto-detect the target binary version of this release by looking up the -# app version within the STAGING-Info.plist file in either the ./ios or ./ios/ directories. -code-push release-react MyApp-iOS ios --pre "STAGING" - -# Tell the CLI to use your dev plist (`DEV-Info.plist`). -# Note that the hyphen separator can be explicitly stated. -code-push release-react MyApp-iOS ios --pre "DEV-" -``` - -*NOTE: This parameter can be set using either --plistFilePrefix or --pre* - -#### Sourcemap output parameter - -This specifies the relative path to where the generated JS bundle's sourcemap file should be written. If left unspecified, sourcemaps will not be generated. - -*NOTE: This parameter can be set using either --sourcemapOutput or -s* - -#### Output directory parameter - -This specifies the relative path to where the assets, JS bundle and sourcemap files should be written. If left unspecified, the assets, JS bundle and sourcemap will be copied to the `/tmp/CodePush` folder. - -*NOTE: All contents within specified folder will be deleted before copying* - -*NOTE: This parameter can be set using either --outputDir or -o* - -### Releasing Updates (Cordova) - -```shell -code-push release-cordova -[--build] -[--deploymentName ] -[--description ] -[--isReleaseBuildType] -[--mandatory] -[--noDuplicateReleaseError] -[--rollout ] -[--targetBinaryVersion ] -``` - -The `release-cordova` command is a Cordova-specific version of the "vanilla" [`release`](#releasing-app-updates) command, which supports all of the same parameters (e.g. `--mandatory`, `--description`), yet simplifies the process of releasing updates by performing the following additional behavior: - -1. Running the `cordova prepare` (or `phonegap prepare`) command in order to generate the [update contents](#update-contents-parameter) (`www` folder) that will be released to the CodePush server. - -2. Inferring the [`targetBinaryVersion`](#target-binary-version-parameter) of this release by using the version name that is specified in your project's `config.xml` file. - -To illustrate the difference that the `release-cordova` command can make, the following is an example of how you might generate and release an update for a Cordova app using the "vanilla" `release` command: - -```shell -cordova prepare ios -code-push release MyApp-iOS ./platforms/ios/www 1.0.0 -``` - -Achieving the equivalent behavior with the `release-cordova` command would simply require the following command, which is generally less error-prone: - -```shell -code-push release-cordova MyApp-iOS ios -``` - -*NOTE: We believe that the `release-cordova` command should be valuable for most Cordova developers, so if you're finding that it isn't flexible enough or missing a key feature, please don't hesistate to [let us know](mailto:codepushfeed@microsoft.com), so that we can improve it.* - -#### App name parameter - -This is the same parameter as the one described in the [above section](#app-name-parameter). - -#### Platform parameter - -This specifies which platform the current update is targeting, and can be either `ios` or `android` (case-insensitive). - -#### Build parameter - -Specifies whether you want to run `cordova build` instead of `cordova prepare` (which is the default behavior), when generating your updated web assets. This is valuable if your project includes before and/or after build hooks (e.g. to transpile TypeScript), and therefore, having CodePush simply run `cordova prepare` isn't sufficient to create and release an update. If left unspecified, this defaults to `false`. - -*NOTE: This parameter can be set using either --build or -b* - -#### Deployment name parameter - -This is the same parameter as the one described in the [above section](#deployment-name-parameter). - -#### Description parameter - -This is the same parameter as the one described in the [above section](#description-parameter). - -#### Disabled parameter - -This is the same parameter as the one described in the [above section](#disabled-parameter). - -#### IsReleaseBuildType parameter - -If `build` option is true specifies whether perform a release build. If left unspecified, this defaults to `debug`. - -#### Mandatory parameter - -This is the same parameter as the one described in the [above section](#mandatory-parameter). - -#### No duplicate release error parameter - -This is the same parameter as the one described in the [above section](#no-duplicate-release-error-parameter). - -#### Rollout parameter - -This is the same parameter as the one described in the [above section](#rollout-parameter). If left unspecified, the release will be made available to all users. - -#### Target binary version parameter - -This is the same parameter as the one described in the [above section](#target-binary-version-parameter). If left unspecified, the command defaults to targeting only the specified version in the project's metadata (`Info.plist` if this update is for iOS clients, and `build.gradle` for Android clients). - -## Debugging CodePush Integration - -Once you've released an update, and the Cordova or React Native plugin has been integrated into your app, it can be helpful to diagnose how the plugin is behaving, especially if you run into an issue and want to understand why. In order to debug the CodePush update discovery experience, you can run the following command in order to easily view the diagnostic logs produced by the CodePush plugin within your app: - -```shell -code-push debug - -# View all CodePush logs from a running -# instace of the iOS simulator. -code-push debug ios - -# View all CodePush logs from a running -# Android emulator or attached device. -code-push debug android -``` - - - -Under the covers, this command simply automates the usage of the iOS system logs and ADB logcat, but provides a platform-agnostic, filtered view of all logs coming from the CodePush plugin, for both Cordova or React Native. This way, you don't need to learn and/or use another tool simply to be able to answer basic questions about how CodePush is behaving. - -*NOTE: The debug command supports both emulators and devices for Android, but currently only supports listening to logs from the iOS simulator. We hope to add device support soon.* - -## Patching Update Metadata - -After releasing an update, there may be scenarios where you need to modify one or more of the metadata attributes associated with it (e.g. you forgot to mark a critical bug fix as mandatory, you want to increase the rollout percentage of an update). You can easily do this by running the following command: - -```shell -code-push patch -[--label ] -[--mandatory ] -[--description ] -[--rollout ] -[--disabled ] -[--targetBinaryVersion ] -``` - -*NOTE: This command doesn't allow modifying the actual update contents of a release (e.g. `www` folder of a Cordova app). If you need to respond to a release that has been identified as being broken, you should use the [rollback](#rolling-back-updates) command to immediately roll it back, and then if necessary, release a new update with the approrpriate fix when it is available.* - -Aside from the `appName` and `deploymentName`, all parameters are optional, and therefore, you can use this command to update just a single attribute or all of them at once. Calling the `patch` command without specifying any attribute flag will result in a no-op. - -```shell -# Mark the latest production release as mandatory -code-push patch MyApp-iOS Production -m - -# Increase the rollout for v23 to 50% -code-push patch MyApp-iOS Production -l v23 -rollout 50% -``` - -### Label parameter - -Indicates which release (e.g. `v23`) you want to update within the specified deployment. If ommitted, the requested changes will be applied to the latest release in the specified deployment. In order to look up the label for the release you want to update, you can run the `code-push deployment history` command and refer to the `Label` column. - -*NOTE: This parameter can be set using either `--label` or `-l`* - -### Mandatory parameter - -This is the same parameter as the one described in the [above section](#mandatory-parameter), and simply allows you to update whether the release should be considered mandatory or not. Note that `--mandatory` and `--mandatory true` are equivalent, but the absence of this flag is not equivalent to `--mandatory false`. Therefore, if the parameter is ommitted, no change will be made to the value of the target release's mandatory property. You need to set this to `--mandatory false` to explicitly make a release optional. - -### Description parameter - -This is the same parameter as the one described in the [above section](#description-parameter), and simply allows you to update the description associated with the release (e.g. you made a typo when releasing, or you forgot to add a description at all). If this parameter is ommitted, no change will be made to the value of the target release's description property. - -### Disabled parameter - -This is the same parameter as the one described in the [above section](#disabled-parameter), and simply allows you to update whether the release should be disabled or not. Note that `--disabled` and `--disabled true` are equivalent, but the absence of this flag is not equivalent to `--disabled false`. Therefore, if the paremeter is ommitted, no change will be made to the value of the target release's disabled property. You need to set this to `--disabled false` to explicity make a release acquirable if it was previously disabled. - -### Rollout parameter - -This is the same parameter as the one described in the [above section](#rollout-parameter), and simply allows you to increase the rollout percentage of the target release. This parameter can only be set to an integer whose value is greater than the current rollout value. Additionally, if you want to "complete" the rollout, and therefore, make the release available to everyone, you can simply set this parameter to `--rollout 100`. If this parameter is ommitted, no change will be made to the value of the target release's rollout parameter. - -Additionally, as mentioned above, when you release an update without a rollout value, it is treated equivalently to setting the rollout to `100`. Therefore, if you released an update without a rollout, you cannot change the rollout property of it via the `patch` command since that would be considered lowering the rollout percentage. - -### Target binary version parameter - -This is the same parameter as the one described in the [above section](#target-binary-version-parameter), and simply allows you to update the semver range that indicates which binary version(s) a release is compatible with. This can be useful if you made a mistake when originally releasing an update (e.g. you specified `1.0.0` but meant `1.1.0`) or you want to increase or decrease the version range that a release supports (e.g. you discovered that a release doesn't work with `1.1.2` after all). If this paremeter is ommitted, no change will be made to the value of the target release's version property. - -```shell -# Add a "max binary version" to an existing release -# by scoping its eligibility to users running >= 1.0.5 -code-push patch MyApp-iOS Staging -t "1.0.0 - 1.0.5" -``` - -## Promoting Updates - -Once you've tested an update against a specific deployment (e.g. `Staging`), and you want to promote it "downstream" (e.g. dev->staging, staging->production), you can simply use the following command to copy the release from one deployment to another: - -``` -code-push promote -[--description ] -[--label