From d5fad163146bf995e0706f9b613791c8f442198e Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 7 Jul 2022 20:54:43 +0530 Subject: [PATCH 01/23] feat: format migratedJSON --- lib/util/fs/index.ts | 5 ++++- lib/util/git/index.ts | 11 +++++++++++ package.json | 4 +--- yarn.lock | 3 +-- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/lib/util/fs/index.ts b/lib/util/fs/index.ts index 1bafad0adc75e7..3809f1b59c8101 100644 --- a/lib/util/fs/index.ts +++ b/lib/util/fs/index.ts @@ -43,7 +43,10 @@ export async function readLocalFile( return null; } } - +export function readLocalPath(fileName: string): string | null { + const { localDir } = GlobalConfig.get(); + return upath.join(localDir, fileName); +} export async function writeLocalFile( fileName: string, fileContent: string | Buffer diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index a1f8b317fb485e..76cee7f89b9fe1 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -2,6 +2,8 @@ import URL from 'url'; import is from '@sindresorhus/is'; import delay from 'delay'; import fs from 'fs-extra'; +// eslint-disable-next-line import/no-extraneous-dependencies +import prettier from 'prettier'; import simpleGit, { Options, ResetMode, @@ -26,6 +28,7 @@ import { api as semverCoerced } from '../../modules/versioning/semver-coerced'; import { ExternalHostError } from '../../types/errors/external-host-error'; import type { GitProtocol } from '../../types/git'; import { Limit, incLimitedValue } from '../../workers/global/limits'; +import { readLocalPath } from '../fs'; import { newlineRegex, regEx } from '../regex'; import { parseGitAuthor } from './author'; import { getNoVerify, simpleGitConfig } from './config'; @@ -875,6 +878,14 @@ export async function prepareCommit({ let contents: Buffer; // istanbul ignore else if (typeof file.contents === 'string') { + if (/migrate-config/g.exec(branchName)) { + const prettierConfigPath = readLocalPath(fileName); + const options = await prettier.resolveConfig(prettierConfigPath!); + file.contents = prettier.format( + file.contents.replace(/\s{2}/g, ''), + { filepath: fileName, ...options } + ); + } contents = Buffer.from(file.contents); } else { contents = file.contents; diff --git a/package.json b/package.json index 4ed6d3274ebeaa..38ffb60701e58d 100644 --- a/package.json +++ b/package.json @@ -309,7 +309,5 @@ "@types/jest/jest-matcher-utils": "^28.0.0", "@types/jest/pretty-format": "^28.0.0" }, - "files": [ - "dist" - ] + "files": ["dist"] } diff --git a/yarn.lock b/yarn.lock index f06e3199bd58c6..8870116cac15e1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2072,7 +2072,6 @@ "@renovate/eslint-plugin@https://github.com/renovatebot/eslint-plugin#v0.0.4": version "0.0.4" - uid "0c444386e79d6145901212507521b8a0a48af000" resolved "https://github.com/renovatebot/eslint-plugin#0c444386e79d6145901212507521b8a0a48af000" "@renovatebot/pep440@2.1.3": @@ -2644,7 +2643,7 @@ resolved "https://registry.yarnpkg.com/@types/parse-link-header/-/parse-link-header-2.0.0.tgz#a94d86ac2d13e3cdef4429c977217084e32378e7" integrity sha512-KbqcQLdRaawDOfXnwqr6nvhe1MV+Uv/Ww+ViSx7Ujgw9X5qCgObLP52B1ZSJqZD8FK1y/4o+bJQTUrZOynegcg== -"@types/prettier@^2.1.5": +"@types/prettier@2.6.3", "@types/prettier@^2.1.5": version "2.6.3" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.3.tgz#68ada76827b0010d0db071f739314fa429943d0a" integrity sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg== From bb906eef68d70c9fd6588327f47b1305880a6ccf Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 7 Jul 2022 20:57:58 +0530 Subject: [PATCH 02/23] Update package.json --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 38ffb60701e58d..4ed6d3274ebeaa 100644 --- a/package.json +++ b/package.json @@ -309,5 +309,7 @@ "@types/jest/jest-matcher-utils": "^28.0.0", "@types/jest/pretty-format": "^28.0.0" }, - "files": ["dist"] + "files": [ + "dist" + ] } From 18d8cc2438659a72ebfbf6b4642abe9f6caa7b63 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 7 Jul 2022 20:58:45 +0530 Subject: [PATCH 03/23] Update yarn.lock --- yarn.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/yarn.lock b/yarn.lock index 8870116cac15e1..de23dc23ea7b20 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2072,6 +2072,7 @@ "@renovate/eslint-plugin@https://github.com/renovatebot/eslint-plugin#v0.0.4": version "0.0.4" + uid "0c444386e79d6145901212507521b8a0a48af000" resolved "https://github.com/renovatebot/eslint-plugin#0c444386e79d6145901212507521b8a0a48af000" "@renovatebot/pep440@2.1.3": From e4ede927f47e3fa43924e46546ab41c51e4f28b5 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 7 Jul 2022 20:59:25 +0530 Subject: [PATCH 04/23] Update yarn.lock --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index de23dc23ea7b20..f06e3199bd58c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2644,7 +2644,7 @@ resolved "https://registry.yarnpkg.com/@types/parse-link-header/-/parse-link-header-2.0.0.tgz#a94d86ac2d13e3cdef4429c977217084e32378e7" integrity sha512-KbqcQLdRaawDOfXnwqr6nvhe1MV+Uv/Ww+ViSx7Ujgw9X5qCgObLP52B1ZSJqZD8FK1y/4o+bJQTUrZOynegcg== -"@types/prettier@2.6.3", "@types/prettier@^2.1.5": +"@types/prettier@^2.1.5": version "2.6.3" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.3.tgz#68ada76827b0010d0db071f739314fa429943d0a" integrity sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg== From 28d5a9f373058ff7d184067d08043c438875e6ca Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 7 Jul 2022 21:05:47 +0530 Subject: [PATCH 05/23] add @types/prettier to dependencies list --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 4ed6d3274ebeaa..21f9210ff286fb 100644 --- a/package.json +++ b/package.json @@ -143,6 +143,7 @@ "@renovatebot/pep440": "2.1.3", "@renovatebot/ruby-semver": "1.1.4", "@sindresorhus/is": "4.6.0", + "@types/prettier": "2.1.5", "@types/tmp": "0.2.3", "@yarnpkg/core": "3.1.0", "@yarnpkg/parsers": "2.5.1", From 6fb990bc5767c21d10cec5776cbdc032ce53ce50 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 7 Jul 2022 21:06:25 +0530 Subject: [PATCH 06/23] feat: skip formatting if options is null --- lib/util/fs/index.ts | 2 +- lib/util/git/index.ts | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/util/fs/index.ts b/lib/util/fs/index.ts index 3809f1b59c8101..cb8a616cd85c42 100644 --- a/lib/util/fs/index.ts +++ b/lib/util/fs/index.ts @@ -43,7 +43,7 @@ export async function readLocalFile( return null; } } -export function readLocalPath(fileName: string): string | null { +export function readLocalPath(fileName: string): string { const { localDir } = GlobalConfig.get(); return upath.join(localDir, fileName); } diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index 76cee7f89b9fe1..5ecc53dd4266b1 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -2,7 +2,6 @@ import URL from 'url'; import is from '@sindresorhus/is'; import delay from 'delay'; import fs from 'fs-extra'; -// eslint-disable-next-line import/no-extraneous-dependencies import prettier from 'prettier'; import simpleGit, { Options, @@ -880,11 +879,13 @@ export async function prepareCommit({ if (typeof file.contents === 'string') { if (/migrate-config/g.exec(branchName)) { const prettierConfigPath = readLocalPath(fileName); - const options = await prettier.resolveConfig(prettierConfigPath!); - file.contents = prettier.format( - file.contents.replace(/\s{2}/g, ''), - { filepath: fileName, ...options } - ); + const options = await prettier.resolveConfig(prettierConfigPath); + if (!is.null_(options)) { + file.contents = prettier.format( + file.contents.replace(/\s{2}/g, ''), + { filepath: fileName, ...options } + ); + } } contents = Buffer.from(file.contents); } else { From 230b8dc5e23566b657ab3d43e0767214ca793b0d Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 7 Jul 2022 21:10:18 +0530 Subject: [PATCH 07/23] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 21f9210ff286fb..9444e6bd233f5c 100644 --- a/package.json +++ b/package.json @@ -143,7 +143,7 @@ "@renovatebot/pep440": "2.1.3", "@renovatebot/ruby-semver": "1.1.4", "@sindresorhus/is": "4.6.0", - "@types/prettier": "2.1.5", + "@types/prettier": "2.6.3", "@types/tmp": "0.2.3", "@yarnpkg/core": "3.1.0", "@yarnpkg/parsers": "2.5.1", From 3b6320585fbd0a6d3d7f5128b7dee3749df3b959 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 7 Jul 2022 21:14:19 +0530 Subject: [PATCH 08/23] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9444e6bd233f5c..21f9210ff286fb 100644 --- a/package.json +++ b/package.json @@ -143,7 +143,7 @@ "@renovatebot/pep440": "2.1.3", "@renovatebot/ruby-semver": "1.1.4", "@sindresorhus/is": "4.6.0", - "@types/prettier": "2.6.3", + "@types/prettier": "2.1.5", "@types/tmp": "0.2.3", "@yarnpkg/core": "3.1.0", "@yarnpkg/parsers": "2.5.1", From 14b52ffdcdb91c3a6a85d877afb32f1d2b6908de Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 7 Jul 2022 21:21:33 +0530 Subject: [PATCH 09/23] revert changes to yarn.lock --- yarn.lock | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yarn.lock b/yarn.lock index f06e3199bd58c6..2415f5aa5b7442 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2644,6 +2644,11 @@ resolved "https://registry.yarnpkg.com/@types/parse-link-header/-/parse-link-header-2.0.0.tgz#a94d86ac2d13e3cdef4429c977217084e32378e7" integrity sha512-KbqcQLdRaawDOfXnwqr6nvhe1MV+Uv/Ww+ViSx7Ujgw9X5qCgObLP52B1ZSJqZD8FK1y/4o+bJQTUrZOynegcg== +"@types/prettier@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.5.tgz#b6ab3bba29e16b821d84e09ecfaded462b816b00" + integrity sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ== + "@types/prettier@^2.1.5": version "2.6.3" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.3.tgz#68ada76827b0010d0db071f739314fa429943d0a" From 321e23cf7089ab728fc131d4e604737f0c740d05 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 7 Jul 2022 23:32:21 +0530 Subject: [PATCH 10/23] move prettier formatting --- lib/util/fs/index.ts | 5 +--- lib/util/git/index.ts | 12 -------- .../config-migration/branch/migrated-data.ts | 29 ++++++++++++++++++- package.json | 3 +- yarn.lock | 5 ---- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/lib/util/fs/index.ts b/lib/util/fs/index.ts index cb8a616cd85c42..1bafad0adc75e7 100644 --- a/lib/util/fs/index.ts +++ b/lib/util/fs/index.ts @@ -43,10 +43,7 @@ export async function readLocalFile( return null; } } -export function readLocalPath(fileName: string): string { - const { localDir } = GlobalConfig.get(); - return upath.join(localDir, fileName); -} + export async function writeLocalFile( fileName: string, fileContent: string | Buffer diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index 5ecc53dd4266b1..a1f8b317fb485e 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -2,7 +2,6 @@ import URL from 'url'; import is from '@sindresorhus/is'; import delay from 'delay'; import fs from 'fs-extra'; -import prettier from 'prettier'; import simpleGit, { Options, ResetMode, @@ -27,7 +26,6 @@ import { api as semverCoerced } from '../../modules/versioning/semver-coerced'; import { ExternalHostError } from '../../types/errors/external-host-error'; import type { GitProtocol } from '../../types/git'; import { Limit, incLimitedValue } from '../../workers/global/limits'; -import { readLocalPath } from '../fs'; import { newlineRegex, regEx } from '../regex'; import { parseGitAuthor } from './author'; import { getNoVerify, simpleGitConfig } from './config'; @@ -877,16 +875,6 @@ export async function prepareCommit({ let contents: Buffer; // istanbul ignore else if (typeof file.contents === 'string') { - if (/migrate-config/g.exec(branchName)) { - const prettierConfigPath = readLocalPath(fileName); - const options = await prettier.resolveConfig(prettierConfigPath); - if (!is.null_(options)) { - file.contents = prettier.format( - file.contents.replace(/\s{2}/g, ''), - { filepath: fileName, ...options } - ); - } - } contents = Buffer.from(file.contents); } else { contents = file.contents; diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index 0812fbc9c86bfa..708c9c78f5fc36 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -1,15 +1,41 @@ +import is from '@sindresorhus/is'; import detectIndent from 'detect-indent'; import JSON5 from 'json5'; +import prettier from 'prettier'; import { migrateConfig } from '../../../../config/migration'; import { logger } from '../../../../logger'; import { readLocalFile } from '../../../../util/fs'; +import { getFileList } from '../../../../util/git'; import { detectRepoFileConfig } from '../../init/merge'; - export interface MigratedData { content: string; filename: string; } +async function applyPrettierFormatting( + content: string, + fileName: string +): Promise { + const prettierConfigFilenames = ['.prettierrc']; + const prettierExists = (await getFileList()).some((file) => + prettierConfigFilenames.includes(file) + ); + + let newContent = content; + + if (!is.null_(prettierExists)) { + const options = await prettier.resolveConfig('.prettierrc'); // renovate's prettierrc config + if (!is.null_(options)) { + newContent = prettier.format(content, { + filepath: fileName, + ...options, + }); + } + } + + return newContent; +} + export class MigratedDataFactory { // singleton private static data: MigratedData | null; @@ -61,6 +87,7 @@ export class MigratedDataFactory { content = JSON.stringify(migratedConfig, undefined, indent); } + content = await applyPrettierFormatting(content, filename); if (!content.endsWith('\n')) { content += '\n'; } diff --git a/package.json b/package.json index 21f9210ff286fb..b2d1fbf71f7832 100644 --- a/package.json +++ b/package.json @@ -143,7 +143,6 @@ "@renovatebot/pep440": "2.1.3", "@renovatebot/ruby-semver": "1.1.4", "@sindresorhus/is": "4.6.0", - "@types/prettier": "2.1.5", "@types/tmp": "0.2.3", "@yarnpkg/core": "3.1.0", "@yarnpkg/parsers": "2.5.1", @@ -198,6 +197,7 @@ "p-map": "4.0.0", "p-queue": "6.6.2", "parse-link-header": "2.0.0", + "prettier": "2.7.1", "redis": "4.1.0", "remark": "13.0.0", "remark-github": "10.1.0", @@ -292,7 +292,6 @@ "mockdate": "3.0.5", "nock": "13.2.7", "npm-run-all": "4.1.5", - "prettier": "2.7.1", "pretty-quick": "3.1.3", "rimraf": "3.0.2", "semantic-release": "19.0.3", diff --git a/yarn.lock b/yarn.lock index 2415f5aa5b7442..f06e3199bd58c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2644,11 +2644,6 @@ resolved "https://registry.yarnpkg.com/@types/parse-link-header/-/parse-link-header-2.0.0.tgz#a94d86ac2d13e3cdef4429c977217084e32378e7" integrity sha512-KbqcQLdRaawDOfXnwqr6nvhe1MV+Uv/Ww+ViSx7Ujgw9X5qCgObLP52B1ZSJqZD8FK1y/4o+bJQTUrZOynegcg== -"@types/prettier@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.5.tgz#b6ab3bba29e16b821d84e09ecfaded462b816b00" - integrity sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ== - "@types/prettier@^2.1.5": version "2.6.3" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.3.tgz#68ada76827b0010d0db071f739314fa429943d0a" From a52633f3955da8401b0eea89419d8b355e1792db Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Fri, 8 Jul 2022 00:19:42 +0530 Subject: [PATCH 11/23] refactor: update tests --- .../__fixtures__/migrated-data-formatted.json | 4 ++++ .../branch/migrated-data.spec.ts | 18 ++++++++++++++++++ .../config-migration/branch/migrated-data.ts | 19 ++++++++++++++++--- 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 lib/workers/repository/config-migration/branch/__fixtures__/migrated-data-formatted.json diff --git a/lib/workers/repository/config-migration/branch/__fixtures__/migrated-data-formatted.json b/lib/workers/repository/config-migration/branch/__fixtures__/migrated-data-formatted.json new file mode 100644 index 00000000000000..dd59ce68ff3f74 --- /dev/null +++ b/lib/workers/repository/config-migration/branch/__fixtures__/migrated-data-formatted.json @@ -0,0 +1,4 @@ +{ + "filename": "renovate.json", + "content": "{\n \"extends\": [\n \":separateMajorReleases\",\n \":prImmediately\",\n \":renovatePrefix\",\n \":semanticPrefixFixDepsChoreOthers\",\n \":updateNotScheduled\",\n \":automergeDisabled\",\n \":maintainLockFilesDisabled\",\n \":autodetectPinVersions\",\n \"group:monorepos\"\n ],\n \"onboarding\": false,\n \"rangeStrategy\": \"replace\",\n \"semanticCommits\": \"enabled\",\n \"timezone\": \"US/Central\",\n \"baseBranches\": [\"main\"]\n}\n" +} 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 0e4074c741a0c7..6ff76baa0cf392 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts @@ -4,10 +4,12 @@ import { mockedFunction } from '../../../../../test/util'; import { migrateConfig } from '../../../../config/migration'; import { readLocalFile } from '../../../../util/fs'; +import { getFileList } from '../../../../util/git'; import { detectRepoFileConfig } from '../../init/merge'; import { MigratedDataFactory } from './migrated-data'; jest.mock('../../../../config/migration'); +jest.mock('../../../../util/git'); jest.mock('../../../../util/fs'); jest.mock('../../init/merge'); jest.mock('detect-indent'); @@ -17,6 +19,9 @@ const rawNonMigratedJson5 = Fixtures.get('./renovate.json5'); const migratedData = Fixtures.getJson('./migrated-data.json'); const migratedDataJson5 = Fixtures.getJson('./migrated-data.json5'); const migratedConfigObj = Fixtures.getJson('./migrated.json'); +const formattedMigratedData = Fixtures.getJson( + './migrated-data-formatted.json' +); describe('workers/repository/config-migration/branch/migrated-data', () => { describe('MigratedDataFactory.getAsync', () => { @@ -35,6 +40,7 @@ describe('workers/repository/config-migration/branch/migrated-data', () => { isMigrated: true, migratedConfig: migratedConfigObj, }); + mockedFunction(getFileList).mockResolvedValue([]); }); it('Calls getAsync a first when migration not needed', async () => { @@ -102,6 +108,18 @@ describe('workers/repository/config-migration/branch/migrated-data', () => { ); }); + 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( + formattedMigratedData + ); + }); + it('Returns nothing due to fs error', async () => { mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ configFileName: undefined, diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index 708c9c78f5fc36..1747b3b72997b8 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -16,14 +16,27 @@ async function applyPrettierFormatting( content: string, fileName: string ): Promise { - const prettierConfigFilenames = ['.prettierrc']; - const prettierExists = (await getFileList()).some((file) => + const prettierConfigFilenames = [ + '.prettierrc', + '.prettierrc.json', + '.prettierrc.yml', + '.prettierrc.yaml', + '.prettierrc.json5', + '.prettierrc.js', + '.prettierrc.cjs', + 'prettier.config.js', + 'prettier.config.cjs', + '.prettierrc.toml', + ]; + let prettierExists = (await getFileList()).some((file) => prettierConfigFilenames.includes(file) ); + const checkPackageJson = await readLocalFile('package.json', 'utf8'); + prettierExists ||= checkPackageJson && JSON.parse(checkPackageJson).prettier; let newContent = content; - if (!is.null_(prettierExists)) { + if (prettierExists) { const options = await prettier.resolveConfig('.prettierrc'); // renovate's prettierrc config if (!is.null_(options)) { newContent = prettier.format(content, { From 7a4ce4de146bdbcaa54a685c4f75135539274ca7 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Fri, 8 Jul 2022 00:22:19 +0530 Subject: [PATCH 12/23] refactor: rename var --- .../repository/config-migration/branch/migrated-data.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index 1747b3b72997b8..1759cd1f0fbdbb 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -31,8 +31,9 @@ async function applyPrettierFormatting( let prettierExists = (await getFileList()).some((file) => prettierConfigFilenames.includes(file) ); - const checkPackageJson = await readLocalFile('package.json', 'utf8'); - prettierExists ||= checkPackageJson && JSON.parse(checkPackageJson).prettier; + const packageJsonContent = await readLocalFile('package.json', 'utf8'); + prettierExists ||= + packageJsonContent && JSON.parse(packageJsonContent).prettier; let newContent = content; From 0b49cd98e90f868add3f6a9ee47be13ca6de4312 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Fri, 8 Jul 2022 11:56:30 +0530 Subject: [PATCH 13/23] refactor: add test + apply suggestions --- .../branch/migrated-data.spec.ts | 20 ++++++++++++--- .../config-migration/branch/migrated-data.ts | 25 ++++++++++--------- 2 files changed, 29 insertions(+), 16 deletions(-) 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 6ff76baa0cf392..91af8838eecef3 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts @@ -108,6 +108,15 @@ describe('workers/repository/config-migration/branch/migrated-data', () => { ); }); + it('Returns nothing due to fs error', async () => { + mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ + configFileName: undefined, + }); + mockedFunction(readLocalFile).mockRejectedValueOnce(null); + MigratedDataFactory.reset(); + await expect(MigratedDataFactory.getAsync()).resolves.toBeNull(); + }); + it('format and migrate a JSON config file', async () => { mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ configFileName: 'renovate.json', @@ -120,13 +129,16 @@ describe('workers/repository/config-migration/branch/migrated-data', () => { ); }); - it('Returns nothing due to fs error', async () => { + it('should not stop run for invalid package.json', async () => { mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ - configFileName: undefined, + configFileName: 'renovate.json', }); - mockedFunction(readLocalFile).mockRejectedValueOnce(null); + mockedFunction(readLocalFile).mockResolvedValueOnce(rawNonMigrated); + mockedFunction(readLocalFile).mockResolvedValue('abci'); MigratedDataFactory.reset(); - await expect(MigratedDataFactory.getAsync()).resolves.toBeNull(); + 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 1759cd1f0fbdbb..fad202a984fc01 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -1,4 +1,3 @@ -import is from '@sindresorhus/is'; import detectIndent from 'detect-indent'; import JSON5 from 'json5'; import prettier from 'prettier'; @@ -32,20 +31,22 @@ async function applyPrettierFormatting( prettierConfigFilenames.includes(file) ); const packageJsonContent = await readLocalFile('package.json', 'utf8'); - prettierExists ||= - packageJsonContent && JSON.parse(packageJsonContent).prettier; + try { + prettierExists ||= + packageJsonContent && JSON.parse(packageJsonContent).prettier; + } catch { + logger.warn('Invalid JSON found in package.json'); + } + + if (!prettierExists) { + return content; + } let newContent = content; - if (prettierExists) { - const options = await prettier.resolveConfig('.prettierrc'); // renovate's prettierrc config - if (!is.null_(options)) { - newContent = prettier.format(content, { - filepath: fileName, - ...options, - }); - } - } + newContent = prettier.format(content, { + filepath: fileName, + }); return newContent; } From 51c715008ec68bd95855f9e4d9f348cff3acb36c Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Fri, 8 Jul 2022 12:37:49 +0530 Subject: [PATCH 14/23] refactor: add test to check working for invalid content --- .../config-migration/branch/migrated-data.spec.ts | 8 +++++++- .../repository/config-migration/branch/migrated-data.ts | 8 ++------ 2 files changed, 9 insertions(+), 7 deletions(-) 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 91af8838eecef3..8209e0f4f1b58a 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts @@ -6,7 +6,7 @@ import { migrateConfig } from '../../../../config/migration'; import { readLocalFile } from '../../../../util/fs'; import { getFileList } from '../../../../util/git'; import { detectRepoFileConfig } from '../../init/merge'; -import { MigratedDataFactory } from './migrated-data'; +import { MigratedDataFactory, applyPrettierFormatting } from './migrated-data'; jest.mock('../../../../config/migration'); jest.mock('../../../../util/git'); @@ -140,5 +140,11 @@ describe('workers/repository/config-migration/branch/migrated-data', () => { migratedData ); }); + + it('return original content if its invalid', async () => { + await expect( + applyPrettierFormatting(`{"name":"Rahul"`, 'renovate.json') + ).resolves.toBe(`{"name":"Rahul"`); + }); }); }); diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index fad202a984fc01..97b894babd2fe2 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -11,7 +11,7 @@ export interface MigratedData { filename: string; } -async function applyPrettierFormatting( +export async function applyPrettierFormatting( content: string, fileName: string ): Promise { @@ -42,13 +42,9 @@ async function applyPrettierFormatting( return content; } - let newContent = content; - - newContent = prettier.format(content, { + return prettier.format(content, { filepath: fileName, }); - - return newContent; } export class MigratedDataFactory { From afe9b3bf17307d8f8a4224c6662a01fe01f5f059 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Fri, 8 Jul 2022 12:39:28 +0530 Subject: [PATCH 15/23] refactor: update test --- .../repository/config-migration/branch/migrated-data.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 8209e0f4f1b58a..1eb83ddc55bb5d 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts @@ -143,7 +143,7 @@ describe('workers/repository/config-migration/branch/migrated-data', () => { it('return original content if its invalid', async () => { await expect( - applyPrettierFormatting(`{"name":"Rahul"`, 'renovate.json') + applyPrettierFormatting(`{"name":"Rahul"`, 'renovate.yaml') ).resolves.toBe(`{"name":"Rahul"`); }); }); From c26764f34ac1a2167d32d4acac5afe8d2bff2d39 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sun, 10 Jul 2022 01:13:49 +0530 Subject: [PATCH 16/23] update options --- .../config-migration/branch/migrated-data.spec.ts | 6 +++--- .../repository/config-migration/branch/migrated-data.ts | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) 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 1eb83ddc55bb5d..52cce13a08eb30 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts @@ -142,9 +142,9 @@ describe('workers/repository/config-migration/branch/migrated-data', () => { }); it('return original content if its invalid', async () => { - await expect( - applyPrettierFormatting(`{"name":"Rahul"`, 'renovate.yaml') - ).resolves.toBe(`{"name":"Rahul"`); + await expect(applyPrettierFormatting(`{"name":"Rahul"`)).resolves.toBe( + `{"name":"Rahul"` + ); }); }); }); diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index 97b894babd2fe2..741e076acc8e8d 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -12,8 +12,7 @@ export interface MigratedData { } export async function applyPrettierFormatting( - content: string, - fileName: string + content: string ): Promise { const prettierConfigFilenames = [ '.prettierrc', @@ -43,7 +42,7 @@ export async function applyPrettierFormatting( } return prettier.format(content, { - filepath: fileName, + parser: 'json', }); } @@ -98,7 +97,7 @@ export class MigratedDataFactory { content = JSON.stringify(migratedConfig, undefined, indent); } - content = await applyPrettierFormatting(content, filename); + content = await applyPrettierFormatting(content); if (!content.endsWith('\n')) { content += '\n'; } From 859630dda1f7f50acc373edddf349d6aed87693b Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sun, 10 Jul 2022 23:59:46 +0530 Subject: [PATCH 17/23] apply suggestions --- .../config-migration/branch/migrated-data.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index 741e076acc8e8d..bb4b4efde33486 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -6,6 +6,7 @@ import { logger } from '../../../../logger'; import { readLocalFile } from '../../../../util/fs'; import { getFileList } from '../../../../util/git'; import { detectRepoFileConfig } from '../../init/merge'; + export interface MigratedData { content: string; filename: string; @@ -29,12 +30,14 @@ export async function applyPrettierFormatting( let prettierExists = (await getFileList()).some((file) => prettierConfigFilenames.includes(file) ); - const packageJsonContent = await readLocalFile('package.json', 'utf8'); - try { - prettierExists ||= - packageJsonContent && JSON.parse(packageJsonContent).prettier; - } catch { - logger.warn('Invalid JSON found in package.json'); + if (!prettierExists) { + try { + const packageJsonContent = await readLocalFile('package.json', 'utf8'); + prettierExists ||= + packageJsonContent && JSON.parse(packageJsonContent).prettier; + } catch { + logger.warn('Invalid JSON found in package.json'); + } } if (!prettierExists) { From e488ec7a6e008111eae888592f88ef28843cc846 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 11 Jul 2022 14:22:59 +0530 Subject: [PATCH 18/23] add ident to prettier options --- .../repository/config-migration/branch/migrated-data.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index bb4b4efde33486..7f4f88ec9cf098 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -13,7 +13,8 @@ export interface MigratedData { } export async function applyPrettierFormatting( - content: string + content: string, + indent: string ): Promise { const prettierConfigFilenames = [ '.prettierrc', @@ -46,6 +47,7 @@ export async function applyPrettierFormatting( return prettier.format(content, { parser: 'json', + tabWidth: indent.length, }); } @@ -100,7 +102,7 @@ export class MigratedDataFactory { content = JSON.stringify(migratedConfig, undefined, indent); } - content = await applyPrettierFormatting(content); + content = await applyPrettierFormatting(content, indent); if (!content.endsWith('\n')) { content += '\n'; } From ca8482d57aa2af2256c2e9142ed982511da4669d Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 11 Jul 2022 16:11:51 +0530 Subject: [PATCH 19/23] update options --- .editorconfig | 2 +- .../branch/migrated-data.spec.ts | 241 +++++++++--------- .../config-migration/branch/migrated-data.ts | 215 ++++++++-------- 3 files changed, 231 insertions(+), 227 deletions(-) diff --git a/.editorconfig b/.editorconfig index 7d2edde437ad4e..e95038fbad624a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,7 +3,7 @@ root = true [*] indent_style = space -indent_size = 2 +indent_size = 0 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true 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 52cce13a08eb30..99bfd893915a29 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts @@ -20,131 +20,124 @@ const migratedData = Fixtures.getJson('./migrated-data.json'); const migratedDataJson5 = Fixtures.getJson('./migrated-data.json5'); const migratedConfigObj = Fixtures.getJson('./migrated.json'); const formattedMigratedData = Fixtures.getJson( - './migrated-data-formatted.json' +'./migrated-data-formatted.json' ); describe('workers/repository/config-migration/branch/migrated-data', () => { - describe('MigratedDataFactory.getAsync', () => { - beforeEach(() => { - jest.resetAllMocks(); - mockedFunction(detectIndent).mockReturnValue({ - type: 'space', - amount: 2, - indent: ' ', - }); - mockedFunction(detectRepoFileConfig).mockResolvedValue({ - configFileName: 'renovate.json', - }); - mockedFunction(readLocalFile).mockResolvedValue(rawNonMigrated); - mockedFunction(migrateConfig).mockReturnValue({ - isMigrated: true, - migratedConfig: migratedConfigObj, - }); - mockedFunction(getFileList).mockResolvedValue([]); - }); - - it('Calls getAsync a first when migration not needed', async () => { - mockedFunction(migrateConfig).mockReturnValueOnce({ - isMigrated: false, - migratedConfig: {}, - }); - await expect(MigratedDataFactory.getAsync()).resolves.toBeNull(); - }); - - it('Calls getAsync a first time to initialize the factory', async () => { - await expect(MigratedDataFactory.getAsync()).resolves.toEqual( - migratedData - ); - expect(detectRepoFileConfig).toHaveBeenCalledTimes(1); - }); - - it('Calls getAsync a second time to get the saved data from before', async () => { - await expect(MigratedDataFactory.getAsync()).resolves.toEqual( - migratedData - ); - expect(detectRepoFileConfig).toHaveBeenCalledTimes(0); - }); - - describe('MigratedData class', () => { - it('gets the filename from the class instance', async () => { - const data = await MigratedDataFactory.getAsync(); - expect(data?.filename).toBe('renovate.json'); - }); - - it('gets the content from the class instance', async () => { - const data = await MigratedDataFactory.getAsync(); - expect(data?.content).toBe(migratedData.content); - }); - }); - - it('Resets the factory and gets a new value', async () => { - MigratedDataFactory.reset(); - await expect(MigratedDataFactory.getAsync()).resolves.toEqual( - migratedData - ); - }); - - it('Resets the factory and gets a new value with default indentation', async () => { - mockedFunction(detectIndent).mockReturnValueOnce({ - type: undefined, - amount: 0, - // TODO: incompatible types (#7154) - indent: null as never, - }); - MigratedDataFactory.reset(); - await expect(MigratedDataFactory.getAsync()).resolves.toEqual( - migratedData - ); - }); - - it('Migrate a JSON5 config file', async () => { - mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ - configFileName: 'renovate.json5', - }); - 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); - MigratedDataFactory.reset(); - await expect(MigratedDataFactory.getAsync()).resolves.toBeNull(); - }); - - 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( - formattedMigratedData - ); - }); - - it('should not stop run for invalid package.json', async () => { - mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ - configFileName: 'renovate.json', - }); - mockedFunction(readLocalFile).mockResolvedValueOnce(rawNonMigrated); - mockedFunction(readLocalFile).mockResolvedValue('abci'); - MigratedDataFactory.reset(); - await expect(MigratedDataFactory.getAsync()).resolves.toEqual( - migratedData - ); - }); - - it('return original content if its invalid', async () => { - await expect(applyPrettierFormatting(`{"name":"Rahul"`)).resolves.toBe( - `{"name":"Rahul"` - ); - }); - }); +describe('MigratedDataFactory.getAsync', () => { +beforeEach(() => { +jest.resetAllMocks(); +mockedFunction(detectIndent).mockReturnValue({ +type: 'space', +amount: 2, +indent: ' ', +}); +mockedFunction(detectRepoFileConfig).mockResolvedValue({ +configFileName: 'renovate.json', +}); +mockedFunction(readLocalFile).mockResolvedValue(rawNonMigrated); +mockedFunction(migrateConfig).mockReturnValue({ +isMigrated: true, +migratedConfig: migratedConfigObj, +}); +mockedFunction(getFileList).mockResolvedValue([]); +}); + +it('Calls getAsync a first when migration not needed', async () => { +mockedFunction(migrateConfig).mockReturnValueOnce({ +isMigrated: false, +migratedConfig: {}, +}); +await expect(MigratedDataFactory.getAsync()).resolves.toBeNull(); +}); + +it('Calls getAsync a first time to initialize the factory', async () => { +await expect(MigratedDataFactory.getAsync()).resolves.toEqual(migratedData); +expect(detectRepoFileConfig).toHaveBeenCalledTimes(1); +}); + +it('Calls getAsync a second time to get the saved data from before', async () => { +await expect(MigratedDataFactory.getAsync()).resolves.toEqual(migratedData); +expect(detectRepoFileConfig).toHaveBeenCalledTimes(0); +}); + +describe('MigratedData class', () => { +it('gets the filename from the class instance', async () => { +const data = await MigratedDataFactory.getAsync(); +expect(data?.filename).toBe('renovate.json'); +}); + +it('gets the content from the class instance', async () => { +const data = await MigratedDataFactory.getAsync(); +expect(data?.content).toBe(migratedData.content); +}); +}); + +it('Resets the factory and gets a new value', async () => { +MigratedDataFactory.reset(); +await expect(MigratedDataFactory.getAsync()).resolves.toEqual(migratedData); +}); + +it('Resets the factory and gets a new value with default indentation', async () => { +mockedFunction(detectIndent).mockReturnValueOnce({ +type: undefined, +amount: 0, +// TODO: incompatible types (#7154) +indent: null as never, +}); +MigratedDataFactory.reset(); +await expect(MigratedDataFactory.getAsync()).resolves.toEqual(migratedData); +}); + +it('Migrate a JSON5 config file', async () => { +mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ +configFileName: 'renovate.json5', +}); +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); +MigratedDataFactory.reset(); +await expect(MigratedDataFactory.getAsync()).resolves.toBeNull(); +}); + +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( +formattedMigratedData +); +}); + +it('should not stop run for invalid package.json', async () => { +mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ +configFileName: 'renovate.json', +}); +mockedFunction(readLocalFile).mockResolvedValueOnce(rawNonMigrated); +mockedFunction(readLocalFile).mockResolvedValue('abci'); +MigratedDataFactory.reset(); +await expect(MigratedDataFactory.getAsync()).resolves.toEqual(migratedData); +}); + +it('return original content if its invalid', async () => { +await expect( +applyPrettierFormatting(`{"name":"Rahul"`, 'json', { +indent: ' ', +amount: 2, +}) +).resolves.toBe(`{"name":"Rahul"`); +}); +}); }); diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index 7f4f88ec9cf098..03c788fd7638e1 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -8,112 +8,123 @@ import { getFileList } from '../../../../util/git'; import { detectRepoFileConfig } from '../../init/merge'; export interface MigratedData { - content: string; - filename: string; +content: string; +filename: string; +} +interface Indent { +amount: number; +indent: string; +type?: string; } - export async function applyPrettierFormatting( - content: string, - indent: string +content: string, +parser: string, +indent: Indent ): Promise { - const prettierConfigFilenames = [ - '.prettierrc', - '.prettierrc.json', - '.prettierrc.yml', - '.prettierrc.yaml', - '.prettierrc.json5', - '.prettierrc.js', - '.prettierrc.cjs', - 'prettier.config.js', - 'prettier.config.cjs', - '.prettierrc.toml', - ]; - let prettierExists = (await getFileList()).some((file) => - prettierConfigFilenames.includes(file) - ); - if (!prettierExists) { - try { - const packageJsonContent = await readLocalFile('package.json', 'utf8'); - prettierExists ||= - packageJsonContent && JSON.parse(packageJsonContent).prettier; - } catch { - logger.warn('Invalid JSON found in package.json'); - } - } - - if (!prettierExists) { - return content; - } - - return prettier.format(content, { - parser: 'json', - tabWidth: indent.length, - }); +const prettierConfigFilenames = [ +'.prettierrc', +'.prettierrc.json', +'.prettierrc.yml', +'.prettierrc.yaml', +'.prettierrc.json5', +'.prettierrc.js', +'.prettierrc.cjs', +'prettier.config.js', +'prettier.config.cjs', +'.prettierrc.toml', +]; +let prettierExists = (await getFileList()).some((file) => +prettierConfigFilenames.includes(file) +); +if (!prettierExists) { +try { +const packageJsonContent = await readLocalFile('package.json', 'utf8'); +prettierExists ||= +packageJsonContent && JSON.parse(packageJsonContent).prettier; +} catch { +logger.warn('Invalid JSON found in package.json'); +} +} + +if (!prettierExists) { +return content; +} +const options = { +parser: parser, +tabWidth: indent.amount, +useTabs: indent.type === 'tab', +}; + +return prettier.format(content, options); } export class MigratedDataFactory { - // singleton - private static data: MigratedData | null; - - public static async getAsync(): Promise { - if (this.data) { - return this.data; - } - const migrated = await this.build(); - - if (!migrated) { - return null; - } - - this.data = migrated; - return this.data; - } - - public static reset(): void { - this.data = null; - } - - private static async build(): Promise { - let res: MigratedData | null = null; - try { - const rc = await detectRepoFileConfig(); - const configFileParsed = rc?.configFileParsed || {}; - - // get migrated config - const { isMigrated, migratedConfig } = migrateConfig(configFileParsed); - if (!isMigrated) { - return null; - } - - 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!).indent ?? ' '; - let content: string; - - if (filename.endsWith('.json5')) { - content = JSON5.stringify(migratedConfig, undefined, indent); - } else { - content = JSON.stringify(migratedConfig, undefined, indent); - } - - content = await applyPrettierFormatting(content, indent); - if (!content.endsWith('\n')) { - content += '\n'; - } - - res = { content, filename }; - } catch (err) { - logger.debug( - { err }, - 'MigratedDataFactory.getAsync() Error initializing renovate MigratedData' - ); - } - return res; - } +// singleton +private static data: MigratedData | null; + +public static async getAsync(): Promise { +if (this.data) { +return this.data; +} +const migrated = await this.build(); + +if (!migrated) { +return null; +} + +this.data = migrated; +return this.data; +} + +public static reset(): void { +this.data = null; +} + +private static async build(): Promise { +let res: MigratedData | null = null; +try { +const rc = await detectRepoFileConfig(); +const configFileParsed = rc?.configFileParsed || {}; + +// get migrated config +const { isMigrated, migratedConfig } = migrateConfig(configFileParsed); +if (!isMigrated) { +return null; +} + +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!); +let content: string; + +if (filename.endsWith('.json5')) { +content = JSON5.stringify(migratedConfig, undefined, indent.indent ?? ' '); +} else { +content = JSON.stringify(migratedConfig, undefined, indent.indent ?? ' '); +} + +content = await applyPrettierFormatting( +content, +filename.endsWith('.json5') ? 'json5' : 'json', +indent +); +if (!content.endsWith('\n')) { +content += '\n'; +} + +res = { content, filename }; +} catch (err) { +logger.debug( +{ err }, +'MigratedDataFactory.getAsync() Error initializing renovate MigratedData' +); +} +return res; +} } From 1bcbb66d131f5cb0f91463f34192c0c2738ebed6 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 11 Jul 2022 16:19:59 +0530 Subject: [PATCH 20/23] Update .editorconfig --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index e95038fbad624a..7d2edde437ad4e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,7 +3,7 @@ root = true [*] indent_style = space -indent_size = 0 +indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true From 3b04d5be10d289ef33b7ac7f4aa6f10fb0fd35e8 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 11 Jul 2022 16:23:42 +0530 Subject: [PATCH 21/23] revert format-change --- .editorconfig | 2 +- .../branch/migrated-data.spec.ts | 244 +++++++++--------- .../config-migration/branch/migrated-data.ts | 230 +++++++++-------- 3 files changed, 247 insertions(+), 229 deletions(-) diff --git a/.editorconfig b/.editorconfig index e95038fbad624a..7d2edde437ad4e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,7 +3,7 @@ root = true [*] indent_style = space -indent_size = 0 +indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true 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 99bfd893915a29..49978519f210aa 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts @@ -20,124 +20,134 @@ const migratedData = Fixtures.getJson('./migrated-data.json'); const migratedDataJson5 = Fixtures.getJson('./migrated-data.json5'); const migratedConfigObj = Fixtures.getJson('./migrated.json'); const formattedMigratedData = Fixtures.getJson( -'./migrated-data-formatted.json' + './migrated-data-formatted.json' ); describe('workers/repository/config-migration/branch/migrated-data', () => { -describe('MigratedDataFactory.getAsync', () => { -beforeEach(() => { -jest.resetAllMocks(); -mockedFunction(detectIndent).mockReturnValue({ -type: 'space', -amount: 2, -indent: ' ', -}); -mockedFunction(detectRepoFileConfig).mockResolvedValue({ -configFileName: 'renovate.json', -}); -mockedFunction(readLocalFile).mockResolvedValue(rawNonMigrated); -mockedFunction(migrateConfig).mockReturnValue({ -isMigrated: true, -migratedConfig: migratedConfigObj, -}); -mockedFunction(getFileList).mockResolvedValue([]); -}); - -it('Calls getAsync a first when migration not needed', async () => { -mockedFunction(migrateConfig).mockReturnValueOnce({ -isMigrated: false, -migratedConfig: {}, -}); -await expect(MigratedDataFactory.getAsync()).resolves.toBeNull(); -}); - -it('Calls getAsync a first time to initialize the factory', async () => { -await expect(MigratedDataFactory.getAsync()).resolves.toEqual(migratedData); -expect(detectRepoFileConfig).toHaveBeenCalledTimes(1); -}); - -it('Calls getAsync a second time to get the saved data from before', async () => { -await expect(MigratedDataFactory.getAsync()).resolves.toEqual(migratedData); -expect(detectRepoFileConfig).toHaveBeenCalledTimes(0); -}); - -describe('MigratedData class', () => { -it('gets the filename from the class instance', async () => { -const data = await MigratedDataFactory.getAsync(); -expect(data?.filename).toBe('renovate.json'); -}); - -it('gets the content from the class instance', async () => { -const data = await MigratedDataFactory.getAsync(); -expect(data?.content).toBe(migratedData.content); -}); -}); - -it('Resets the factory and gets a new value', async () => { -MigratedDataFactory.reset(); -await expect(MigratedDataFactory.getAsync()).resolves.toEqual(migratedData); -}); - -it('Resets the factory and gets a new value with default indentation', async () => { -mockedFunction(detectIndent).mockReturnValueOnce({ -type: undefined, -amount: 0, -// TODO: incompatible types (#7154) -indent: null as never, -}); -MigratedDataFactory.reset(); -await expect(MigratedDataFactory.getAsync()).resolves.toEqual(migratedData); -}); - -it('Migrate a JSON5 config file', async () => { -mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ -configFileName: 'renovate.json5', -}); -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); -MigratedDataFactory.reset(); -await expect(MigratedDataFactory.getAsync()).resolves.toBeNull(); -}); - -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( -formattedMigratedData -); -}); - -it('should not stop run for invalid package.json', async () => { -mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ -configFileName: 'renovate.json', -}); -mockedFunction(readLocalFile).mockResolvedValueOnce(rawNonMigrated); -mockedFunction(readLocalFile).mockResolvedValue('abci'); -MigratedDataFactory.reset(); -await expect(MigratedDataFactory.getAsync()).resolves.toEqual(migratedData); -}); - -it('return original content if its invalid', async () => { -await expect( -applyPrettierFormatting(`{"name":"Rahul"`, 'json', { -indent: ' ', -amount: 2, -}) -).resolves.toBe(`{"name":"Rahul"`); -}); -}); + describe('MigratedDataFactory.getAsync', () => { + beforeEach(() => { + jest.resetAllMocks(); + mockedFunction(detectIndent).mockReturnValue({ + type: 'space', + amount: 2, + indent: ' ', + }); + mockedFunction(detectRepoFileConfig).mockResolvedValue({ + configFileName: 'renovate.json', + }); + mockedFunction(readLocalFile).mockResolvedValue(rawNonMigrated); + mockedFunction(migrateConfig).mockReturnValue({ + isMigrated: true, + migratedConfig: migratedConfigObj, + }); + mockedFunction(getFileList).mockResolvedValue([]); + }); + + it('Calls getAsync a first when migration not needed', async () => { + mockedFunction(migrateConfig).mockReturnValueOnce({ + isMigrated: false, + migratedConfig: {}, + }); + await expect(MigratedDataFactory.getAsync()).resolves.toBeNull(); + }); + + it('Calls getAsync a first time to initialize the factory', async () => { + await expect(MigratedDataFactory.getAsync()).resolves.toEqual( + migratedData + ); + expect(detectRepoFileConfig).toHaveBeenCalledTimes(1); + }); + + it('Calls getAsync a second time to get the saved data from before', async () => { + await expect(MigratedDataFactory.getAsync()).resolves.toEqual( + migratedData + ); + expect(detectRepoFileConfig).toHaveBeenCalledTimes(0); + }); + + describe('MigratedData class', () => { + it('gets the filename from the class instance', async () => { + const data = await MigratedDataFactory.getAsync(); + expect(data?.filename).toBe('renovate.json'); + }); + + it('gets the content from the class instance', async () => { + const data = await MigratedDataFactory.getAsync(); + expect(data?.content).toBe(migratedData.content); + }); + }); + + it('Resets the factory and gets a new value', async () => { + MigratedDataFactory.reset(); + await expect(MigratedDataFactory.getAsync()).resolves.toEqual( + migratedData + ); + }); + + it('Resets the factory and gets a new value with default indentation', async () => { + mockedFunction(detectIndent).mockReturnValueOnce({ + type: undefined, + amount: 0, + // TODO: incompatible types (#7154) + indent: null as never, + }); + MigratedDataFactory.reset(); + await expect(MigratedDataFactory.getAsync()).resolves.toEqual( + migratedData + ); + }); + + it('Migrate a JSON5 config file', async () => { + mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ + configFileName: 'renovate.json5', + }); + 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); + MigratedDataFactory.reset(); + await expect(MigratedDataFactory.getAsync()).resolves.toBeNull(); + }); + + 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( + formattedMigratedData + ); + }); + + it('should not stop run for invalid package.json', async () => { + mockedFunction(detectRepoFileConfig).mockResolvedValueOnce({ + configFileName: 'renovate.json', + }); + mockedFunction(readLocalFile).mockResolvedValueOnce(rawNonMigrated); + mockedFunction(readLocalFile).mockResolvedValue('abci'); + MigratedDataFactory.reset(); + await expect(MigratedDataFactory.getAsync()).resolves.toEqual( + migratedData + ); + }); + + it('return original content if its invalid', async () => { + await expect( + applyPrettierFormatting(`{"name":"Rahul"`, 'json', { + indent: ' ', + amount: 2, + }) + ).resolves.toBe(`{"name":"Rahul"`); + }); + }); }); diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index 03c788fd7638e1..fa2002e378c30b 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -8,123 +8,131 @@ import { getFileList } from '../../../../util/git'; import { detectRepoFileConfig } from '../../init/merge'; export interface MigratedData { -content: string; -filename: string; + content: string; + filename: string; } interface Indent { -amount: number; -indent: string; -type?: string; + amount: number; + indent: string; + type?: string; } export async function applyPrettierFormatting( -content: string, -parser: string, -indent: Indent + content: string, + parser: string, + indent: Indent ): Promise { -const prettierConfigFilenames = [ -'.prettierrc', -'.prettierrc.json', -'.prettierrc.yml', -'.prettierrc.yaml', -'.prettierrc.json5', -'.prettierrc.js', -'.prettierrc.cjs', -'prettier.config.js', -'prettier.config.cjs', -'.prettierrc.toml', -]; -let prettierExists = (await getFileList()).some((file) => -prettierConfigFilenames.includes(file) -); -if (!prettierExists) { -try { -const packageJsonContent = await readLocalFile('package.json', 'utf8'); -prettierExists ||= -packageJsonContent && JSON.parse(packageJsonContent).prettier; -} catch { -logger.warn('Invalid JSON found in package.json'); -} -} - -if (!prettierExists) { -return content; -} -const options = { -parser: parser, -tabWidth: indent.amount, -useTabs: indent.type === 'tab', -}; - -return prettier.format(content, options); + const prettierConfigFilenames = [ + '.prettierrc', + '.prettierrc.json', + '.prettierrc.yml', + '.prettierrc.yaml', + '.prettierrc.json5', + '.prettierrc.js', + '.prettierrc.cjs', + 'prettier.config.js', + 'prettier.config.cjs', + '.prettierrc.toml', + ]; + let prettierExists = (await getFileList()).some((file) => + prettierConfigFilenames.includes(file) + ); + if (!prettierExists) { + try { + const packageJsonContent = await readLocalFile('package.json', 'utf8'); + prettierExists ||= + packageJsonContent && JSON.parse(packageJsonContent).prettier; + } catch { + logger.warn('Invalid JSON found in package.json'); + } + } + + if (!prettierExists) { + return content; + } + const options = { + parser: parser, + tabWidth: indent.amount, + useTabs: indent.type === 'tab', + }; + + return prettier.format(content, options); } export class MigratedDataFactory { -// singleton -private static data: MigratedData | null; - -public static async getAsync(): Promise { -if (this.data) { -return this.data; -} -const migrated = await this.build(); - -if (!migrated) { -return null; -} - -this.data = migrated; -return this.data; -} - -public static reset(): void { -this.data = null; -} - -private static async build(): Promise { -let res: MigratedData | null = null; -try { -const rc = await detectRepoFileConfig(); -const configFileParsed = rc?.configFileParsed || {}; - -// get migrated config -const { isMigrated, migratedConfig } = migrateConfig(configFileParsed); -if (!isMigrated) { -return null; -} - -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!); -let content: string; - -if (filename.endsWith('.json5')) { -content = JSON5.stringify(migratedConfig, undefined, indent.indent ?? ' '); -} else { -content = JSON.stringify(migratedConfig, undefined, indent.indent ?? ' '); -} - -content = await applyPrettierFormatting( -content, -filename.endsWith('.json5') ? 'json5' : 'json', -indent -); -if (!content.endsWith('\n')) { -content += '\n'; -} - -res = { content, filename }; -} catch (err) { -logger.debug( -{ err }, -'MigratedDataFactory.getAsync() Error initializing renovate MigratedData' -); -} -return res; -} + // singleton + private static data: MigratedData | null; + + public static async getAsync(): Promise { + if (this.data) { + return this.data; + } + const migrated = await this.build(); + + if (!migrated) { + return null; + } + + this.data = migrated; + return this.data; + } + + public static reset(): void { + this.data = null; + } + + private static async build(): Promise { + let res: MigratedData | null = null; + try { + const rc = await detectRepoFileConfig(); + const configFileParsed = rc?.configFileParsed || {}; + + // get migrated config + const { isMigrated, migratedConfig } = migrateConfig(configFileParsed); + if (!isMigrated) { + return null; + } + + 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!); + let content: string; + + if (filename.endsWith('.json5')) { + content = JSON5.stringify( + migratedConfig, + undefined, + indent.indent ?? ' ' + ); + } else { + content = JSON.stringify( + migratedConfig, + undefined, + indent.indent ?? ' ' + ); + } + + content = await applyPrettierFormatting( + content, + filename.endsWith('.json5') ? 'json5' : 'json', + indent + ); + if (!content.endsWith('\n')) { + content += '\n'; + } + + res = { content, filename }; + } catch (err) { + logger.debug( + { err }, + 'MigratedDataFactory.getAsync() Error initializing renovate MigratedData' + ); + } + return res; + } } From 393d21df1eca282afec9d12cc6bfb53dcc2bd069 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Wed, 13 Jul 2022 07:08:05 +0530 Subject: [PATCH 22/23] refactor: apply suggestions --- .../config-migration/branch/migrated-data.ts | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index fa2002e378c30b..926a0593e1c49f 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -16,30 +16,33 @@ interface Indent { indent: string; type?: string; } + +const prettierConfigFilenames = new Set([ + '.prettierrc', + '.prettierrc.json', + '.prettierrc.yml', + '.prettierrc.yaml', + '.prettierrc.json5', + '.prettierrc.js', + '.prettierrc.cjs', + 'prettier.config.js', + 'prettier.config.cjs', + '.prettierrc.toml', +]); + export async function applyPrettierFormatting( content: string, parser: string, indent: Indent ): Promise { - const prettierConfigFilenames = [ - '.prettierrc', - '.prettierrc.json', - '.prettierrc.yml', - '.prettierrc.yaml', - '.prettierrc.json5', - '.prettierrc.js', - '.prettierrc.cjs', - 'prettier.config.js', - 'prettier.config.cjs', - '.prettierrc.toml', - ]; - let prettierExists = (await getFileList()).some((file) => - prettierConfigFilenames.includes(file) + const fileList = await getFileList(); + let prettierExists = fileList.some((file) => + prettierConfigFilenames.has(file) ); if (!prettierExists) { try { const packageJsonContent = await readLocalFile('package.json', 'utf8'); - prettierExists ||= + prettierExists = packageJsonContent && JSON.parse(packageJsonContent).prettier; } catch { logger.warn('Invalid JSON found in package.json'); @@ -50,8 +53,8 @@ export async function applyPrettierFormatting( return content; } const options = { - parser: parser, - tabWidth: indent.amount, + parser, + tabWidth: indent.amount === 0 ? 2 : indent.amount, useTabs: indent.type === 'tab', }; @@ -101,20 +104,13 @@ export class MigratedDataFactory { // indent defaults to 2 spaces // TODO #7154 const indent = detectIndent(raw!); + const indentSpace = indent.indent ?? ' '; let content: string; if (filename.endsWith('.json5')) { - content = JSON5.stringify( - migratedConfig, - undefined, - indent.indent ?? ' ' - ); + content = JSON5.stringify(migratedConfig, undefined, indentSpace); } else { - content = JSON.stringify( - migratedConfig, - undefined, - indent.indent ?? ' ' - ); + content = JSON.stringify(migratedConfig, undefined, indentSpace); } content = await applyPrettierFormatting( From 37e734123c442d473de108ff7a85b32204aa9965 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Wed, 13 Jul 2022 09:57:37 +0530 Subject: [PATCH 23/23] add comment --- lib/workers/repository/config-migration/branch/migrated-data.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index 926a0593e1c49f..da22bb5f4b0daf 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -113,6 +113,7 @@ export class MigratedDataFactory { content = JSON.stringify(migratedConfig, undefined, indentSpace); } + // format if prettier is found in the user's repo content = await applyPrettierFormatting( content, filename.endsWith('.json5') ? 'json5' : 'json',