diff --git a/packages/data-context/src/actions/MigrationActions.ts b/packages/data-context/src/actions/MigrationActions.ts index 58dadd515f3..c154784b96c 100644 --- a/packages/data-context/src/actions/MigrationActions.ts +++ b/packages/data-context/src/actions/MigrationActions.ts @@ -170,8 +170,7 @@ export class MigrationActions { async initialize (config: LegacyCypressConfigJson) { const legacyConfigForMigration = await this.setLegacyConfigForMigration(config) - // for testing mainly, we want to ensure the flags are reset each test - this.resetFlags() + this.reset(legacyConfigForMigration) if (!this.ctx.currentProject || !legacyConfigForMigration) { throw Error('cannot do migration without currentProject!') @@ -435,11 +434,9 @@ export class MigrationActions { } } - resetFlags () { + reset (config?: LegacyCypressConfigJson) { this.ctx.update((coreData) => { - const defaultFlags = makeCoreData().migration.flags - - coreData.migration.flags = defaultFlags + coreData.migration = { ...makeCoreData().migration, legacyConfigForMigration: config } }) } } diff --git a/packages/data-context/src/actions/ProjectActions.ts b/packages/data-context/src/actions/ProjectActions.ts index 0c3be8c5255..a0d0e887dd6 100644 --- a/packages/data-context/src/actions/ProjectActions.ts +++ b/packages/data-context/src/actions/ProjectActions.ts @@ -98,6 +98,7 @@ export class ProjectActions { d.app.browserStatus = 'closed' }) + this.ctx.actions.migration.reset() await this.ctx.lifecycleManager.clearCurrentProject() resetIssuedWarnings() await this.api.closeActiveProject() diff --git a/packages/data-context/src/data/ProjectConfigManager.ts b/packages/data-context/src/data/ProjectConfigManager.ts index 753d4c5de16..30508f02ff4 100644 --- a/packages/data-context/src/data/ProjectConfigManager.ts +++ b/packages/data-context/src/data/ProjectConfigManager.ts @@ -135,6 +135,12 @@ export class ProjectConfigManager { ...loadConfigReply.requires, this.configFilePath, ]) + + // Only call "to{App,Launchpad}" once the config is done loading. + // Calling this in a "finally" would trigger this emission for every + // call to get the config (which we do a lot) + this.options.ctx.emitter.toLaunchpad() + this.options.ctx.emitter.toApp() } return loadConfigReply.initialConfig @@ -147,10 +153,10 @@ export class ProjectConfigManager { this._state = 'errored' await this.closeWatchers() - throw error - } finally { this.options.ctx.emitter.toLaunchpad() this.options.ctx.emitter.toApp() + + throw error } } diff --git a/packages/data-context/src/data/ProjectLifecycleManager.ts b/packages/data-context/src/data/ProjectLifecycleManager.ts index 0ee303f9017..8c681fbc3c4 100644 --- a/packages/data-context/src/data/ProjectLifecycleManager.ts +++ b/packages/data-context/src/data/ProjectLifecycleManager.ts @@ -103,6 +103,11 @@ export class ProjectLifecycleManager { async getProjectId (): Promise { try { + // No need to kick off config initialization if we need to migrate + if (this.ctx.migration.needsCypressJsonMigration()) { + return null + } + const contents = await this.ctx.project.getConfig() return contents.projectId ?? null @@ -458,8 +463,6 @@ export class ProjectLifecycleManager { const legacyConfigPath = path.join(projectRoot, this.ctx.migration.legacyConfigFile) if (needsCypressJsonMigration && !this.ctx.isRunMode && this.ctx.fs.existsSync(legacyConfigPath)) { - this.legacyMigration(legacyConfigPath).catch(this.onLoadError) - return false } @@ -470,8 +473,9 @@ export class ProjectLifecycleManager { return this.metaState.hasValidConfigFile } - private async legacyMigration (legacyConfigPath: string) { + async legacyMigration () { try { + const legacyConfigPath = path.join(this.projectRoot, this.ctx.migration.legacyConfigFile) // we run the legacy plugins/index.js in a child process // and mutate the config based on the return value for migration // only used in open mode (cannot migrate via terminal) @@ -480,8 +484,6 @@ export class ProjectLifecycleManager { // should never throw, unless there existing pluginsFile errors out, // in which case they are attempting to migrate an already broken project. await this.ctx.actions.migration.initialize(legacyConfig) - - this.ctx.emitter.toLaunchpad() } catch (error) { this.onLoadError(error) } diff --git a/packages/frontend-shared/src/gql-components/HeaderBarContent.vue b/packages/frontend-shared/src/gql-components/HeaderBarContent.vue index fee774a9cda..0dd818466da 100644 --- a/packages/frontend-shared/src/gql-components/HeaderBarContent.vue +++ b/packages/frontend-shared/src/gql-components/HeaderBarContent.vue @@ -217,6 +217,10 @@ mutation GlobalPageHeader_clearCurrentProject { currentProject { id } + # This ensures the cache is updated with null after clearing project + migration { + configFileNameBefore + } } } ` diff --git a/packages/graphql/src/schemaTypes/objectTypes/gql-Query.ts b/packages/graphql/src/schemaTypes/objectTypes/gql-Query.ts index 2ccad6aa708..b19ff1ee705 100644 --- a/packages/graphql/src/schemaTypes/objectTypes/gql-Query.ts +++ b/packages/graphql/src/schemaTypes/objectTypes/gql-Query.ts @@ -43,7 +43,18 @@ export const Query = objectType({ t.field('migration', { type: Migration, description: 'Metadata about the migration, null if we aren\'t showing it', - resolve: (root, args, ctx) => ctx.coreData.migration.legacyConfigForMigration ? ctx.coreData.migration : null, + resolve: async (root, args, ctx) => { + // First check to see if "legacyConfigForMigration" is defined as that means we have started migration + if (ctx.coreData.migration.legacyConfigForMigration) return ctx.coreData.migration.legacyConfigForMigration + + if (!ctx.migration.needsCypressJsonMigration()) { + return null + } + + await ctx.lifecycleManager.legacyMigration() + + return ctx.coreData.migration.legacyConfigForMigration + }, }) t.nonNull.field('dev', { diff --git a/packages/launchpad/cypress/e2e/migration.cy.ts b/packages/launchpad/cypress/e2e/migration.cy.ts index 85af6641dbd..052d27041c4 100644 --- a/packages/launchpad/cypress/e2e/migration.cy.ts +++ b/packages/launchpad/cypress/e2e/migration.cy.ts @@ -80,9 +80,7 @@ function renameSupport (lang: 'js' | 'ts' | 'coffee' = 'js') { } describe('global mode', () => { - // TODO: Figure out why it is flaky. Seems to be due to MigrationWizard query being executed multiple times - // see: https://github.com/cypress-io/cypress/issues/25377 - it.skip('migrates 2 projects in global mode', () => { + it('migrates 2 projects in global mode', () => { cy.openGlobalMode() cy.addProject('migration-e2e-export-default') cy.addProject('migration-e2e-custom-integration-with-projectId')