diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ad1c2fbd1..d7442f8f86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ This is the log of notable changes to EAS CLI and related packages. ### ๐ŸŽ‰ New features +- Warn for misconfigured channel configuration when using EAS Update. ([#1082](https://github.com/expo/eas-cli/pull/1082)) by [@kbrandwijk](https://github.com/kbrandwijk)) + ### ๐Ÿ› Bug fixes - Rebind `console.info` correctly after `ora` instance stops. ([#1113](https://github.com/expo/eas-cli/pull/1113) by [@EvanBacon](https://github.com/EvanBacon)) diff --git a/packages/eas-cli/src/build/runBuildAndSubmit.ts b/packages/eas-cli/src/build/runBuildAndSubmit.ts index 6f2f4e60fa..26183f3336 100644 --- a/packages/eas-cli/src/build/runBuildAndSubmit.ts +++ b/packages/eas-cli/src/build/runBuildAndSubmit.ts @@ -40,6 +40,7 @@ import { waitToCompleteAsync as waitForSubmissionsToCompleteAsync, } from '../submit/submit'; import { printSubmissionDetailsUrls } from '../submit/utils/urls'; +import { checkBuildProfileConfigMatchesProjectConfigAsync } from '../update/utils'; import { printJsonOnlyOutput } from '../utils/json'; import { ProfileData, getProfilesAsync } from '../utils/profiles'; import { getVcsClient } from '../vcs'; @@ -121,6 +122,12 @@ export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFla }[] = []; const buildCtxByPlatform: { [p in AppPlatform]?: BuildContext } = {}; + // Check only first buildprofile (there should be only one unique one) + // Warn only once + if (buildProfiles.length > 0) { + await checkBuildProfileConfigMatchesProjectConfigAsync(projectDir, buildProfiles[0]); + } + for (const buildProfile of buildProfiles) { const { build: maybeBuild, buildCtx } = await prepareAndStartBuildAsync({ projectDir, diff --git a/packages/eas-cli/src/commands/update/configure.ts b/packages/eas-cli/src/commands/update/configure.ts index 8feb494eef..3a5321f5e1 100644 --- a/packages/eas-cli/src/commands/update/configure.ts +++ b/packages/eas-cli/src/commands/update/configure.ts @@ -1,8 +1,10 @@ import { ExpoConfig, modifyConfigAsync } from '@expo/config'; import { Platform, Workflow } from '@expo/eas-build-job'; +import { EasJsonReader } from '@expo/eas-json'; import { Flags } from '@oclif/core'; import assert from 'assert'; import chalk from 'chalk'; +import { promises as fs } from 'fs-extra'; import { getEASUpdateURL } from '../../api'; import EasCommand from '../../commandUtils/EasCommand'; @@ -64,6 +66,11 @@ export default class UpdateConfigure extends EasCommand { }); Log.withTick(`Configured ${chalk.bold('app.json')} for EAS Update`); + const madeChanges = await checkAndConfigureEasJsonReleaseChannelsAsync(projectDir); + if (madeChanges) { + Log.withTick(`Configured ${chalk.bold('eas.json')} for EAS Update`); + } + // configure native files for EAS Update if ( [RequestedPlatform.Android, RequestedPlatform.All].includes(platform) && @@ -241,6 +248,36 @@ async function configureAppJSONForEASUpdateAsync({ return result.config.expo; } +async function checkAndConfigureEasJsonReleaseChannelsAsync(projectDir: string): Promise { + const reader = new EasJsonReader(projectDir); + const easJson = await reader.readAsync(); + + let releaseChannelsFound = false; + + if (easJson.build) { + for (const [key, value] of Object.entries(easJson.build)) { + if (value.releaseChannel) { + releaseChannelsFound = true; + easJson.build[key].channel = value.releaseChannel; + delete easJson.build[key].releaseChannel; + } + } + } + + if (releaseChannelsFound) { + try { + await fs.writeFile( + EasJsonReader.formatEasJsonPath(projectDir), + JSON.stringify(easJson, null, 2) + ); + } catch { + throw new Error('Error occured updating eas.json file'); + } + } + + return releaseChannelsFound; +} + function isRuntimeEqual( runtimeVersionA: string | { policy: 'sdkVersion' | 'nativeVersion' | 'appVersion' }, runtimeVersionB: string | { policy: 'sdkVersion' | 'nativeVersion' | 'appVersion' } diff --git a/packages/eas-cli/src/commands/update/index.ts b/packages/eas-cli/src/commands/update/index.ts index 46e69d4188..4c2b241f59 100644 --- a/packages/eas-cli/src/commands/update/index.ts +++ b/packages/eas-cli/src/commands/update/index.ts @@ -48,7 +48,11 @@ import { } from '../../project/publish'; import { resolveWorkflowAsync } from '../../project/workflow'; import { confirmAsync, promptAsync, selectAsync } from '../../prompts'; -import { formatUpdate } from '../../update/utils'; +import { + checkDeprecatedChannelConfigurationAsync, + ensureEASUpdateURLIsSetAsync, + formatUpdate, +} from '../../update/utils'; import { ensureLoggedInAsync } from '../../user/actions'; import { checkManifestBodyAgainstUpdateInfoGroup, @@ -275,7 +279,7 @@ export default class UpdatePublish extends EasCommand { const runtimeVersions = await getRuntimeVersionObjectAsync(exp, platformFlag, projectDir); const projectId = await getProjectIdAsync(exp); - await checkEASUpdateURLIsSetAsync(exp); + await ensureEASUpdateURLIsSetAsync(exp); if (!branchName && autoFlag) { branchName = @@ -324,6 +328,13 @@ export default class UpdatePublish extends EasCommand { assert(branchName, 'Branch name must be specified.'); } + const { id: branchId, updates } = await ensureBranchExistsAsync({ + appId: projectId, + name: branchName, + }); + + await checkDeprecatedChannelConfigurationAsync(projectDir); + let unsortedUpdateInfoGroups: UpdateInfoGroup = {}; let oldMessage: string, oldRuntimeVersion: string; let uploadedAssetCount = 0; @@ -749,6 +760,8 @@ function formatUpdateTitle( 'mmm dd HH:MM' )} by ${actorName}, runtimeVersion: ${runtimeVersion}] ${message}`; } +<<<<<<< HEAD +======= async function checkEASUpdateURLIsSetAsync(exp: ExpoConfig): Promise { const configuredURL = exp.updates?.url; diff --git a/packages/eas-cli/src/update/utils.ts b/packages/eas-cli/src/update/utils.ts index 9d955d368e..27cadad0d1 100644 --- a/packages/eas-cli/src/update/utils.ts +++ b/packages/eas-cli/src/update/utils.ts @@ -1,12 +1,16 @@ -import { ExpoConfig } from '@expo/config'; +import { ExpoConfig, getConfig } from '@expo/config'; +import { EasJsonReader } from '@expo/eas-json'; import { format } from '@expo/timeago.js'; import chalk from 'chalk'; +import { getEASUpdateURL } from '../api'; import { Maybe, Robot, Update, User } from '../graphql/generated'; -import { learnMore } from '../log'; +import Log, { learnMore } from '../log'; import { RequestedPlatform } from '../platform'; +import { getProjectIdAsync } from '../project/projectUtils'; import { getActorDisplayName } from '../user/User'; import groupBy from '../utils/expodash/groupBy'; +import { ProfileData } from '../utils/profiles'; export type FormatUpdateParameter = Pick & { actor?: Maybe | Pick>; @@ -105,3 +109,60 @@ export function ensureValidVersions(exp: ExpoConfig, platform: RequestedPlatform throw error; } } + +export async function checkDeprecatedChannelConfigurationAsync( + projectDir: string +): Promise { + const easJson = await new EasJsonReader(projectDir).readAsync(); + if (easJson.build && Object.entries(easJson.build).some(([, value]) => value.releaseChannel)) { + Log.warn(`ยป One or more build profiles in your eas.json specify the "releaseChannel" property. +For EAS Update, you need to specify the "channel" property, or your build will not be able to receive any updates. +Update your eas.json manually, or run ${chalk.bold('eas update:configure')}. +${learnMore('https://docs.expo.dev/eas-update/getting-started/#configure-your-project')}`); + Log.newLine(); + return true; + } + + return false; +} + +export async function checkBuildProfileConfigMatchesProjectConfigAsync( + projectDir: string, + buildProfile: ProfileData<'build'> +): Promise { + const { exp } = getConfig(projectDir, { + skipSDKVersionRequirement: true, + isPublicConfig: true, + }); + if ((await checkEASUpdateURLIsSetAsync(exp)) && buildProfile.profile.releaseChannel) { + Log.warn(`ยป Build profile ${chalk.bold( + buildProfile.profileName + )} in your eas.json specifies the "releaseChannel" property. +For EAS Update, you need to specify the "channel" property, or your build will not be able to receive any updates. +Update your eas.json manually, or run ${chalk.bold('eas update:configure')}. +${learnMore('https://docs.expo.dev/eas-update/getting-started/#configure-your-project')}`); + return true; + } + + return false; +} + +export async function checkEASUpdateURLIsSetAsync(exp: ExpoConfig): Promise { + const configuredURL = exp.updates?.url; + const projectId = await getProjectIdAsync(exp); + const expectedURL = getEASUpdateURL(projectId); + + return configuredURL === expectedURL; +} + +export async function ensureEASUpdateURLIsSetAsync(exp: ExpoConfig): Promise { + const configuredURL = exp.updates?.url; + const projectId = await getProjectIdAsync(exp); + const expectedURL = getEASUpdateURL(projectId); + + if (configuredURL !== expectedURL) { + throw new Error( + `The update URL is incorrectly configured for EAS Update. Please set updates.url to ${expectedURL} in your app.json.` + ); + } +}