diff --git a/azure-pipelines.release-vnext-nightly.yml b/azure-pipelines.release-vnext-nightly.yml index cc956a1a80112..cdb35c0438745 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: | diff --git a/tools/generators/version-bump/index.spec.ts b/tools/generators/version-bump/index.spec.ts index 3e922edd94f4b..5a9f1df3161e7 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 { PackageJsonWithBeachball } from '../../types'; const noop = () => null; @@ -128,12 +129,67 @@ 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'); 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 +308,7 @@ function setupDummyPackage( devDependencies: Record; dependencies: Record; projectConfiguration: Partial>; + beachball: PackageJsonWithBeachball['beachball']; }>, ) { const workspaceConfig = readWorkspaceConfiguration(tree); @@ -279,6 +336,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 36b07a625215f..4db70dda58dd0 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) { @@ -33,32 +39,57 @@ 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' && + packageJsonHasBeachballConfig(packageJson) && + packageJson.beachball?.disallowedChangeTypes + ) { + packageJson.beachball.disallowedChangeTypes = undefined; + } packageJson.version = nextVersion; return packageJson; }); 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({ @@ -66,7 +97,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]) { @@ -74,20 +105,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/types.ts b/tools/types.ts index 97f04fb123921..895f33de71f22 100644 --- a/tools/types.ts +++ b/tools/types.ts @@ -33,6 +33,12 @@ export interface PackageJson { exports?: Record>; } +export interface PackageJsonWithBeachball extends PackageJson { + beachball?: { + disallowedChangeTypes?: string[]; + }; +} + // =============== // Type Utilities // =============== diff --git a/tools/utils.ts b/tools/utils.ts index 63842dfa0b031..0890300ba7b74 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'; /** @@ -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; } @@ -207,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; +}