From b33269dd30d2c49f0a50d92316b6338029145201 Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Fri, 7 Oct 2022 10:56:35 +0200 Subject: [PATCH 1/4] fix: version-bump generator removes beachball disallowedChangeType config for nightly releases Fixes #25116 --- tools/generators/version-bump/index.spec.ts | 24 +++++++++++++++++++++ tools/generators/version-bump/index.ts | 5 +++++ tools/types.ts | 3 +++ 3 files changed, 32 insertions(+) diff --git a/tools/generators/version-bump/index.spec.ts b/tools/generators/version-bump/index.spec.ts index 3e922edd94f4b5..416ab1e63df0aa 100644 --- a/tools/generators/version-bump/index.spec.ts +++ b/tools/generators/version-bump/index.spec.ts @@ -10,6 +10,7 @@ import { import generator from './index'; import { VersionBumpGeneratorSchema } from './schema'; +import { PackageJson } from '../../types'; const noop = () => null; @@ -134,6 +135,27 @@ describe('version-string-replace generator', () => { expect(packageJson.version).toMatchInlineSnapshot(`"0.0.0-nightly.0"`); }); + it('should remove beachball disallowedChangeType config when bumping nightly', async () => { + tree = setupDummyPackage(tree, { + name: '@proj/make-styles', + version: '9.0.0-alpha.0', + projectConfiguration: { tags: ['vNext', 'platform:web'], sourceRoot: 'packages/make-styles/src' }, + beachball: { + disallowedChangeTypes: ['prerelease'], + }, + }); + + expect(readJson(tree, 'packages/make-styles/package.json').beachball?.disallowedChangeTypes).toEqual([ + 'prerelease', + ]); + + await generator(tree, { name: '@proj/make-styles', bumpType: 'nightly', prereleaseTag: 'nightly' }); + + const packageJson = readJson(tree, 'packages/make-styles/package.json'); + expect(packageJson.version).toMatchInlineSnapshot(`"0.0.0-nightly.0"`); + expect(packageJson.beachball?.disallowedChangeTypes).toBeUndefined(); + }); + describe('--all', () => { beforeEach(() => { tree = setupDummyPackage(tree, { @@ -252,6 +274,7 @@ function setupDummyPackage( devDependencies: Record; dependencies: Record; projectConfiguration: Partial>; + beachball: PackageJson['beachball']; }>, ) { const workspaceConfig = readWorkspaceConfiguration(tree); @@ -279,6 +302,7 @@ function setupDummyPackage( version: normalizedOptions.version, dependencies: normalizedOptions.dependencies, devDependencies: normalizedOptions.devDependencies, + beachball: options.beachball, }, }; diff --git a/tools/generators/version-bump/index.ts b/tools/generators/version-bump/index.ts index 36b07a625215fd..959f9266211e09 100644 --- a/tools/generators/version-bump/index.ts +++ b/tools/generators/version-bump/index.ts @@ -33,6 +33,11 @@ function runMigrationOnProject(host: Tree, schema: ValidatedSchema, userLog: Use updateJson(host, packageJsonPath, (packageJson: PackageJson) => { nextVersion = bumpVersion(packageJson, schema.bumpType, schema.prereleaseTag); + + // nightly releases should bypass beachball disallowed changetypes + if (schema.bumpType === 'nightly' && packageJson.beachball?.disallowedChangeTypes) { + packageJson.beachball.disallowedChangeTypes = undefined; + } packageJson.version = nextVersion; return packageJson; diff --git a/tools/types.ts b/tools/types.ts index 97f04fb1239211..3a9dc0fe963496 100644 --- a/tools/types.ts +++ b/tools/types.ts @@ -31,6 +31,9 @@ export interface PackageJson { devDependencies?: Record; peerDependencies?: Record; exports?: Record>; + beachball?: { + disallowedChangeTypes?: string[]; + }; } // =============== From afa8c9b16f9b787647940efefb6f790a8edfe41c Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Fri, 7 Oct 2022 11:08:10 +0200 Subject: [PATCH 2/4] update release pipeline to use lage --- azure-pipelines.release-vnext-nightly.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-pipelines.release-vnext-nightly.yml b/azure-pipelines.release-vnext-nightly.yml index cc956a1a801125..cdb35c04387455 100644 --- a/azure-pipelines.release-vnext-nightly.yml +++ b/azure-pipelines.release-vnext-nightly.yml @@ -65,15 +65,15 @@ jobs: # --only makes it only run tests (otherwise due to the missing --production arg, lage would re-run the build) # https://github.com/microsoft/fluentui/issues/21686 - script: | - yarn run:published test + yarn lage test --to @fluentui/react-components displayName: yarn test - script: | - yarn run:published lint + yarn lage lint --to @fluentui/react-components displayName: yarn lint - script: | - yarn run:published build --production + yarn lage build --to @fluentui/react-components displayName: yarn build - script: | From 490718515b962629f0a3d959b8831424da6dcdae Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Fri, 7 Oct 2022 17:02:29 +0200 Subject: [PATCH 3/4] dependents shouldn't use carets for nightly --- tools/generators/version-bump/index.spec.ts | 34 +++++++++++++ tools/generators/version-bump/index.ts | 55 ++++++++++++++------- tools/utils.ts | 6 ++- 3 files changed, 75 insertions(+), 20 deletions(-) diff --git a/tools/generators/version-bump/index.spec.ts b/tools/generators/version-bump/index.spec.ts index 416ab1e63df0aa..50e656545f407f 100644 --- a/tools/generators/version-bump/index.spec.ts +++ b/tools/generators/version-bump/index.spec.ts @@ -129,6 +129,40 @@ describe('version-string-replace generator', () => { projectConfiguration: { tags: ['vNext', 'platform:web'], sourceRoot: 'packages/make-styles/src' }, }); + tree = setupDummyPackage(tree, { + name: '@proj/react-button', + version: '9.0.0-alpha.0', + dependencies: { + '@proj/make-styles': '^9.0.0', + }, + devDependencies: { + '@proj/make-styles': '^9.0.0', + }, + projectConfiguration: { tags: ['vNext', 'platform:web'], sourceRoot: 'packages/react-button/src' }, + }); + + await generator(tree, { name: '@proj/make-styles', bumpType: 'nightly', prereleaseTag: 'nightly' }); + + const packageJson = readJson(tree, 'packages/react-button/package.json'); + expect(packageJson.dependencies).toMatchInlineSnapshot(` + Object { + "@proj/make-styles": "0.0.0-nightly.0", + } + `); + expect(packageJson.devDependencies).toMatchInlineSnapshot(` + Object { + "@proj/make-styles": "0.0.0-nightly.0", + } + `); + }); + + it('should remove carets for dependents when `nightly` is selected as the bump type', async () => { + tree = setupDummyPackage(tree, { + name: '@proj/make-styles', + version: '^9.0.0', + projectConfiguration: { tags: ['vNext', 'platform:web'], sourceRoot: 'packages/make-styles/src' }, + }); + await generator(tree, { name: '@proj/make-styles', bumpType: 'nightly', prereleaseTag: 'nightly' }); const packageJson = readJson(tree, 'packages/make-styles/package.json'); diff --git a/tools/generators/version-bump/index.ts b/tools/generators/version-bump/index.ts index 959f9266211e09..d8bc7577e21b97 100644 --- a/tools/generators/version-bump/index.ts +++ b/tools/generators/version-bump/index.ts @@ -44,26 +44,42 @@ function runMigrationOnProject(host: Tree, schema: ValidatedSchema, userLog: Use }); if (nextVersion) { - updatePackageDependents(host, nextVersion, schema.name, userLog); + updatePackageDependents({ host, nextVersion, userLog, schema }); } } -function updatePackageDependents(host: Tree, nextVersion: string, dependencyName: string, userLog: UserLog) { +function updatePackageDependents(options: { + host: Tree; + nextVersion: string; + userLog: UserLog; + schema: ValidatedSchema; +}) { + const { host, nextVersion, userLog, schema } = options; const projects = getProjects(host); projects.forEach((project, projectName) => { const projectConfig = getProjectConfig(host, { packageName: projectName }); - updatePackageDependent(host, nextVersion, dependencyName, projectConfig.paths.packageJson, userLog); + updatePackageDependent({ + host, + nextVersion, + dependencyName: schema.name, + packageJsonPath: projectConfig.paths.packageJson, + userLog, + bumpType: schema.bumpType, + }); }); } -function updatePackageDependent( - host: Tree, - nextVersion: string, - dependencyName: string, - packageJsonPath: string, - userLog: UserLog, -) { +function updatePackageDependent(options: { + host: Tree; + nextVersion: string; + dependencyName: string; + packageJsonPath: string; + userLog: UserLog; + bumpType: ValidatedSchema['bumpType']; +}) { + const { host, nextVersion, dependencyName, packageJsonPath, userLog, bumpType } = options; + updateJson(host, packageJsonPath, (packageJson: PackageJson) => { if (packageJson.dependencies?.[dependencyName]) { userLog.push({ @@ -71,7 +87,7 @@ function updatePackageDependent( message: `bumping dependency ${dependencyName} in ${packageJsonPath}`, }); - bumpDependency(packageJson.dependencies, dependencyName, nextVersion); + bumpDependency({ dependencies: packageJson.dependencies, dependencyName, version: nextVersion, bumpType }); } if (packageJson.devDependencies?.[dependencyName]) { @@ -79,20 +95,23 @@ function updatePackageDependent( type: 'info', message: `bumping devDependency ${dependencyName} in ${packageJsonPath}`, }); - bumpDependency(packageJson.devDependencies, dependencyName, nextVersion); + bumpDependency({ dependencies: packageJson.devDependencies, dependencyName, version: nextVersion, bumpType }); } return packageJson; }); } -const bumpDependency = ( - dependencies: NonNullable, - dependencyName: string, - version: string, -) => { +const bumpDependency = (options: { + dependencies: NonNullable; + dependencyName: string; + version: string; + bumpType: ValidatedSchema['bumpType']; +}) => { + const { dependencies, dependencyName, version, bumpType } = options; + const hasCaret = dependencies[dependencyName].includes('^'); - const versionToBump = hasCaret ? `^${version}` : version; + const versionToBump = hasCaret && bumpType !== 'nightly' ? `^${version}` : version; dependencies[dependencyName] = versionToBump; }; diff --git a/tools/utils.ts b/tools/utils.ts index 63842dfa0b031b..1676ae09bb96c4 100644 --- a/tools/utils.ts +++ b/tools/utils.ts @@ -186,9 +186,11 @@ export function hasSchemaFlag(schema: T, flag: K): schema } export function isPackageVersionConverged(versionString: string) { - const version = semver.parse(versionString); + const versionWithoutCaret = versionString.replace('^', ''); + + const version = semver.parse(versionWithoutCaret); if (version === null) { - throw new Error(`${versionString} is not a valid semver version`); + throw new Error(`${versionWithoutCaret} is not a valid semver version`); } return version.major === 9; } From 9b5a40b7d52e79aa44ff65016676b67e0748c77a Mon Sep 17 00:00:00 2001 From: Lingfan Gao Date: Fri, 7 Oct 2022 17:05:52 +0200 Subject: [PATCH 4/4] extract beachball config to separate types --- tools/generators/version-bump/index.spec.ts | 12 ++++++------ tools/generators/version-bump/index.ts | 14 ++++++++++++-- tools/types.ts | 3 +++ tools/utils.ts | 6 +++++- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/tools/generators/version-bump/index.spec.ts b/tools/generators/version-bump/index.spec.ts index 50e656545f407f..5a9f1df3161e7d 100644 --- a/tools/generators/version-bump/index.spec.ts +++ b/tools/generators/version-bump/index.spec.ts @@ -10,7 +10,7 @@ import { import generator from './index'; import { VersionBumpGeneratorSchema } from './schema'; -import { PackageJson } from '../../types'; +import { PackageJsonWithBeachball } from '../../types'; const noop = () => null; @@ -179,13 +179,13 @@ describe('version-string-replace generator', () => { }, }); - expect(readJson(tree, 'packages/make-styles/package.json').beachball?.disallowedChangeTypes).toEqual([ - 'prerelease', - ]); + expect( + readJson(tree, 'packages/make-styles/package.json').beachball?.disallowedChangeTypes, + ).toEqual(['prerelease']); await generator(tree, { name: '@proj/make-styles', bumpType: 'nightly', prereleaseTag: 'nightly' }); - const packageJson = readJson(tree, 'packages/make-styles/package.json'); + const packageJson = readJson(tree, 'packages/make-styles/package.json'); expect(packageJson.version).toMatchInlineSnapshot(`"0.0.0-nightly.0"`); expect(packageJson.beachball?.disallowedChangeTypes).toBeUndefined(); }); @@ -308,7 +308,7 @@ function setupDummyPackage( devDependencies: Record; dependencies: Record; projectConfiguration: Partial>; - beachball: PackageJson['beachball']; + beachball: PackageJsonWithBeachball['beachball']; }>, ) { const workspaceConfig = readWorkspaceConfiguration(tree); diff --git a/tools/generators/version-bump/index.ts b/tools/generators/version-bump/index.ts index d8bc7577e21b97..4db70dda58dd03 100644 --- a/tools/generators/version-bump/index.ts +++ b/tools/generators/version-bump/index.ts @@ -1,7 +1,13 @@ import { Tree, updateJson, getProjects, formatFiles, readJson } from '@nrwl/devkit'; import * as semver from 'semver'; import { VersionBumpGeneratorSchema } from './schema'; -import { getProjectConfig, isPackageVersionConverged, printUserLogs, UserLog } from '../../utils'; +import { + getProjectConfig, + isPackageVersionConverged, + packageJsonHasBeachballConfig, + printUserLogs, + UserLog, +} from '../../utils'; import { PackageJson } from '../../types'; export default async function (host: Tree, schema: VersionBumpGeneratorSchema) { @@ -35,7 +41,11 @@ function runMigrationOnProject(host: Tree, schema: ValidatedSchema, userLog: Use nextVersion = bumpVersion(packageJson, schema.bumpType, schema.prereleaseTag); // nightly releases should bypass beachball disallowed changetypes - if (schema.bumpType === 'nightly' && packageJson.beachball?.disallowedChangeTypes) { + if ( + schema.bumpType === 'nightly' && + packageJsonHasBeachballConfig(packageJson) && + packageJson.beachball?.disallowedChangeTypes + ) { packageJson.beachball.disallowedChangeTypes = undefined; } packageJson.version = nextVersion; diff --git a/tools/types.ts b/tools/types.ts index 3a9dc0fe963496..895f33de71f227 100644 --- a/tools/types.ts +++ b/tools/types.ts @@ -31,6 +31,9 @@ export interface PackageJson { devDependencies?: Record; peerDependencies?: Record; exports?: Record>; +} + +export interface PackageJsonWithBeachball extends PackageJson { beachball?: { disallowedChangeTypes?: string[]; }; diff --git a/tools/utils.ts b/tools/utils.ts index 1676ae09bb96c4..0890300ba7b74c 100644 --- a/tools/utils.ts +++ b/tools/utils.ts @@ -10,7 +10,7 @@ import { ProjectConfiguration, readJson, } from '@nrwl/devkit'; -import { PackageJson } from './types'; +import { PackageJson, PackageJsonWithBeachball } from './types'; import * as semver from 'semver'; /** @@ -209,3 +209,7 @@ export function isV8Package(tree: Tree, project: ProjectConfiguration) { const packageJson = readJson(tree, joinPathFragments(project.root, 'package.json')); return packageJson.version.startsWith('8.'); } + +export function packageJsonHasBeachballConfig(packageJson: PackageJson): packageJson is PackageJsonWithBeachball { + return !!(packageJson as PackageJsonWithBeachball).beachball; +}