UNPKG

eas-cli

Version:
145 lines (144 loc) 8.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.republishAsync = void 0; const tslib_1 = require("tslib"); const assert_1 = tslib_1.__importDefault(require("assert")); const nullthrows_1 = tslib_1.__importDefault(require("nullthrows")); const url_1 = require("../build/utils/url"); const fetch_1 = tslib_1.__importDefault(require("../fetch")); const PublishMutation_1 = require("../graphql/mutations/PublishMutation"); const log_1 = tslib_1.__importStar(require("../log")); const ora_1 = require("../ora"); const projectUtils_1 = require("../project/projectUtils"); const code_signing_1 = require("../utils/code-signing"); const formatFields_1 = tslib_1.__importDefault(require("../utils/formatFields")); const json_1 = require("../utils/json"); /** * @param updatesToPublish The update group to republish * @param targetBranch The branch to repubish the update group on */ async function republishAsync({ graphqlClient, app, updatesToPublish, targetBranch, updateMessage, codeSigningInfo, json, }) { const { branchName: targetBranchName, branchId: targetBranchId } = targetBranch; // The update group properties are the same for all updates (0, assert_1.default)(updatesToPublish.length > 0, 'Updates to republish must be provided'); const arbitraryUpdate = updatesToPublish[0]; const isSameGroup = (update) => update.groupId === arbitraryUpdate.groupId && update.branchId === arbitraryUpdate.branchId && update.branchName === arbitraryUpdate.branchName && update.runtimeVersion === arbitraryUpdate.runtimeVersion; (0, assert_1.default)(updatesToPublish.every(isSameGroup), 'All updates being republished must belong to the same update group'); (0, assert_1.default)(updatesToPublish.every(u => u.isRollBackToEmbedded) || updatesToPublish.every(u => !u.isRollBackToEmbedded), 'All updates must either be roll back to embedded updates or not'); (0, assert_1.default)(!updatesToPublish.some(u => !!u.rolloutControlUpdate), 'Cannot republish an update that is being rolled-out. Either complete the update rollout and then republish or publish a new rollout update.'); const { runtimeVersion } = arbitraryUpdate; // If codesigning was created for the original update, we need to add it to the republish. // If one wishes to not sign the republish or sign with a different key, a normal publish should // be performed. const shouldRepublishWithCodesigning = updatesToPublish.some(update => update.codeSigningInfo); if (shouldRepublishWithCodesigning) { if (!codeSigningInfo) { throw new Error('Must specify --private-key-path argument to sign republished update group for code signing'); } for (const update of updatesToPublish) { if ((0, nullthrows_1.default)(update.codeSigningInfo).alg !== codeSigningInfo.codeSigningMetadata.alg || (0, nullthrows_1.default)(update.codeSigningInfo).keyid !== codeSigningInfo.codeSigningMetadata.keyid) { throw new Error('Republished updates must use the same code signing key and algorithm as original update'); } } log_1.default.withTick(`The republished update group will be signed with the same code signing key and algorithm as the original update`); } const publishIndicator = (0, ora_1.ora)('Republishing...').start(); let updatesRepublished; try { const arbitraryUpdate = updatesToPublish[0]; const objectToMergeIn = arbitraryUpdate.isRollBackToEmbedded ? { rollBackToEmbeddedInfoGroup: Object.fromEntries(updatesToPublish.map(update => [update.platform, true])), } : { updateInfoGroup: Object.fromEntries(updatesToPublish.map(update => [update.platform, JSON.parse(update.manifestFragment)])), fingerprintInfoGroup: Object.fromEntries(updatesToPublish.map(update => { const fingerprint = update.fingerprint; if (!fingerprint) { return [update.platform, undefined]; } return [ update.platform, { fingerprintHash: fingerprint.hash, fingerprintSource: fingerprint.source ? { type: fingerprint.source.type, bucketKey: fingerprint.source.bucketKey, isDebugFingerprint: fingerprint.source.isDebugFingerprint, } : undefined, }, ]; })), }; updatesRepublished = await PublishMutation_1.PublishMutation.publishUpdateGroupAsync(graphqlClient, [ { branchId: targetBranchId, runtimeVersion, message: updateMessage, ...objectToMergeIn, gitCommitHash: updatesToPublish[0].gitCommitHash, awaitingCodeSigningInfo: !!codeSigningInfo, }, ]); if (codeSigningInfo) { log_1.default.log('🔒 Signing republished update group'); await Promise.all(updatesRepublished.map(async (newUpdate) => { const response = await (0, fetch_1.default)(newUpdate.manifestPermalink, { method: 'GET', headers: { accept: 'multipart/mixed' }, }); let signature; if (newUpdate.isRollBackToEmbedded) { const directiveBody = (0, nullthrows_1.default)(await (0, code_signing_1.getDirectiveBodyAsync)(response)); (0, code_signing_1.checkDirectiveBodyAgainstUpdateInfoGroup)(directiveBody); signature = (0, code_signing_1.signBody)(directiveBody, codeSigningInfo); } else { const manifestBody = (0, nullthrows_1.default)(await (0, code_signing_1.getManifestBodyAsync)(response)); (0, code_signing_1.checkManifestBodyAgainstUpdateInfoGroup)(manifestBody, (0, nullthrows_1.default)((0, nullthrows_1.default)(objectToMergeIn.updateInfoGroup)[newUpdate.platform])); signature = (0, code_signing_1.signBody)(manifestBody, codeSigningInfo); } await PublishMutation_1.PublishMutation.setCodeSigningInfoAsync(graphqlClient, newUpdate.id, { alg: codeSigningInfo.codeSigningMetadata.alg, keyid: codeSigningInfo.codeSigningMetadata.keyid, sig: signature, }); })); } publishIndicator.succeed('Republished update group'); } catch (error) { publishIndicator.fail('Failed to republish update group'); throw error; } if (json) { (0, json_1.printJsonOnlyOutput)(updatesRepublished); return; } const updatesRepublishedByPlatform = Object.fromEntries(updatesRepublished.map(update => [update.platform, update])); const arbitraryRepublishedUpdate = updatesRepublished[0]; const updateGroupUrl = (0, url_1.getUpdateGroupUrl)((await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, app.projectId)).name, app.exp.slug, arbitraryRepublishedUpdate.group); log_1.default.addNewLineIfNone(); log_1.default.log((0, formatFields_1.default)([ { label: 'Branch', value: targetBranchName }, { label: 'Runtime version', value: arbitraryRepublishedUpdate.runtimeVersion }, { label: 'Platform', value: updatesRepublished.map(update => update.platform).join(', ') }, { label: 'Update group ID', value: arbitraryRepublishedUpdate.group }, ...(updatesRepublishedByPlatform.android ? [{ label: 'Android update ID', value: updatesRepublishedByPlatform.android.id }] : []), ...(updatesRepublishedByPlatform.ios ? [{ label: 'iOS update ID', value: updatesRepublishedByPlatform.ios.id }] : []), { label: 'Message', value: updateMessage }, { label: 'EAS Dashboard', value: (0, log_1.link)(updateGroupUrl, { dim: false }) }, ])); } exports.republishAsync = republishAsync;