From 70a49def74555e0bef0a57d0b97dc437f3947f61 Mon Sep 17 00:00:00 2001 From: Gabriel-Ladzaretti <97394622+Gabriel-Ladzaretti@users.noreply.github.com> Date: Mon, 29 Aug 2022 23:08:35 +0300 Subject: [PATCH] refactor(repo/config-migration): use cached raw config file from `detectRepoFileConfig` (#17311) Co-authored-by: Rhys Arkins <rhys@arkins.net> Co-authored-by: Michael Kriese <michael.kriese@visualon.de> --- .../branch/migrated-data.spec.ts | 32 ++++++++---- .../config-migration/branch/migrated-data.ts | 15 +++--- .../config-migration/branch/rebase.ts | 11 +--- .../repository/config-migration/index.spec.ts | 51 +++++++++++++++++++ .../repository/config-migration/index.ts | 22 ++++++++ lib/workers/repository/finalise/index.ts | 18 +------ 6 files changed, 109 insertions(+), 40 deletions(-) create mode 100644 lib/workers/repository/config-migration/index.spec.ts create mode 100644 lib/workers/repository/config-migration/index.ts diff --git a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts index 49978519f2..b43ca2b6f8 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts @@ -3,6 +3,7 @@ import { Fixtures } from '../../../../../test/fixtures'; import { mockedFunction } from '../../../../../test/util'; import { migrateConfig } from '../../../../config/migration'; +import { logger } from '../../../../logger'; import { readLocalFile } from '../../../../util/fs'; import { getFileList } from '../../../../util/git'; import { detectRepoFileConfig } from '../../init/merge'; @@ -34,8 +35,8 @@ describe('workers/repository/config-migration/branch/migrated-data', () => { }); mockedFunction(detectRepoFileConfig).mockResolvedValue({ configFileName: 'renovate.json', + configFileRaw: rawNonMigrated, }); - mockedFunction(readLocalFile).mockResolvedValue(rawNonMigrated); mockedFunction(migrateConfig).mockReturnValue({ isMigrated: true, migratedConfig: migratedConfigObj, @@ -100,28 +101,29 @@ describe('workers/repository/config-migration/branch/migrated-data', () => { it('Migrate a JSON5 config file', async () => { mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ configFileName: 'renovate.json5', + configFileRaw: rawNonMigratedJson5, }); - mockedFunction(readLocalFile).mockResolvedValueOnce(rawNonMigratedJson5); MigratedDataFactory.reset(); await expect(MigratedDataFactory.getAsync()).resolves.toEqual( migratedDataJson5 ); }); - it('Returns nothing due to fs error', async () => { - mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ - configFileName: undefined, - }); - mockedFunction(readLocalFile).mockRejectedValueOnce(null); + it('Returns nothing due to detectRepoFileConfig throwing', async () => { + const err = new Error('error-message'); + mockedFunction(detectRepoFileConfig).mockRejectedValueOnce(err); MigratedDataFactory.reset(); await expect(MigratedDataFactory.getAsync()).resolves.toBeNull(); + expect(logger.debug).toHaveBeenCalledWith( + { err }, + 'MigratedDataFactory.getAsync() Error initializing renovate MigratedData' + ); }); it('format and migrate a JSON config file', async () => { mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ configFileName: 'renovate.json', }); - mockedFunction(readLocalFile).mockResolvedValueOnce(rawNonMigrated); mockedFunction(getFileList).mockResolvedValue(['.prettierrc']); MigratedDataFactory.reset(); await expect(MigratedDataFactory.getAsync()).resolves.toEqual( @@ -132,9 +134,21 @@ describe('workers/repository/config-migration/branch/migrated-data', () => { it('should not stop run for invalid package.json', async () => { mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ configFileName: 'renovate.json', + configFileRaw: 'abci', }); mockedFunction(readLocalFile).mockResolvedValueOnce(rawNonMigrated); - mockedFunction(readLocalFile).mockResolvedValue('abci'); + MigratedDataFactory.reset(); + await expect(MigratedDataFactory.getAsync()).resolves.toEqual( + migratedData + ); + }); + + it('should not stop run for readLocalFile error', async () => { + mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ + configFileName: 'renovate.json', + configFileRaw: 'abci', + }); + mockedFunction(readLocalFile).mockRejectedValueOnce(null); MigratedDataFactory.reset(); await expect(MigratedDataFactory.getAsync()).resolves.toEqual( migratedData diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index da22bb5f4b..a6062a49a3 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -45,7 +45,9 @@ export async function applyPrettierFormatting( prettierExists = packageJsonContent && JSON.parse(packageJsonContent).prettier; } catch { - logger.warn('Invalid JSON found in package.json'); + logger.warn( + 'applyPrettierFormatting() - Error processing package.json file' + ); } } @@ -86,8 +88,11 @@ export class MigratedDataFactory { private static async build(): Promise<MigratedData | null> { let res: MigratedData | null = null; try { - const rc = await detectRepoFileConfig(); - const configFileParsed = rc?.configFileParsed || {}; + const { + configFileName, + configFileRaw: raw, + configFileParsed = {}, + } = await detectRepoFileConfig(); // get migrated config const { isMigrated, migratedConfig } = migrateConfig(configFileParsed); @@ -98,13 +103,11 @@ export class MigratedDataFactory { delete migratedConfig.errors; delete migratedConfig.warnings; - const filename = rc.configFileName ?? ''; - const raw = await readLocalFile(filename, 'utf8'); - // indent defaults to 2 spaces // TODO #7154 const indent = detectIndent(raw!); const indentSpace = indent.indent ?? ' '; + const filename = configFileName!; let content: string; if (filename.endsWith('.json5')) { diff --git a/lib/workers/repository/config-migration/branch/rebase.ts b/lib/workers/repository/config-migration/branch/rebase.ts index fc3817f2b4..1da3459f0a 100644 --- a/lib/workers/repository/config-migration/branch/rebase.ts +++ b/lib/workers/repository/config-migration/branch/rebase.ts @@ -2,11 +2,7 @@ import { GlobalConfig } from '../../../../config/global'; import type { RenovateConfig } from '../../../../config/types'; import { logger } from '../../../../logger'; import { commitAndPush } from '../../../../modules/platform/commit'; -import { - getFile, - isBranchBehindBase, - isBranchModified, -} from '../../../../util/git'; +import { getFile, isBranchModified } from '../../../../util/git'; import { getMigrationBranchName } from '../common'; import { ConfigMigrationCommitMessageFactory } from './commit-message'; import type { MigratedData } from './migrated-data'; @@ -24,10 +20,7 @@ export async function rebaseMigrationBranch( const configFileName = migratedConfigData.filename; const contents = migratedConfigData.content; const existingContents = await getFile(configFileName, branchName); - if ( - contents === existingContents && - !(await isBranchBehindBase(branchName)) - ) { + if (contents === existingContents) { logger.debug('Migration branch is up to date'); return null; } diff --git a/lib/workers/repository/config-migration/index.spec.ts b/lib/workers/repository/config-migration/index.spec.ts new file mode 100644 index 0000000000..0a4380e34c --- /dev/null +++ b/lib/workers/repository/config-migration/index.spec.ts @@ -0,0 +1,51 @@ +import { Fixtures } from '../../../../test/fixtures'; +import { defaultConfig, mockedFunction } from '../../../../test/util'; +import { checkConfigMigrationBranch } from './branch'; +import { MigratedDataFactory } from './branch/migrated-data'; +import { ensureConfigMigrationPr } from './pr'; +import { configMigration } from './index'; + +jest.mock('./pr'); +jest.mock('./branch'); +jest.mock('./branch/migrated-data'); + +const content = Fixtures.getJson('./migrated-data.json', './branch'); +const filename = 'renovate.json'; +const branchName = 'renovate/config-migration'; +const config = { + ...defaultConfig, + configMigration: true, +}; + +describe('workers/repository/config-migration/index', () => { + beforeEach(() => { + jest.resetAllMocks(); + mockedFunction(MigratedDataFactory.getAsync).mockResolvedValue({ + filename, + content, + }); + }); + + it('does nothing when config migration is disabled', async () => { + await configMigration({ ...config, configMigration: false }, []); + expect(MigratedDataFactory.getAsync).toHaveBeenCalledTimes(0); + expect(checkConfigMigrationBranch).toHaveBeenCalledTimes(0); + expect(ensureConfigMigrationPr).toHaveBeenCalledTimes(0); + }); + + it('ensures config migration PR when migrated', async () => { + const branchList: string[] = []; + mockedFunction(checkConfigMigrationBranch).mockResolvedValue(branchName); + await configMigration(config, branchList); + expect(branchList).toContainEqual(branchName); + expect(ensureConfigMigrationPr).toHaveBeenCalledTimes(1); + }); + + it('skips pr creation when migration is not needed', async () => { + const branchList: string[] = []; + mockedFunction(checkConfigMigrationBranch).mockResolvedValue(null); + await configMigration(config, branchList); + expect(checkConfigMigrationBranch).toHaveBeenCalledTimes(1); + expect(ensureConfigMigrationPr).toHaveBeenCalledTimes(0); + }); +}); diff --git a/lib/workers/repository/config-migration/index.ts b/lib/workers/repository/config-migration/index.ts new file mode 100644 index 0000000000..33a401d063 --- /dev/null +++ b/lib/workers/repository/config-migration/index.ts @@ -0,0 +1,22 @@ +import type { RenovateConfig } from '../../../config/types'; +import { checkConfigMigrationBranch } from './branch'; +import { MigratedDataFactory } from './branch/migrated-data'; +import { ensureConfigMigrationPr } from './pr'; + +export async function configMigration( + config: RenovateConfig, + branchList: string[] +): Promise<void> { + if (config.configMigration) { + const migratedConfigData = await MigratedDataFactory.getAsync(); + const migrationBranch = await checkConfigMigrationBranch( + config, + migratedConfigData + ); // null if migration not needed + if (migrationBranch) { + branchList.push(migrationBranch); + await ensureConfigMigrationPr(config, migratedConfigData!); + } + MigratedDataFactory.reset(); + } +} diff --git a/lib/workers/repository/finalise/index.ts b/lib/workers/repository/finalise/index.ts index 5a588bda29..0c8f93dcf7 100644 --- a/lib/workers/repository/finalise/index.ts +++ b/lib/workers/repository/finalise/index.ts @@ -1,12 +1,9 @@ -/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ import type { RenovateConfig } from '../../../config/types'; import { logger } from '../../../logger'; import { platform } from '../../../modules/platform'; import * as repositoryCache from '../../../util/cache/repository'; import { clearRenovateRefs } from '../../../util/git'; -import { checkConfigMigrationBranch } from '../config-migration/branch'; -import { MigratedDataFactory } from '../config-migration/branch/migrated-data'; -import { ensureConfigMigrationPr } from '../config-migration/pr'; +import { configMigration } from '../config-migration'; import { PackageFiles } from '../package-files'; import { pruneStaleBranches } from './prune'; import { runRenovateRepoStats } from './repository-statistics'; @@ -16,18 +13,7 @@ export async function finaliseRepo( config: RenovateConfig, branchList: string[] ): Promise<void> { - if (config.configMigration) { - const migratedConfigData = await MigratedDataFactory.getAsync(); - const migrationBranch = await checkConfigMigrationBranch( - config, - migratedConfigData! - ); // null if migration not needed - if (migrationBranch) { - branchList.push(migrationBranch); - await ensureConfigMigrationPr(config, migratedConfigData!); - } - MigratedDataFactory.reset(); - } + await configMigration(config, branchList); await repositoryCache.saveCache(); await pruneStaleBranches(config, branchList); await platform.ensureIssueClosing( -- GitLab