-
Notifications
You must be signed in to change notification settings - Fork 97
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
[eas-cli] warn for misconfigured channel configuration for eas update #1082
base: main
Are you sure you want to change the base?
Changes from all commits
0c83275
9ff1f9e
29d7f73
bbe9426
ff94be6
995bdf7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -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'; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or import |
||||||
|
||||||
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<boolean> { | ||||||
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; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we log that we changed this? Log.withTick(`Migrated the Classic Updates release channel "${value.releaseChannel}" to be an EAS Update channel.`) |
||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
if (releaseChannelsFound) { | ||||||
try { | ||||||
await fs.writeFile( | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a strong opinion, but I would prefer to avoid modifying eas.json automatically:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
But most importantly: I think the amount of people missing this migration change in the docs and ending up with updates that don't work outweighs any downsides for the tiny minority who has manually applied some special indentation to the file. |
||||||
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' } | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Update, 'id' | 'createdAt' | 'message'> & { | ||
actor?: Maybe<Pick<User, 'username' | 'id'> | Pick<Robot, 'firstName' | 'id'>>; | ||
|
@@ -105,3 +109,60 @@ export function ensureValidVersions(exp: ExpoConfig, platform: RequestedPlatform | |
throw error; | ||
} | ||
} | ||
|
||
export async function checkDeprecatedChannelConfigurationAsync( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you are mixing here to responsibilities, this function should either:
|
||
projectDir: string | ||
): Promise<boolean> { | ||
const easJson = await new EasJsonReader(projectDir).readAsync(); | ||
if (easJson.build && Object.entries(easJson.build).some(([, value]) => value.releaseChannel)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO the second condition is too complicated to keep it inline. |
||
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( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same as above, it should either handle the situation or return boolean(not both) |
||
projectDir: string, | ||
buildProfile: ProfileData<'build'> | ||
): Promise<boolean> { | ||
const { exp } = getConfig(projectDir, { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO this should be passed as an argument. |
||
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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Our pattern is:
|
||
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<boolean> { | ||
const configuredURL = exp.updates?.url; | ||
const projectId = await getProjectIdAsync(exp); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd also pass this as an argument. |
||
const expectedURL = getEASUpdateURL(projectId); | ||
|
||
return configuredURL === expectedURL; | ||
} | ||
|
||
export async function ensureEASUpdateURLIsSetAsync(exp: ExpoConfig): Promise<void> { | ||
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.` | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prepareAndStartBuildAsync
. There's anexp
object available there so you wouldn't need to callgetConfig
incheckBuildProfileConfigMatchesProjectConfigAsync
.