Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): add build command for ios #5925

Merged
merged 10 commits into from
Oct 5, 2022
3 changes: 3 additions & 0 deletions cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export function runProgram(config: Config): void {
program
.command('build <platform>')
.description('builds the release version of the selected platform')
.option('--scheme <schemeToBuild>', 'iOS Scheme to build')
.option('--keystorepath <keystorePath>', 'Path to the keystore')
.option('--keystorepass <keystorePass>', 'Password to the keystore')
.option('--keystorealias <keystoreAlias>', 'Key Alias in the keystore')
Expand All @@ -162,6 +163,7 @@ export function runProgram(config: Config): void {
async (
platform,
{
scheme,
keystorepath,
keystorepass,
keystorealias,
Expand All @@ -171,6 +173,7 @@ export function runProgram(config: Config): void {
) => {
const { buildCommand } = await import('./tasks/build');
await buildCommand(config, platform, {
scheme,
keystorepath,
keystorepass,
keystorealias,
Expand Down
84 changes: 84 additions & 0 deletions cli/src/ios/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { writeFileSync, unlinkSync } from '@ionic/utils-fs';
import { join } from 'path';
import rimraf from 'rimraf';

import { runTask } from '../common';
import type { Config } from '../definitions';
import { logSuccess } from '../log';
import type { BuildCommandOptions } from '../tasks/build';
import { runCommand } from '../util/subprocess';

export async function buildiOS(
config: Config,
buildOptions: BuildCommandOptions,
): Promise<void> {
const theScheme = buildOptions.scheme ?? 'App';

await runTask('Building xArchive', async () =>
runCommand(
'xcodebuild',
[
'-workspace',
`${theScheme}.xcworkspace`,
'-scheme',
`${theScheme}`,
'-destination',
`generic/platform=iOS`,
'-archivePath',
`${theScheme}.xcarchive`,
'archive',
],
{
cwd: config.ios.nativeProjectDirAbs,
},
),
);

const archivePlistContents = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>app-store</string>
</dict>
</plist>`;

const archivePlistPath = join(
`${config.ios.nativeProjectDirAbs}`,
'archive.plist',
);

writeFileSync(archivePlistPath, archivePlistContents);

await runTask('Building IPA', async () =>
runCommand(
'xcodebuild',
[
'archive',
'-archivePath',
`${theScheme}.xcarchive`,
'-exportArchive',
'-exportOptionsPlist',
'archive.plist',
'-exportPath',
'output',
'-allowProvisioningUpdates',
],
{
cwd: config.ios.nativeProjectDirAbs,
},
),
);

await runTask('Cleaning up', async () => {
unlinkSync(archivePlistPath);
rimraf.sync(join(config.ios.nativeProjectDirAbs, `${theScheme}.xcarchive`));
});

logSuccess(
`Successfully generated an IPA at: ${join(
config.ios.nativeProjectDirAbs,
'output',
)}`,
);
}
5 changes: 4 additions & 1 deletion cli/src/tasks/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { buildAndroid } from '../android/build';
import { selectPlatforms, promptForPlatform } from '../common';
import type { Config } from '../definitions';
import { fatal, isFatal } from '../errors';
import { buildiOS } from '../ios/build';

export interface BuildCommandOptions {
scheme?: string;
keystorepath?: string;
keystorepass?: string;
keystorealias?: string;
Expand All @@ -28,6 +30,7 @@ export async function buildCommand(
}

const buildCommandOptions: BuildCommandOptions = {
scheme: buildOptions.scheme || config.ios.scheme,
keystorepath:
buildOptions.keystorepath || config.android.buildOptions.keystorePath,
keystorepass:
Expand Down Expand Up @@ -58,7 +61,7 @@ export async function build(
buildOptions: BuildCommandOptions,
): Promise<void> {
if (platformName == config.ios.name) {
throw `Platform "${platformName}" is not available in the build command.`;
await buildiOS(config, buildOptions);
} else if (platformName === config.android.name) {
await buildAndroid(config, buildOptions);
} else if (platformName === config.web.name) {
Expand Down