Compare commits

...
5 changed files with 124 additions and 4 deletions

No files matched your search

+2
View File
@@ -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))
@@ -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<Platform> } = {};
// 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,
@@ -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<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;
}
}
}
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' }
+15 -2
View File
@@ -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<void> {
const configuredURL = exp.updates?.url;
+63 -2
View File
@@ -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(
projectDir: string
): Promise<boolean> {
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<boolean> {
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<boolean> {
const configuredURL = exp.updates?.url;
const projectId = await getProjectIdAsync(exp);
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.`
);
}
}