Skip to content

Commit

Permalink
[CLI] Support code signing (microsoft#23)
Browse files Browse the repository at this point in the history
Add support for signing update bundle.
  • Loading branch information
DmitriyKirakosyan authored and lucen-ms committed Oct 23, 2024
1 parent 2f6cfee commit 00322ee
Show file tree
Hide file tree
Showing 8 changed files with 289 additions and 36 deletions.
7 changes: 7 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ code-push-standalone release-react <appName> <platform>
[--useHermes <useHermes>]
[--podFile <podFile>]
[--extraHermesFlags <extraHermesFlags>]
[--privateKeyPath <privateKeyPath>]
```

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

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

#### Private key path parameter

Private key path which is used for code signing.

_NOTE: This parameter can be set using either --privateKeyPath or -k_

## Debugging CodePush Integration

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:
Expand Down
162 changes: 140 additions & 22 deletions cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"cli-table": "^0.3.11",
"email-validator": "^2.0.4",
"gradle-to-js": "2.0.1",
"jsonwebtoken": "^9.0.2",
"moment": "^2.29.4",
"opener": "^1.5.2",
"parse-duration": "1.1.0",
Expand All @@ -38,6 +39,7 @@
"simctl": "^2.0.3",
"slash": "1.0.0",
"superagent": "^8.0.9",
"temp": "^0.9.4",
"which": "^1.2.7",
"wordwrap": "1.0.0",
"xml2js": "^0.6.0",
Expand Down
19 changes: 13 additions & 6 deletions cli/script/command-executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const Table = require("cli-table");
const which = require("which");
import wordwrap = require("wordwrap");
import * as cli from "../script/types/cli";
import sign from "./sign";
import {
AccessKey,
Account,
Expand All @@ -37,11 +38,14 @@ import {
UpdateMetrics,
} from "../script/types";
import {
fileDoesNotExistOrIsDirectory,
getAndroidHermesEnabled,
getiOSHermesEnabled,
runHermesEmitBinaryCommand
} from "./react-native-utils";
import {
fileDoesNotExistOrIsDirectory,
isBinaryOrZip
} from "./utils/file-utils";

const configFilePath: string = path.join(process.env.LOCALAPPDATA || process.env.HOME, ".code-push.config");
const emailValidator = require("email-validator");
Expand Down Expand Up @@ -1321,7 +1325,14 @@ export const releaseReact = (command: cli.IReleaseReactCommand): Promise<void> =
command.gradleFile
);
}

})
.then(async () => {
if (command.privateKeyPath) {
log(chalk.cyan("\nSigning the bundle:\n"));
await sign(command.privateKeyPath, outputFolder);
} else {
console.log("private key was not provided");
}
})
.then(() => {
log(chalk.cyan("\nReleasing update contents to CodePush:\n"));
Expand Down Expand Up @@ -1490,10 +1501,6 @@ function releaseErrorHandler(error: CodePushError, command: cli.ICommand): void
}
}

function isBinaryOrZip(path: string): boolean {
return path.search(/\.zip$/i) !== -1 || path.search(/\.apk$/i) !== -1 || path.search(/\.ipa$/i) !== -1;
}

function throwForInvalidEmail(email: string): void {
if (!emailValidator.validate(email)) {
throw new Error('"' + email + '" is an invalid e-mail address.');
Expand Down
8 changes: 8 additions & 0 deletions cli/script/command-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,13 @@ yargs
"Flags that get passed to Hermes, JavaScript to bytecode compiler. Can be specified multiple times.",
type: "array",
})
.option("privateKeyPath", {
alias: "k",
default: null,
demand: false,
description: "Path to private key used for code signing.",
type: "string",
})
.check((argv: any, aliases: { [aliases: string]: string }): any => {
return checkValidReleaseOptions(argv);
});
Expand Down Expand Up @@ -1194,6 +1201,7 @@ export function createCommand(): cli.ICommand {
releaseReactCommand.useHermes = argv["useHermes"] as any;
releaseReactCommand.extraHermesFlags = argv["extraHermesFlags"] as any;
releaseReactCommand.podFile = argv["podFile"] as any;
releaseReactCommand.privateKeyPath = argv["privateKeyPath"] as any;
}
break;

Expand Down
9 changes: 1 addition & 8 deletions cli/script/react-native-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as chalk from "chalk";
import * as path from "path";
import * as childProcess from "child_process";
import { coerce, compare } from "semver";
import { fileDoesNotExistOrIsDirectory } from "./utils/file-utils";

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

Expand Down Expand Up @@ -119,14 +120,6 @@ export async function runHermesEmitBinaryCommand(
});
}

export function fileDoesNotExistOrIsDirectory(filePath: string): boolean {
try {
return fs.lstatSync(filePath).isDirectory();
} catch (error) {
return true;
}
}

function parseBuildGradleFile(gradleFile: string) {
let buildGradlePath: string = path.join("android", "app");
if (gradleFile) {
Expand Down
Loading

0 comments on commit 00322ee

Please sign in to comment.