fix(core): format global config files modified by nx migrate (#27066)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #8928
This commit is contained in:
Leosvel Pérez Espinosa 2024-07-25 15:22:18 +02:00 committed by GitHub
parent 9fe9c291c8
commit e9d9c9fde9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 61 additions and 14 deletions

View File

@ -28,6 +28,7 @@ import {
extractFileFromTarball, extractFileFromTarball,
fileExists, fileExists,
JsonReadOptions, JsonReadOptions,
JsonWriteOptions,
readJsonFile, readJsonFile,
writeJsonFile, writeJsonFile,
} from '../../utils/fileutils'; } from '../../utils/fileutils';
@ -54,7 +55,7 @@ import {
onlyDefaultRunnerIsUsed, onlyDefaultRunnerIsUsed,
} from '../connect/connect-to-nx-cloud'; } from '../connect/connect-to-nx-cloud';
import { output } from '../../utils/output'; import { output } from '../../utils/output';
import { existsSync, readFileSync } from 'fs'; import { existsSync, readFileSync, writeFileSync } from 'fs';
import { workspaceRoot } from '../../utils/workspace-root'; import { workspaceRoot } from '../../utils/workspace-root';
import { isCI } from '../../utils/is-ci'; import { isCI } from '../../utils/is-ci';
import { getNxRequirePaths } from '../../utils/installation-directory'; import { getNxRequirePaths } from '../../utils/installation-directory';
@ -66,6 +67,7 @@ import {
createProjectGraphAsync, createProjectGraphAsync,
readProjectsConfigurationFromProjectGraph, readProjectsConfigurationFromProjectGraph,
} from '../../project-graph/project-graph'; } from '../../project-graph/project-graph';
import { formatFilesWithPrettierIfAvailable } from '../../generators/internal-utils/format-changed-files-with-prettier-if-available';
export interface ResolvedMigrationConfiguration extends MigrationsJson { export interface ResolvedMigrationConfiguration extends MigrationsJson {
packageGroup?: ArrayPackageGroup; packageGroup?: ArrayPackageGroup;
@ -1105,17 +1107,17 @@ function readPackageMigrationConfig(
} }
} }
function createMigrationsFile( async function createMigrationsFile(
root: string, root: string,
migrations: { migrations: {
package: string; package: string;
name: string; name: string;
}[] }[]
) { ) {
writeJsonFile(join(root, 'migrations.json'), { migrations }); await writeFormattedJsonFile(join(root, 'migrations.json'), { migrations });
} }
function updatePackageJson( async function updatePackageJson(
root: string, root: string,
updatedPackages: Record<string, PackageUpdate> updatedPackages: Record<string, PackageUpdate>
) { ) {
@ -1145,7 +1147,7 @@ function updatePackageJson(
} }
}); });
writeJsonFile(packageJsonPath, json, { await writeFormattedJsonFile(packageJsonPath, json, {
appendNewLine: parseOptions.endsWithNewline, appendNewLine: parseOptions.endsWithNewline,
}); });
} }
@ -1178,7 +1180,7 @@ async function updateInstallationDetails(
} }
} }
writeJsonFile(nxJsonPath, nxJson, { await writeFormattedJsonFile(nxJsonPath, nxJson, {
appendNewLine: parseOptions.endsWithNewline, appendNewLine: parseOptions.endsWithNewline,
}); });
} }
@ -1238,11 +1240,11 @@ async function generateMigrationsJsonAndUpdatePackageJson(
const { migrations, packageUpdates, minVersionWithSkippedUpdates } = const { migrations, packageUpdates, minVersionWithSkippedUpdates } =
await migrator.migrate(opts.targetPackage, opts.targetVersion); await migrator.migrate(opts.targetPackage, opts.targetVersion);
updatePackageJson(root, packageUpdates); await updatePackageJson(root, packageUpdates);
await updateInstallationDetails(root, packageUpdates); await updateInstallationDetails(root, packageUpdates);
if (migrations.length > 0) { if (migrations.length > 0) {
createMigrationsFile(root, [ await createMigrationsFile(root, [
...addSplitConfigurationMigrationIfAvailable(from, packageUpdates), ...addSplitConfigurationMigrationIfAvailable(from, packageUpdates),
...migrations, ...migrations,
] as any); ] as any);
@ -1318,6 +1320,26 @@ async function generateMigrationsJsonAndUpdatePackageJson(
} }
} }
async function writeFormattedJsonFile(
filePath: string,
content: any,
options?: JsonWriteOptions
): Promise<void> {
const formattedContent = await formatFilesWithPrettierIfAvailable(
[{ path: filePath, content: JSON.stringify(content) }],
workspaceRoot,
{ silent: true }
);
if (formattedContent.has(filePath)) {
writeFileSync(filePath, formattedContent.get(filePath)!, {
encoding: 'utf-8',
});
} else {
writeJsonFile(filePath, content, options);
}
}
function addSplitConfigurationMigrationIfAvailable( function addSplitConfigurationMigrationIfAvailable(
from: string, from: string,
packageJson: any packageJson: any

View File

@ -12,20 +12,43 @@ export async function formatChangedFilesWithPrettierIfAvailable(
silent?: boolean; silent?: boolean;
} }
): Promise<void> { ): Promise<void> {
const files = new Set(
tree.listChanges().filter((file) => file.type !== 'DELETE')
);
const results = await formatFilesWithPrettierIfAvailable(
Array.from(files),
tree.root,
options
);
for (const [path, content] of results) {
tree.write(path, content);
}
}
export async function formatFilesWithPrettierIfAvailable(
files: { path: string; content: string | Buffer }[],
root: string,
options?: {
silent?: boolean;
}
): Promise<Map<string, string>> {
const results = new Map<string, string>();
let prettier: typeof Prettier; let prettier: typeof Prettier;
try { try {
prettier = await import('prettier'); prettier = await import('prettier');
} catch {} } catch {}
if (!prettier) return; if (!prettier) {
return results;
}
const files = new Set(
tree.listChanges().filter((file) => file.type !== 'DELETE')
);
await Promise.all( await Promise.all(
Array.from(files).map(async (file) => { Array.from(files).map(async (file) => {
try { try {
const systemPath = path.join(tree.root, file.path); const systemPath = path.join(root, file.path);
let options: any = { let options: any = {
filepath: systemPath, filepath: systemPath,
}; };
@ -46,7 +69,7 @@ export async function formatChangedFilesWithPrettierIfAvailable(
return; return;
} }
tree.write( results.set(
file.path, file.path,
// In prettier v3 the format result is a promise // In prettier v3 the format result is a promise
await (prettier.format(file.content.toString('utf-8'), options) as await (prettier.format(file.content.toString('utf-8'), options) as
@ -60,4 +83,6 @@ export async function formatChangedFilesWithPrettierIfAvailable(
} }
}) })
); );
return results;
} }