@appzung/react-native-code-push 6.3.1 → 7.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CodePush.js +10 -7
- package/CodePush.podspec +2 -2
- package/README.md +35 -21
- package/SECURITY.md +41 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +10 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java +14 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/FileUtils.java +8 -9
- package/android/app/src/main/java/com/microsoft/codepush/react/TLSSocketFactory.java +72 -0
- package/android/codepush.gradle +11 -8
- package/docs/multi-deployment-testing-android.md +1 -1
- package/docs/multi-deployment-testing-ios.md +1 -1
- package/docs/setup-android.md +7 -6
- package/docs/setup-ios.md +5 -5
- package/docs/setup-windows.md +37 -4
- package/ios/CodePush/CodePush.m +26 -11
- package/ios/CodePush/CodePushUpdateUtils.m +1 -1
- package/ios/CodePush.xcodeproj/project.pbxproj +2 -2
- package/package.json +16 -16
- package/windows/CodePush/CodePush.def +3 -0
- package/windows/CodePush/CodePush.vcxproj +199 -0
- package/windows/CodePush/CodePush.vcxproj.filters +91 -0
- package/windows/CodePush/CodePushConfig.cpp +104 -0
- package/windows/CodePush/CodePushConfig.h +66 -0
- package/windows/CodePush/CodePushConfig.idl +12 -0
- package/windows/CodePush/CodePushDownloadHandler.cpp +73 -0
- package/windows/CodePush/CodePushDownloadHandler.h +32 -0
- package/windows/CodePush/CodePushNativeModule.cpp +934 -0
- package/windows/CodePush/CodePushNativeModule.h +247 -0
- package/windows/CodePush/CodePushPackage.cpp +456 -0
- package/windows/CodePush/CodePushPackage.h +49 -0
- package/windows/CodePush/CodePushTelemetryManager.cpp +213 -0
- package/windows/CodePush/CodePushTelemetryManager.h +29 -0
- package/windows/CodePush/CodePushUpdateUtils.cpp +86 -0
- package/windows/CodePush/CodePushUpdateUtils.h +38 -0
- package/windows/CodePush/CodePushUtils.cpp +29 -0
- package/windows/CodePush/CodePushUtils.h +18 -0
- package/windows/CodePush/FileUtils.cpp +131 -0
- package/windows/CodePush/FileUtils.h +28 -0
- package/windows/CodePush/PropertySheet.props +16 -0
- package/windows/CodePush/ReactPackageProvider.cpp +15 -0
- package/windows/CodePush/ReactPackageProvider.h +22 -0
- package/windows/CodePush/ReactPackageProvider.idl +9 -0
- package/windows/CodePush/miniz/LICENSE +22 -0
- package/windows/CodePush/miniz/miniz.c +7657 -0
- package/windows/CodePush/miniz/miniz.h +1338 -0
- package/windows/CodePush/miniz/readme.md +37 -0
- package/windows/CodePush/packages.config +4 -0
- package/windows/CodePush/pch.cpp +1 -0
- package/windows/CodePush/pch.h +4 -0
- package/{windows → windows-legacy}/CodePush/CodePush.csproj +1 -1
- package/{windows → windows-legacy}/CodePush.Net46/packages.config +1 -1
- package/windows-legacy/CodePush.Net46.Test/ApplicationDataContainerTest.cs +105 -0
- package/windows-legacy/CodePush.Net46.Test/CodePush.Net46.Test.csproj +137 -0
- package/windows-legacy/CodePush.Net46.Test/Properties/AssemblyInfo.cs +36 -0
- package/windows-legacy/CodePush.Net46.Test/TelemetryManagerTest.cs +117 -0
- package/windows-legacy/CodePush.Net46.Test/app.config +11 -0
- package/windows-legacy/CodePush.Net46.Test/packages.config +4 -0
- /package/{windows → windows-legacy}/CodePush/CodePushUtils.cs +0 -0
- /package/{windows → windows-legacy}/CodePush/FileUtils.cs +0 -0
- /package/{windows → windows-legacy}/CodePush/Properties/AssemblyInfo.cs +0 -0
- /package/{windows → windows-legacy}/CodePush/Properties/CodePush.rd.xml +0 -0
- /package/{windows → windows-legacy}/CodePush/UpdateManager.cs +0 -0
- /package/{windows → windows-legacy}/CodePush/UpdateUtils.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Net46/Adapters/Http/HttpProgress.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Net46/Adapters/Storage/ApplicationDataContainer.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Net46/CodePush.Net46.csproj +0 -0
- /package/{windows → windows-legacy}/CodePush.Net46/CodePushUtils.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Net46/FileUtils.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Net46/Properties/AssemblyInfo.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Net46/UpdateManager.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Net46/UpdateUtils.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Shared/CodePush.Shared.projitems +0 -0
- /package/{windows → windows-legacy}/CodePush.Shared/CodePush.Shared.shproj +0 -0
- /package/{windows → windows-legacy}/CodePush.Shared/CodePushConstants.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Shared/CodePushNativeModule.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Shared/CodePushReactPackage.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Shared/CodePushUtils.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Shared/InstallMode.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Shared/MinimumBackgroundListener.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Shared/SettingsManager.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Shared/TelemetryManager.cs +0 -0
- /package/{windows → windows-legacy}/CodePush.Shared/UpdateState.cs +0 -0
package/CodePush.js
CHANGED
|
@@ -180,7 +180,7 @@ async function notifyApplicationReadyInternal() {
|
|
|
180
180
|
return statusReport;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
async function tryReportStatus(statusReport,
|
|
183
|
+
async function tryReportStatus(statusReport, retryOnAppResume) {
|
|
184
184
|
const config = await getConfiguration();
|
|
185
185
|
const previousLabelOrAppVersion = statusReport.previousLabelOrAppVersion;
|
|
186
186
|
const previousDeploymentKey = statusReport.previousDeploymentKey || config.deploymentKey;
|
|
@@ -188,6 +188,10 @@ async function tryReportStatus(statusReport, resumeListener) {
|
|
|
188
188
|
if (statusReport.appVersion) {
|
|
189
189
|
log(`Reporting binary update (${statusReport.appVersion})`);
|
|
190
190
|
|
|
191
|
+
if (!config.deploymentKey) {
|
|
192
|
+
throw new Error("Deployment key is missed");
|
|
193
|
+
}
|
|
194
|
+
|
|
191
195
|
const sdk = getPromisifiedSdk(requestFetchAdapter, config);
|
|
192
196
|
await sdk.reportStatusDeploy(/* deployedPackage */ null, /* status */ null, previousLabelOrAppVersion, previousDeploymentKey);
|
|
193
197
|
} else {
|
|
@@ -205,22 +209,21 @@ async function tryReportStatus(statusReport, resumeListener) {
|
|
|
205
209
|
}
|
|
206
210
|
|
|
207
211
|
NativeCodePush.recordStatusReported(statusReport);
|
|
208
|
-
|
|
212
|
+
retryOnAppResume && retryOnAppResume.remove();
|
|
209
213
|
} catch (e) {
|
|
210
214
|
log(`Report status failed: ${JSON.stringify(statusReport)}`);
|
|
211
215
|
NativeCodePush.saveStatusReportForRetry(statusReport);
|
|
212
216
|
// Try again when the app resumes
|
|
213
|
-
if (!
|
|
214
|
-
resumeListener = async (newState) => {
|
|
217
|
+
if (!retryOnAppResume) {
|
|
218
|
+
const resumeListener = AppState.addEventListener("change", async (newState) => {
|
|
215
219
|
if (newState !== "active") return;
|
|
216
220
|
const refreshedStatusReport = await NativeCodePush.getNewStatusReport();
|
|
217
221
|
if (refreshedStatusReport) {
|
|
218
222
|
tryReportStatus(refreshedStatusReport, resumeListener);
|
|
219
223
|
} else {
|
|
220
|
-
|
|
224
|
+
resumeListener && resumeListener.remove();
|
|
221
225
|
}
|
|
222
|
-
};
|
|
223
|
-
AppState.addEventListener("change", resumeListener);
|
|
226
|
+
});
|
|
224
227
|
}
|
|
225
228
|
}
|
|
226
229
|
}
|
package/CodePush.podspec
CHANGED
|
@@ -10,7 +10,7 @@ Pod::Spec.new do |s|
|
|
|
10
10
|
s.license = package['license']
|
|
11
11
|
s.homepage = package['homepage']
|
|
12
12
|
s.source = { :git => 'https://github.com/appzung/react-native-code-push.git', :tag => "v#{s.version}"}
|
|
13
|
-
s.ios.deployment_target = '
|
|
13
|
+
s.ios.deployment_target = '9.0'
|
|
14
14
|
s.tvos.deployment_target = '9.0'
|
|
15
15
|
s.preserve_paths = '*.js'
|
|
16
16
|
s.library = 'z'
|
|
@@ -20,7 +20,7 @@ Pod::Spec.new do |s|
|
|
|
20
20
|
# Note: Even though there are copy/pasted versions of some of these dependencies in the repo,
|
|
21
21
|
# we explicitly let CocoaPods pull in the versions below so all dependencies are resolved and
|
|
22
22
|
# linked properly at a parent workspace level.
|
|
23
|
-
s.dependency 'React'
|
|
23
|
+
s.dependency 'React-Core'
|
|
24
24
|
s.dependency 'SSZipArchive', '~> 2.2.2'
|
|
25
25
|
s.dependency 'JWT', '~> 3.0.0-beta.12'
|
|
26
26
|
s.dependency 'Base64', '~> 1.1'
|
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ This plugin provides client-side integration for the [CodePush service](https://
|
|
|
39
39
|
|
|
40
40
|
## How does it work?
|
|
41
41
|
|
|
42
|
-
A React Native app is composed of JavaScript files and any accompanying [images](https://
|
|
42
|
+
A React Native app is composed of JavaScript files and any accompanying [images](https://reactnative.dev/docs/image), which are bundled together by the [metro bundler](https://github.com/facebook/metro) and distributed as part of a platform-specific binary (i.e. an `.ipa` or `.apk` file). Once the app is released, updating either the JavaScript code (e.g. making bug fixes, adding new features) or image assets, requires you to recompile and redistribute the entire binary, which of course, includes any review time associated with the store(s) you are publishing to.
|
|
43
43
|
|
|
44
44
|
The CodePush plugin helps get product improvements in front of your end users instantly, by keeping your JavaScript and images synchronized with updates you release to the CodePush server. This way, your app gets the benefits of an offline mobile experience, as well as the "web-like" agility of side-loading updates as soon as they are available. It's a win-win!
|
|
45
45
|
|
|
@@ -74,7 +74,10 @@ We try our best to maintain backwards compatibility of our plugin with previous
|
|
|
74
74
|
| v0.56-v0.58 | v5.4+ *(RN upgraded versions for Android tools)* |
|
|
75
75
|
| v0.59 | v5.6+ *(RN refactored js bundle loader code)* |
|
|
76
76
|
| v0.60-v0.61 | v6.0+ *(RN migrated to Autolinking)* |
|
|
77
|
-
| v0.62
|
|
77
|
+
| v0.62-v0.64 | v6.2+ *(RN removed LiveReload)* |
|
|
78
|
+
| v0.65-v0.69 | v7.2+ *(RN updated iPhone-target-version)* |
|
|
79
|
+
|
|
80
|
+
*NOTE: `react-native-code-push` versions lower than **[v5.7.0](https://github.com/microsoft/react-native-code-push/releases/tag/v5.7.0)** will stop working in the near future. You can find more information in our [documentation](https://github.com/microsoft/code-push/blob/master/migration-notice.md).*
|
|
78
81
|
|
|
79
82
|
We work hard to respond to new RN releases, but they do occasionally break us. We will update this chart with each RN release, so that users can check to see what our "official" support is.
|
|
80
83
|
|
|
@@ -244,7 +247,16 @@ If you would like to display an update confirmation dialog (an "active install")
|
|
|
244
247
|
|
|
245
248
|
### Store Guideline Compliance
|
|
246
249
|
|
|
247
|
-
|
|
250
|
+
Android Google Play and iOS App Store have corresponding guidelines that have rules you should be aware of before integrating the CodePush solution within your application.
|
|
251
|
+
|
|
252
|
+
#### Google play
|
|
253
|
+
|
|
254
|
+
Third paragraph of [Device and Network Abuse](https://support.google.com/googleplay/android-developer/answer/9888379?hl=en) topic describe that updating source code by any method other than Google Play's update mechanism is restricted. But this restriction does not apply to updating javascript bundles.
|
|
255
|
+
> This restriction does not apply to code that runs in a virtual machine and has limited access to Android APIs (such as JavaScript in a webview or browser).
|
|
256
|
+
|
|
257
|
+
That fully allow CodePush as it updates just JS bundles and can't update native code part.
|
|
258
|
+
|
|
259
|
+
#### App Store
|
|
248
260
|
|
|
249
261
|
Paragraph **3.3.2**, since back in 2015's [Apple Developer Program License Agreement](https://developer.apple.com/programs/ios/information/) fully allowed performing over-the-air updates of JavaScript and assets - and in its latest version (20170605) [downloadable here](https://developer.apple.com/terms/) this ruling is even broader:
|
|
250
262
|
|
|
@@ -260,33 +272,35 @@ This is not necessarily the case for `updateDialog`, since it won't force the us
|
|
|
260
272
|
|
|
261
273
|
## Releasing Updates
|
|
262
274
|
|
|
263
|
-
Once your app
|
|
275
|
+
Once your app is configured and distributed to your users, and you have made some JS or asset changes, it's time to release them. The recommended way to release them is using the `release-react` command in the App Center CLI, which will bundle your JavaScript files, asset files, and release the update to the CodePush server.
|
|
276
|
+
|
|
277
|
+
*NOTE: Before you can start releasing updates, please log into App Center by running the `appcenter login` command.*
|
|
264
278
|
|
|
265
|
-
In it's most basic form, this command only requires
|
|
279
|
+
In it's the most basic form, this command only requires one parameter: your owner name + "/" + app name.
|
|
266
280
|
|
|
267
281
|
```shell
|
|
268
|
-
|
|
282
|
+
appcenter codepush release-react -a <ownerName>/<appName>
|
|
269
283
|
|
|
270
|
-
|
|
271
|
-
|
|
284
|
+
appcenter codepush release-react -a <ownerName>/MyApp-iOS
|
|
285
|
+
appcenter codepush release-react -a <ownerName>/MyApp-Android
|
|
272
286
|
```
|
|
273
287
|
|
|
274
288
|
The `release-react` command enables such a simple workflow because it provides many sensible defaults (like generating a release bundle, assuming your app's entry file on iOS is either `index.ios.js` or `index.js`). However, all of these defaults can be customized to allow incremental flexibility as necessary, which makes it a good fit for most scenarios.
|
|
275
289
|
|
|
276
290
|
```shell
|
|
277
291
|
# Release a mandatory update with a changelog
|
|
278
|
-
|
|
292
|
+
appcenter codepush release-react -a <ownerName>/MyApp-iOS -m --description "Modified the header color"
|
|
279
293
|
|
|
280
294
|
# Release an update for an app that uses a non-standard entry file name, and also capture
|
|
281
295
|
# the sourcemap file generated by react-native bundle
|
|
282
|
-
|
|
296
|
+
appcenter codepush release-react -a <ownerName>/MyApp-iOS --entry-file MyApp.js --sourcemap-output ../maps/MyApp.map
|
|
283
297
|
|
|
284
298
|
# Release a dev Android build to just 1/4 of your end users
|
|
285
|
-
|
|
299
|
+
appcenter codepush release-react -a <ownerName>/MyApp-Android --rollout 25 --development true
|
|
286
300
|
|
|
287
301
|
# Release an update that targets users running any 1.1.* binary, as opposed to
|
|
288
302
|
# limiting the update to exact version name in the build.gradle file
|
|
289
|
-
|
|
303
|
+
appcenter codepush release-react -a <ownerName>/MyApp-Android --target-binary-version "~1.1.0"
|
|
290
304
|
|
|
291
305
|
```
|
|
292
306
|
|
|
@@ -302,19 +316,19 @@ If you run into any issues, or have any questions/comments/feedback, you can pin
|
|
|
302
316
|
|
|
303
317
|
In our [getting started](#getting-started) docs, we illustrated how to configure the CodePush plugin using a specific deployment key. However, in order to effectively test your releases, it is critical that you leverage the `Staging` and `Production` deployments that are auto-generated when you first created your CodePush app (or any custom deployments you may have created). This way, you never release an update to your end users that you haven't been able to validate yourself.
|
|
304
318
|
|
|
305
|
-
*NOTE: Our client-side rollback feature can help unblock users after installing a release that resulted in a crash, and server-side rollbacks (i.e. `
|
|
319
|
+
*NOTE: Our client-side rollback feature can help unblock users after installing a release that resulted in a crash, and server-side rollbacks (i.e. `appcenter codepush rollback`) allow you to prevent additional users from installing a bad release once it's been identified. However, it's obviously better if you can prevent an erroneous update from being broadly released in the first place.*
|
|
306
320
|
|
|
307
321
|
Taking advantage of the `Staging` and `Production` deployments allows you to achieve a workflow like the following (feel free to customize!):
|
|
308
322
|
|
|
309
|
-
1. Release a CodePush update to your `Staging` deployment using the `
|
|
323
|
+
1. Release a CodePush update to your `Staging` deployment using the `appcenter codepush release-react` command (or `appcenter codepush release` if you need more control)
|
|
310
324
|
|
|
311
325
|
2. Run your staging/beta build of your app, sync the update from the server, and verify it works as expected
|
|
312
326
|
|
|
313
|
-
3. Promote the tested release from `Staging` to `Production` using the `
|
|
327
|
+
3. Promote the tested release from `Staging` to `Production` using the `appcenter codepush promote` command
|
|
314
328
|
|
|
315
329
|
4. Run your production/release build of your app, sync the update from the server and verify it works as expected
|
|
316
330
|
|
|
317
|
-
*NOTE: If you want to
|
|
331
|
+
*NOTE: If you want to take a more cautious approach, you can even choose to perform a "staged rollout" as part of #3, which allows you to mitigate additional potential risk with the update (like did your testing in #2 touch all possible devices/conditions?) by only making the production update available to a percentage of your users (for example `appcenter codepush promote -a <ownerName>/<appName> -s Staging -d Production -r 20`). Then, after waiting for a reasonable amount of time to see if any crash reports or customer feedback comes in, you can expand it to your entire audience by running `appcenter codepush patch -a <ownerName>/<appName> Production -r 100`.*
|
|
318
332
|
|
|
319
333
|
You'll notice that the above steps refer to a "staging build" and "production build" of your app. If your build process already generates distinct binaries per "environment", then you don't need to read any further, since swapping out CodePush deployment keys is just like handling environment-specific config for any other service your app uses (like Facebook). However, if you're looking for examples (**including demo projects**) on how to setup your build process to accommodate this, then refer to the following sections, depending on the platform(s) your app is targeting:
|
|
320
334
|
|
|
@@ -346,10 +360,10 @@ Since we recommend using the `Staging` deployment for pre-release testing of you
|
|
|
346
360
|
|
|
347
361
|
```javascript
|
|
348
362
|
// #1) Create your new deployment to hold releases of a specific app variant
|
|
349
|
-
|
|
363
|
+
appcenter codepush deployment add -a <ownerName>/<appName> test-variant-one
|
|
350
364
|
|
|
351
365
|
// #2) Target any new releases at that custom deployment
|
|
352
|
-
|
|
366
|
+
appcenter codepush release-react -a <ownerName>/<appName> -d test-variant-one
|
|
353
367
|
```
|
|
354
368
|
|
|
355
369
|
*NOTE: The total user count that is reported in your deployment's "Install Metrics" will take into account users that have "switched" from one deployment to another. For example, if your `Production` deployment currently reports having 1 total user, but you dynamically switch that user to `Staging`, then the `Production` deployment would report 0 total users, while `Staging` would report 1 (the user that just switched). This behavior allows you to accurately track your release adoption, even in the event of using a runtime-based deployment redirection solution.*
|
|
@@ -382,7 +396,7 @@ Additionally, if you're looking to get started with React Native + CodePush, and
|
|
|
382
396
|
|
|
383
397
|
The `sync` method includes a lot of diagnostic logging out-of-the-box, so if you're encountering an issue when using it, the best thing to try first is examining the output logs of your app. This will tell you whether the app is configured correctly (like can the plugin find your deployment key?), if the app is able to reach the server, if an available update is being discovered, if the update is being successfully downloaded/installed, etc. We want to continue improving the logging to be as intuitive/comprehensive as possible, so please [let us know](mailto:codepushfeed@microsoft.com) if you find it to be confusing or missing anything.
|
|
384
398
|
|
|
385
|
-
The simplest way to view these logs is to
|
|
399
|
+
The simplest way to view these logs is to add the flag `--debug` for each command. This will output a log stream that is filtered to just CodePush messages. This makes it easy to identify issues, without needing to use a platform-specific tool, or wade through a potentially high volume of logs.
|
|
386
400
|
|
|
387
401
|
<img width="540" alt="screen shot 2016-06-21 at 10 15 42 am" src="https://cloud.githubusercontent.com/assets/116461/16246973/838e2e98-37bc-11e6-9649-685f39e325a0.png">
|
|
388
402
|
|
|
@@ -404,7 +418,7 @@ Now you'll be able to see CodePush logs in either debug or release mode, on both
|
|
|
404
418
|
|-----------------|-------------------|
|
|
405
419
|
| Compilation Error | Double-check that your version of React Native is [compatible](#supported-react-native-platforms) with the CodePush version you are using. |
|
|
406
420
|
| Network timeout / hang when calling `sync` or `checkForUpdate` in the iOS Simulator | Try resetting the simulator by selecting the `Simulator -> Reset Content and Settings..` menu item, and then re-running your app. |
|
|
407
|
-
| Server responds with a `404` when calling `sync` or `checkForUpdate` | Double-check that the deployment key you added to your `Info.plist` (iOS), `build.gradle` (Android) or that you're passing to `sync`/`checkForUpdate`, is in fact correct. You can run `
|
|
421
|
+
| Server responds with a `404` when calling `sync` or `checkForUpdate` | Double-check that the deployment key you added to your `Info.plist` (iOS), `build.gradle` (Android) or that you're passing to `sync`/`checkForUpdate`, is in fact correct. You can run `appcenter codepush deployment list <ownerName>/<appName> --displayKeys` to view the correct keys for your app deployments. |
|
|
408
422
|
| Update not being discovered | Double-check that the version of your running app (like `1.0.0`) matches the version you specified when releasing the update to CodePush. Additionally, make sure that you are releasing to the same deployment that your app is configured to sync with. |
|
|
409
423
|
| Update not being displayed after restart | If you're not calling `sync` on app start (like within `componentDidMount` of your root component), then you need to explicitly call `notifyApplicationReady` on app start, otherwise, the plugin will think your update failed and roll it back. |
|
|
410
424
|
| I've released an update for iOS but my Android app also shows an update and it breaks it | Be sure you have different deployment keys for each platform in order to receive updates correctly |
|
|
@@ -413,7 +427,7 @@ Now you'll be able to see CodePush logs in either debug or release mode, on both
|
|
|
413
427
|
|
|
414
428
|
### Continuous Integration / Delivery
|
|
415
429
|
|
|
416
|
-
In addition to being able to use the CodePush CLI to "manually" release updates, we believe that it's important to create a repeatable and sustainable solution for contiously delivering updates to your app. That way, it's simple enough for you and/or your team to create and maintain the rhythm of performing agile deployments. In order to assist with
|
|
430
|
+
In addition to being able to use the CodePush CLI to "manually" release updates, we believe that it's important to create a repeatable and sustainable solution for contiously delivering updates to your app. That way, it's simple enough for you and/or your team to create and maintain the rhythm of performing agile deployments. In order to assist with setting up a CodePush-based CD pipeline, refer to the following integrations with various CI servers:
|
|
417
431
|
|
|
418
432
|
* [Visual Studio Team Services](https://marketplace.visualstudio.com/items?itemName=ms-vsclient.code-push) - *NOTE: VSTS also has extensions for publishing to [HockeyApp](https://marketplace.visualstudio.com/items?itemName=ms.hockeyapp) and the [Google Play](https://github.com/microsoft/google-play-vsts-extension) store, so it provides a pretty great mobile CD solution in general.*
|
|
419
433
|
* [Travis CI](https://github.com/mondora/code-push-travis-cli)
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.5 BLOCK -->
|
|
2
|
+
|
|
3
|
+
## Security
|
|
4
|
+
|
|
5
|
+
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/).
|
|
6
|
+
|
|
7
|
+
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.
|
|
8
|
+
|
|
9
|
+
## Reporting Security Issues
|
|
10
|
+
|
|
11
|
+
**Please do not report security vulnerabilities through public GitHub issues.**
|
|
12
|
+
|
|
13
|
+
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
|
|
14
|
+
|
|
15
|
+
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).
|
|
16
|
+
|
|
17
|
+
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).
|
|
18
|
+
|
|
19
|
+
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:
|
|
20
|
+
|
|
21
|
+
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
|
22
|
+
* Full paths of source file(s) related to the manifestation of the issue
|
|
23
|
+
* The location of the affected source code (tag/branch/commit or direct URL)
|
|
24
|
+
* Any special configuration required to reproduce the issue
|
|
25
|
+
* Step-by-step instructions to reproduce the issue
|
|
26
|
+
* Proof-of-concept or exploit code (if possible)
|
|
27
|
+
* Impact of the issue, including how an attacker might exploit the issue
|
|
28
|
+
|
|
29
|
+
This information will help us triage your report more quickly.
|
|
30
|
+
|
|
31
|
+
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.
|
|
32
|
+
|
|
33
|
+
## Preferred Languages
|
|
34
|
+
|
|
35
|
+
We prefer all communications to be in English.
|
|
36
|
+
|
|
37
|
+
## Policy
|
|
38
|
+
|
|
39
|
+
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
|
|
40
|
+
|
|
41
|
+
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
|
@@ -693,4 +693,14 @@ public class CodePushNativeModule extends ReactContextBaseJavaModule {
|
|
|
693
693
|
CodePushUtils.log("Clearing updates.");
|
|
694
694
|
mCodePush.clearUpdates();
|
|
695
695
|
}
|
|
696
|
+
|
|
697
|
+
@ReactMethod
|
|
698
|
+
public void addListener(String eventName) {
|
|
699
|
+
// Set up any upstream listeners or background tasks as necessary
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
@ReactMethod
|
|
703
|
+
public void removeListeners(Integer count) {
|
|
704
|
+
// Remove upstream listeners, stop unnecessary background tasks
|
|
705
|
+
}
|
|
696
706
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package com.microsoft.codepush.react;
|
|
2
2
|
|
|
3
|
+
import android.os.Build;
|
|
4
|
+
|
|
3
5
|
import org.json.JSONObject;
|
|
4
6
|
|
|
5
7
|
import java.io.BufferedInputStream;
|
|
@@ -12,6 +14,8 @@ import java.net.MalformedURLException;
|
|
|
12
14
|
import java.net.URL;
|
|
13
15
|
import java.nio.ByteBuffer;
|
|
14
16
|
|
|
17
|
+
import javax.net.ssl.HttpsURLConnection;
|
|
18
|
+
|
|
15
19
|
public class CodePushUpdateManager {
|
|
16
20
|
|
|
17
21
|
private String mDocumentsDirectory;
|
|
@@ -163,6 +167,16 @@ public class CodePushUpdateManager {
|
|
|
163
167
|
try {
|
|
164
168
|
URL downloadUrl = new URL(downloadUrlString);
|
|
165
169
|
connection = (HttpURLConnection) (downloadUrl.openConnection());
|
|
170
|
+
|
|
171
|
+
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP &&
|
|
172
|
+
downloadUrl.toString().startsWith("https")) {
|
|
173
|
+
try {
|
|
174
|
+
((HttpsURLConnection)connection).setSSLSocketFactory(new TLSSocketFactory());
|
|
175
|
+
} catch (Exception e) {
|
|
176
|
+
throw new CodePushUnknownException("Error set SSLSocketFactory. ", e);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
166
180
|
connection.setRequestProperty("Accept-Encoding", "identity");
|
|
167
181
|
bin = new BufferedInputStream(connection.getInputStream());
|
|
168
182
|
|
|
@@ -123,14 +123,13 @@ public class FileUtils {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
private static String validateFileName(String fileName,
|
|
127
|
-
|
|
128
|
-
String canonicalPath = file.getCanonicalPath();
|
|
126
|
+
private static String validateFileName(String fileName, File destinationFolder) throws IOException {
|
|
127
|
+
String destinationFolderCanonicalPath = destinationFolder.getCanonicalPath() + File.separator;
|
|
129
128
|
|
|
130
|
-
File
|
|
131
|
-
String
|
|
129
|
+
File file = new File(destinationFolderCanonicalPath, fileName);
|
|
130
|
+
String canonicalPath = file.getCanonicalPath();
|
|
132
131
|
|
|
133
|
-
if (!canonicalPath.startsWith(
|
|
132
|
+
if (!canonicalPath.startsWith(destinationFolderCanonicalPath)) {
|
|
134
133
|
throw new IllegalStateException("File is outside extraction target directory.");
|
|
135
134
|
}
|
|
136
135
|
|
|
@@ -151,13 +150,13 @@ public class FileUtils {
|
|
|
151
150
|
if (destinationFolder.exists()) {
|
|
152
151
|
deleteFileOrFolderSilently(destinationFolder);
|
|
153
152
|
}
|
|
154
|
-
|
|
153
|
+
|
|
155
154
|
destinationFolder.mkdirs();
|
|
156
155
|
|
|
157
156
|
byte[] buffer = new byte[WRITE_BUFFER_SIZE];
|
|
158
157
|
while ((entry = zipStream.getNextEntry()) != null) {
|
|
159
|
-
String fileName = validateFileName(entry.getName(),
|
|
160
|
-
File file = new File(
|
|
158
|
+
String fileName = validateFileName(entry.getName(), destinationFolder);
|
|
159
|
+
File file = new File(fileName);
|
|
161
160
|
if (entry.isDirectory()) {
|
|
162
161
|
file.mkdirs();
|
|
163
162
|
} else {
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
package com.microsoft.codepush.react;
|
|
2
|
+
|
|
3
|
+
import java.io.IOException;
|
|
4
|
+
import java.net.InetAddress;
|
|
5
|
+
import java.net.Socket;
|
|
6
|
+
import java.net.UnknownHostException;
|
|
7
|
+
import java.security.KeyManagementException;
|
|
8
|
+
import java.security.NoSuchAlgorithmException;
|
|
9
|
+
|
|
10
|
+
import javax.net.ssl.SSLContext;
|
|
11
|
+
import javax.net.ssl.SSLSocket;
|
|
12
|
+
import javax.net.ssl.SSLSocketFactory;
|
|
13
|
+
|
|
14
|
+
public class TLSSocketFactory extends SSLSocketFactory {
|
|
15
|
+
|
|
16
|
+
private SSLSocketFactory delegate;
|
|
17
|
+
|
|
18
|
+
public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
|
|
19
|
+
SSLContext context = SSLContext.getInstance("TLS");
|
|
20
|
+
context.init(null, null, null);
|
|
21
|
+
delegate = context.getSocketFactory();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@Override
|
|
25
|
+
public String[] getDefaultCipherSuites() {
|
|
26
|
+
return delegate.getDefaultCipherSuites();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Override
|
|
30
|
+
public String[] getSupportedCipherSuites() {
|
|
31
|
+
return delegate.getSupportedCipherSuites();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Override
|
|
35
|
+
public Socket createSocket() throws IOException {
|
|
36
|
+
return enableTLSOnSocket(delegate.createSocket());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@Override
|
|
40
|
+
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
|
41
|
+
return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@Override
|
|
45
|
+
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
|
|
46
|
+
return enableTLSOnSocket(delegate.createSocket(host, port));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@Override
|
|
50
|
+
public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
|
|
51
|
+
throws IOException, UnknownHostException {
|
|
52
|
+
return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@Override
|
|
56
|
+
public Socket createSocket(InetAddress host, int port) throws IOException {
|
|
57
|
+
return enableTLSOnSocket(delegate.createSocket(host, port));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@Override
|
|
61
|
+
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
|
|
62
|
+
throws IOException {
|
|
63
|
+
return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private Socket enableTLSOnSocket(Socket socket) {
|
|
67
|
+
if (socket != null && (socket instanceof SSLSocket)) {
|
|
68
|
+
((SSLSocket) socket).setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.2" });
|
|
69
|
+
}
|
|
70
|
+
return socket;
|
|
71
|
+
}
|
|
72
|
+
}
|
package/android/codepush.gradle
CHANGED
|
@@ -17,13 +17,13 @@ void runBefore(String dependentTaskName, Task task) {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
android.buildTypes.each { buildType ->
|
|
21
|
+
// to prevent incorrect long value restoration from strings.xml we need to wrap it with double quotes
|
|
22
|
+
// https://github.com/microsoft/cordova-plugin-code-push/issues/264
|
|
23
|
+
buildType.resValue 'string', "CODE_PUSH_APK_BUILD_TIME", String.format("\"%d\"", System.currentTimeMillis())
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
gradle.projectsEvaluated {
|
|
27
27
|
android.applicationVariants.all { variant ->
|
|
28
28
|
def nodeModulesPath;
|
|
29
29
|
if (config.root) {
|
|
@@ -62,7 +62,10 @@ gradle.projectsEvaluated {
|
|
|
62
62
|
enabled config."bundleIn${targetName}" ||
|
|
63
63
|
config."bundleIn${variant.buildType.name.capitalize()}" ?:
|
|
64
64
|
targetName.toLowerCase().contains("release")
|
|
65
|
-
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
runBefore("merge${targetName}Resources", generateBundledResourcesHash)
|
|
68
|
+
runBefore("merge${targetName}Assets", generateBundledResourcesHash)
|
|
66
69
|
} else {
|
|
67
70
|
def jsBundleDirConfigName = "jsBundleDir${targetName}"
|
|
68
71
|
jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?:
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
The [Android Gradle plugin](https://google.github.io/android-gradle-dsl/current/index.html) allows you to define custom config settings for each "build type" (like debug, release). This mechanism allows you to easily configure your debug builds to use your CodePush staging deployment key and your release builds to use your CodePush production deployment key.
|
|
8
8
|
|
|
9
|
-
*NOTE: As a reminder, you can retrieve these keys by running `
|
|
9
|
+
*NOTE: As a reminder, you can retrieve these keys by running `appcenter codepush deployment list -a <ownerName>/<appName> -k` from your terminal.*
|
|
10
10
|
|
|
11
11
|
To set this up, perform the following steps:
|
|
12
12
|
|
|
@@ -44,7 +44,7 @@ To set this up, perform the following steps:
|
|
|
44
44
|
|
|
45
45
|

|
|
46
46
|
|
|
47
|
-
*NOTE: As a reminder, you can retrieve these keys by running `
|
|
47
|
+
*NOTE: As a reminder, you can retrieve these keys by running `appcenter codepush deployment list -a <ownerName>/<appName> -k` from your terminal.*
|
|
48
48
|
|
|
49
49
|
9. Open your project's `Info.plist` file and change the value of your `CodePushDeploymentKey` entry to `$(CODEPUSH_KEY)`
|
|
50
50
|
|
package/docs/setup-android.md
CHANGED
|
@@ -19,9 +19,10 @@ In order to integrate CodePush into your Android project, please perform the fol
|
|
|
19
19
|
|
|
20
20
|
### Plugin Installation and Configuration for React Native 0.60 version and above (Android)
|
|
21
21
|
|
|
22
|
-
1. In your `android/settings.gradle` file, make the following additions:
|
|
22
|
+
1. In your `android/settings.gradle` file, make the following additions at the end of the file:
|
|
23
23
|
|
|
24
24
|
```gradle
|
|
25
|
+
...
|
|
25
26
|
include ':app', ':react-native-code-push'
|
|
26
27
|
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
|
|
27
28
|
```
|
|
@@ -59,8 +60,8 @@ In order to integrate CodePush into your Android project, please perform the fol
|
|
|
59
60
|
```
|
|
60
61
|
|
|
61
62
|
4. Add the Deployment key to `strings.xml`:
|
|
62
|
-
|
|
63
|
-
To let the CodePush runtime know which deployment it should query for updates, open your app's `strings.xml` file and add a new string named `CodePushDeploymentKey`, whose value is the key of the deployment you want to configure this app against (like the key for the `Staging` deployment for the `FooBar` app). You can retrieve this value by running `
|
|
63
|
+
|
|
64
|
+
To let the CodePush runtime know which deployment it should query for updates, open your app's `strings.xml` file and add a new string named `CodePushDeploymentKey`, whose value is the key of the deployment you want to configure this app against (like the key for the `Staging` deployment for the `FooBar` app). You can retrieve this value by running `appcenter codepush deployment list -a <ownerName>/<appName> -k` in the CodePush CLI (the `-k` flag is necessary since keys aren't displayed by default) and copying the value of the `Key` column which corresponds to the deployment you want to use (see below). Note that using the deployment's name (like Staging) will not work. The "friendly name" is intended only for authenticated management usage from the CLI, and not for public consumption within your app.
|
|
64
65
|
|
|
65
66
|

|
|
66
67
|
|
|
@@ -101,7 +102,7 @@ In order to accommodate as many developer preferences as possible, the CodePush
|
|
|
101
102
|
|
|
102
103
|
*Note: If you don't already have RNPM installed, you can do so by simply running `npm i -g rnpm` and then executing the above command.*
|
|
103
104
|
|
|
104
|
-
2. If you're using RNPM >=1.6.0, you will be prompted for the deployment key you'd like to use. If you don't already have it, you can retrieve this value by running `
|
|
105
|
+
2. If you're using RNPM >=1.6.0, you will be prompted for the deployment key you'd like to use. If you don't already have it, you can retrieve this value by running `appcenter codepush deployment list -a <ownerName>/<appName> -k`, or you can choose to ignore it (by simply hitting `<ENTER>`) and add it in later. To get started, we would recommend just using your `Staging` deployment key, so that you can test out the CodePush end-to-end.
|
|
105
106
|
|
|
106
107
|
And that's it for installation using RNPM! Continue below to the [Plugin Configuration](#plugin-configuration-for-react-native-lower-than-060-android) section to complete the setup.
|
|
107
108
|
|
|
@@ -168,7 +169,7 @@ public class MainApplication extends Application implements ReactApplication {
|
|
|
168
169
|
protected List<ReactPackage> getPackages() {
|
|
169
170
|
// 3. Instantiate an instance of the CodePush runtime and add it to the list of
|
|
170
171
|
// existing packages, specifying the right deployment key. If you don't already
|
|
171
|
-
// have it, you can run "
|
|
172
|
+
// have it, you can run "appcenter codepush deployment list -a <ownerName>/<appName> -k" to retrieve your key.
|
|
172
173
|
return Arrays.<ReactPackage>asList(
|
|
173
174
|
new MainReactPackage(),
|
|
174
175
|
new CodePush("deployment-key-here", MainApplication.this, BuildConfig.DEBUG)
|
|
@@ -245,7 +246,7 @@ public class MainActivity extends ReactActivity {
|
|
|
245
246
|
protected List<ReactPackage> getPackages() {
|
|
246
247
|
// 3. Instantiate an instance of the CodePush runtime and add it to the list of
|
|
247
248
|
// existing packages, specifying the right deployment key. If you don't already
|
|
248
|
-
// have it, you can run "
|
|
249
|
+
// have it, you can run "appcenter codepush deployment list -a <ownerName>/<appName> -k" to retrieve your key.
|
|
249
250
|
return Arrays.<ReactPackage>asList(
|
|
250
251
|
new MainReactPackage(),
|
|
251
252
|
new CodePush("deployment-key-here", this, BuildConfig.DEBUG)
|
package/docs/setup-ios.md
CHANGED
|
@@ -43,15 +43,15 @@ Once you've acquired the CodePush plugin, you need to integrate it into the Xcod
|
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
5. Add the Deployment key to `Info.plist`:
|
|
46
|
-
|
|
47
|
-
To let the CodePush runtime know which deployment it should query for updates against, open your app's `Info.plist` file and add a new entry named `CodePushDeploymentKey`, whose value is the key of the deployment you want to configure this app against (like the key for the `Staging` deployment for the `FooBar` app). You can retrieve this value by running `
|
|
46
|
+
|
|
47
|
+
To let the CodePush runtime know which deployment it should query for updates against, open your app's `Info.plist` file and add a new entry named `CodePushDeploymentKey`, whose value is the key of the deployment you want to configure this app against (like the key for the `Staging` deployment for the `FooBar` app). You can retrieve this value by running `appcenter codepush deployment list -a <ownerName>/<appName> -k` in the AppCenter CLI (the `-k` flag is necessary since keys aren't displayed by default) and copying the value of the `Key` column which corresponds to the deployment you want to use (see below). Note that using the deployment's name (like Staging) will not work. That "friendly name" is intended only for authenticated management usage from the CLI, and not for public consumption within your app.
|
|
48
48
|
|
|
49
49
|

|
|
50
50
|
|
|
51
51
|
In order to effectively make use of the `Staging` and `Production` deployments that were created along with your CodePush app, refer to the [multi-deployment testing](../README.md#multi-deployment-testing) docs below before actually moving your app's usage of CodePush into production.
|
|
52
52
|
|
|
53
53
|
*Note: If you need to dynamically use a different deployment, you can also override your deployment key in JS code using [Code-Push options](./api-js.md#CodePushOptions)*
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
### Plugin Installation for React Native lower than 0.60 (iOS)
|
|
56
56
|
|
|
57
57
|
In order to accommodate as many developer preferences as possible, the CodePush plugin supports iOS installation via three mechanisms:
|
|
@@ -76,7 +76,7 @@ In order to accommodate as many developer preferences as possible, the CodePush
|
|
|
76
76
|
|
|
77
77
|
*Note: If you don't already have RNPM installed, you can do so by simply running `npm i -g rnpm` and then executing the above command. If you already have RNPM installed, make sure you have v1.9.0+ in order to benefit from this one step install.*
|
|
78
78
|
|
|
79
|
-
2. You will be prompted for the deployment key you'd like to use. If you don't already have it, you can retrieve this value by running `
|
|
79
|
+
2. You will be prompted for the deployment key you'd like to use. If you don't already have it, you can retrieve this value by running `appcenter codepush deployment list -a <ownerName>/<appName> -k`, or you can choose to ignore it (by simply hitting `<ENTER>`) and add it in later. To get started, we would recommend just using your `Staging` deployment key, so that you can test out the CodePush end-to-end.
|
|
80
80
|
|
|
81
81
|
And that's it! Isn't RNPM awesome? :)
|
|
82
82
|
|
|
@@ -218,7 +218,7 @@ NSURL *jsCodeLocation;
|
|
|
218
218
|
#endif
|
|
219
219
|
```
|
|
220
220
|
|
|
221
|
-
To let the CodePush runtime know which deployment it should query for updates against, open your app's `Info.plist` file and add a new entry named `CodePushDeploymentKey`, whose value is the key of the deployment you want to configure this app against (like the key for the `Staging` deployment for the `FooBar` app). You can retrieve this value by running `
|
|
221
|
+
To let the CodePush runtime know which deployment it should query for updates against, open your app's `Info.plist` file and add a new entry named `CodePushDeploymentKey`, whose value is the key of the deployment you want to configure this app against (like the key for the `Staging` deployment for the `FooBar` app). You can retrieve this value by running `appcenter codepush deployment list -a <ownerName>/<appName> -k` in the AppCenter CLI (the `-k` flag is necessary since keys aren't displayed by default) and copying the value of the `Key` column which corresponds to the deployment you want to use (see below). Note that using the deployment's name (like Staging) will not work. That "friendly name" is intended only for authenticated management usage from the CLI, and not for public consumption within your app.
|
|
222
222
|
|
|
223
223
|

|
|
224
224
|
|