UNPKG

eas-cli

Version:
157 lines (156 loc) 7.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const eas_build_job_1 = require("@expo/eas-build-job"); const results_1 = require("@expo/results"); const chalk_1 = tslib_1.__importDefault(require("chalk")); const getenv_1 = tslib_1.__importDefault(require("getenv")); const wrap_ansi_1 = tslib_1.__importDefault(require("wrap-ansi")); const AppProduce_1 = require("./AppProduce"); const AppSpecificPasswordSource_1 = require("./AppSpecificPasswordSource"); const AscApiKeySource_1 = require("./AscApiKeySource"); const IosSubmitter_1 = tslib_1.__importDefault(require("./IosSubmitter")); const errors_1 = require("../../credentials/errors"); const log_1 = tslib_1.__importStar(require("../../log")); const ArchiveSource_1 = require("../ArchiveSource"); const commons_1 = require("../commons"); class IosSubmitCommand { ctx; constructor(ctx) { this.ctx = ctx; } async runAsync() { log_1.default.addNewLineIfNone(); const archiveSource = this.resolveArchiveSource(); if (!archiveSource.ok) { log_1.default.error(archiveSource.reason?.message); throw new Error('Submission failed'); } const archiveSourceValue = archiveSource.enforceValue(); const archive = await (0, ArchiveSource_1.getArchiveAsync)({ graphqlClient: this.ctx.graphqlClient, platform: eas_build_job_1.Platform.IOS, projectId: this.ctx.projectId, nonInteractive: this.ctx.nonInteractive, }, archiveSourceValue); const archiveProfile = archive.sourceType === ArchiveSource_1.ArchiveSourceType.build ? archive.build.buildProfile : undefined; if (archiveProfile && !this.ctx.specifiedProfile) { this.ctx = await (0, commons_1.refreshContextSubmitProfileAsync)(this.ctx, archiveProfile); } const options = await this.resolveSubmissionOptionsAsync(archiveSourceValue); const submitter = new IosSubmitter_1.default(this.ctx, options, archive); return submitter; } async resolveSubmissionOptionsAsync(archiveSource) { const credentialsSource = await this.resolveCredentialSubmissionOptionsAsync(); const maybeAppSpecificPasswordSource = 'appSpecificPasswordSource' in credentialsSource ? credentialsSource.appSpecificPasswordSource : null; const maybeAscApiKeySource = 'ascApiKeySource' in credentialsSource ? credentialsSource.ascApiKeySource : null; const ascAppIdentifier = await this.resolveAscAppIdentifierAsync(); const errored = [ ...(maybeAppSpecificPasswordSource ? [maybeAppSpecificPasswordSource] : []), ...(maybeAscApiKeySource ? [maybeAscApiKeySource] : []), ascAppIdentifier, ].filter(r => !r.ok); if (errored.length > 0) { const message = errored.map(err => err.reason?.message).join('\n'); log_1.default.error(message); throw new Error('Submission failed'); } return { projectId: this.ctx.projectId, ascAppIdentifier: ascAppIdentifier.enforceValue(), archiveSource, ...(maybeAppSpecificPasswordSource ? { appSpecificPasswordSource: maybeAppSpecificPasswordSource.enforceValue(), } : null), ...(maybeAscApiKeySource ? { ascApiKeySource: maybeAscApiKeySource.enforceValue(), } : null), }; } async resolveCredentialSubmissionOptionsAsync() { // if an App Specific Password env var is not specified, use ASC Api Key const appSpecificPasswordSource = this.resolveAppSpecificPasswordSource(); const shouldSkipAppSpecificPasswordSource = !appSpecificPasswordSource.ok && appSpecificPasswordSource.enforceError() instanceof errors_1.MissingCredentialsError; if (!shouldSkipAppSpecificPasswordSource) { return { appSpecificPasswordSource: this.resolveAppSpecificPasswordSource() }; } const ascApiKeySource = this.resolveAscApiKeySource(); return { ascApiKeySource }; } resolveAppSpecificPasswordSource() { const envAppSpecificPassword = getenv_1.default.string('EXPO_APPLE_APP_SPECIFIC_PASSWORD', ''); if (envAppSpecificPassword) { if (!/^[a-z]{4}-[a-z]{4}-[a-z]{4}-[a-z]{4}$/.test(envAppSpecificPassword)) { throw new Error('EXPO_APPLE_APP_SPECIFIC_PASSWORD must be in the format xxxx-xxxx-xxxx-xxxx, where x is a lowercase letter.'); } return (0, results_1.result)({ sourceType: AppSpecificPasswordSource_1.AppSpecificPasswordSourceType.userDefined, appSpecificPassword: envAppSpecificPassword, }); } return (0, results_1.result)(new errors_1.MissingCredentialsError('The EXPO_APPLE_APP_SPECIFIC_PASSWORD environment variable must be set.')); } resolveAscApiKeySource() { const { ascApiKeyPath, ascApiKeyIssuerId, ascApiKeyId } = this.ctx.profile; if (ascApiKeyPath && ascApiKeyIssuerId && ascApiKeyId) { return (0, results_1.result)({ sourceType: AscApiKeySource_1.AscApiKeySourceType.path, path: { keyP8Path: ascApiKeyPath, issuerId: ascApiKeyIssuerId, keyId: ascApiKeyId, }, }); } // interpret this to mean the user had some intention of passing in ASC Api key if (ascApiKeyPath || ascApiKeyIssuerId || ascApiKeyId) { const message = `ascApiKeyPath, ascApiKeyIssuerId and ascApiKeyId must all be defined in eas.json`; // in non-interactive mode, we should fail if (this.ctx.nonInteractive) { throw new Error(message); } log_1.default.warn(message); return (0, results_1.result)({ sourceType: AscApiKeySource_1.AscApiKeySourceType.prompt, }); } return (0, results_1.result)({ sourceType: AscApiKeySource_1.AscApiKeySourceType.credentialsService }); } resolveArchiveSource() { try { return (0, results_1.result)((0, commons_1.resolveArchiveSource)(this.ctx)); } catch (err) { return (0, results_1.result)(err); } } async resolveAscAppIdentifierAsync() { const { ascAppId } = this.ctx.profile; if (ascAppId) { return (0, results_1.result)(ascAppId); } else if (this.ctx.nonInteractive) { return (0, results_1.result)(new Error('Set ascAppId in the submit profile (eas.json) or re-run this command in interactive mode.')); } else { log_1.default.log((0, wrap_ansi_1.default)(`Ensuring your app exists on App Store Connect. This step can be skipped by providing ${chalk_1.default.bold(`ascAppId`)} in the submit profile. ${(0, log_1.learnMore)('https://expo.fyi/asc-app-id')}`, process.stdout.columns || 80)); log_1.default.addNewLineIfNone(); try { const { ascAppIdentifier } = await (0, AppProduce_1.ensureAppStoreConnectAppExistsAsync)(this.ctx); return (0, results_1.result)(ascAppIdentifier); } catch (err) { return (0, results_1.result)(err); } } } } exports.default = IosSubmitCommand;