Skip to content

Commit 00322ee

Browse files
DmitriyKirakosyanlucen-ms
authored andcommitted
[CLI] Support code signing (microsoft#23)
Add support for signing update bundle.
1 parent 2f6cfee commit 00322ee

File tree

8 files changed

+289
-36
lines changed

8 files changed

+289
-36
lines changed

cli/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ code-push-standalone release-react <appName> <platform>
395395
[--useHermes <useHermes>]
396396
[--podFile <podFile>]
397397
[--extraHermesFlags <extraHermesFlags>]
398+
[--privateKeyPath <privateKeyPath>]
398399
```
399400

400401
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:
@@ -542,6 +543,12 @@ Hermes flags which will be passed to Hermes compiler.
542543

543544
_NOTE: This parameter can be set using either --extraHermesFlags or -hf_
544545

546+
#### Private key path parameter
547+
548+
Private key path which is used for code signing.
549+
550+
_NOTE: This parameter can be set using either --privateKeyPath or -k_
551+
545552
## Debugging CodePush Integration
546553

547554
Once you've released an update, 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:

cli/package-lock.json

Lines changed: 140 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"cli-table": "^0.3.11",
2525
"email-validator": "^2.0.4",
2626
"gradle-to-js": "2.0.1",
27+
"jsonwebtoken": "^9.0.2",
2728
"moment": "^2.29.4",
2829
"opener": "^1.5.2",
2930
"parse-duration": "1.1.0",
@@ -38,6 +39,7 @@
3839
"simctl": "^2.0.3",
3940
"slash": "1.0.0",
4041
"superagent": "^8.0.9",
42+
"temp": "^0.9.4",
4143
"which": "^1.2.7",
4244
"wordwrap": "1.0.0",
4345
"xml2js": "^0.6.0",

cli/script/command-executor.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const Table = require("cli-table");
2121
const which = require("which");
2222
import wordwrap = require("wordwrap");
2323
import * as cli from "../script/types/cli";
24+
import sign from "./sign";
2425
import {
2526
AccessKey,
2627
Account,
@@ -37,11 +38,14 @@ import {
3738
UpdateMetrics,
3839
} from "../script/types";
3940
import {
40-
fileDoesNotExistOrIsDirectory,
4141
getAndroidHermesEnabled,
4242
getiOSHermesEnabled,
4343
runHermesEmitBinaryCommand
4444
} from "./react-native-utils";
45+
import {
46+
fileDoesNotExistOrIsDirectory,
47+
isBinaryOrZip
48+
} from "./utils/file-utils";
4549

4650
const configFilePath: string = path.join(process.env.LOCALAPPDATA || process.env.HOME, ".code-push.config");
4751
const emailValidator = require("email-validator");
@@ -1321,7 +1325,14 @@ export const releaseReact = (command: cli.IReleaseReactCommand): Promise<void> =
13211325
command.gradleFile
13221326
);
13231327
}
1324-
1328+
})
1329+
.then(async () => {
1330+
if (command.privateKeyPath) {
1331+
log(chalk.cyan("\nSigning the bundle:\n"));
1332+
await sign(command.privateKeyPath, outputFolder);
1333+
} else {
1334+
console.log("private key was not provided");
1335+
}
13251336
})
13261337
.then(() => {
13271338
log(chalk.cyan("\nReleasing update contents to CodePush:\n"));
@@ -1490,10 +1501,6 @@ function releaseErrorHandler(error: CodePushError, command: cli.ICommand): void
14901501
}
14911502
}
14921503

1493-
function isBinaryOrZip(path: string): boolean {
1494-
return path.search(/\.zip$/i) !== -1 || path.search(/\.apk$/i) !== -1 || path.search(/\.ipa$/i) !== -1;
1495-
}
1496-
14971504
function throwForInvalidEmail(email: string): void {
14981505
if (!emailValidator.validate(email)) {
14991506
throw new Error('"' + email + '" is an invalid e-mail address.');

cli/script/command-parser.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,13 @@ yargs
797797
"Flags that get passed to Hermes, JavaScript to bytecode compiler. Can be specified multiple times.",
798798
type: "array",
799799
})
800+
.option("privateKeyPath", {
801+
alias: "k",
802+
default: null,
803+
demand: false,
804+
description: "Path to private key used for code signing.",
805+
type: "string",
806+
})
800807
.check((argv: any, aliases: { [aliases: string]: string }): any => {
801808
return checkValidReleaseOptions(argv);
802809
});
@@ -1194,6 +1201,7 @@ export function createCommand(): cli.ICommand {
11941201
releaseReactCommand.useHermes = argv["useHermes"] as any;
11951202
releaseReactCommand.extraHermesFlags = argv["extraHermesFlags"] as any;
11961203
releaseReactCommand.podFile = argv["podFile"] as any;
1204+
releaseReactCommand.privateKeyPath = argv["privateKeyPath"] as any;
11971205
}
11981206
break;
11991207

cli/script/react-native-utils.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as chalk from "chalk";
33
import * as path from "path";
44
import * as childProcess from "child_process";
55
import { coerce, compare } from "semver";
6+
import { fileDoesNotExistOrIsDirectory } from "./utils/file-utils";
67

78
const g2js = require("gradle-to-js/lib/parser");
89

@@ -119,14 +120,6 @@ export async function runHermesEmitBinaryCommand(
119120
});
120121
}
121122

122-
export function fileDoesNotExistOrIsDirectory(filePath: string): boolean {
123-
try {
124-
return fs.lstatSync(filePath).isDirectory();
125-
} catch (error) {
126-
return true;
127-
}
128-
}
129-
130123
function parseBuildGradleFile(gradleFile: string) {
131124
let buildGradlePath: string = path.join("android", "app");
132125
if (gradleFile) {

0 commit comments

Comments
 (0)