diff --git a/packages/plugin-version/sources/commands/version.ts b/packages/plugin-version/sources/commands/version.ts index 3f4530deb587..ab5b7e1437c9 100644 --- a/packages/plugin-version/sources/commands/version.ts +++ b/packages/plugin-version/sources/commands/version.ts @@ -24,6 +24,9 @@ export default class VersionCommand extends BaseCommand { @Command.Boolean(`-f,--force`) force: boolean = false; + @Command.Boolean(`-a,--all`) + all?: boolean = false + static schema = yup.object().shape({ strategy: yup.string().test({ name: `strategy`, @@ -118,8 +121,26 @@ export default class VersionCommand extends BaseCommand { } } + let workspaces = new Set([workspace]); const versionFile = await versionUtils.openVersionFile(project, {allowEmpty: true}); - await versionFile.releases.set(workspace, releaseStrategy as any); + + if (this.all) { + let baseWorkspaces = new Map([...versionFile.releaseRoots.keys()].map(workspace => [workspace.anchoredLocator.locatorHash, workspace])); + let newChanged = true; + while (newChanged) { + newChanged = false; + const dependentWorkspaces = versionUtils.getDependentWorkspaces(versionFile.project, baseWorkspaces); + if (dependentWorkspaces.size) { + newChanged = true; + dependentWorkspaces.forEach(workspace => baseWorkspaces.set(workspace.anchoredLocator.locatorHash, workspace)); + } + } + + workspaces = new Set([...baseWorkspaces.values()]); + } + for (let workspace of workspaces) + await versionFile.releases.set(workspace, releaseStrategy as any); + await versionFile.saveAll(); if (!deferred) { diff --git a/packages/plugin-version/sources/versionUtils.ts b/packages/plugin-version/sources/versionUtils.ts index 4cb58bafac7a..8079109c1cb6 100644 --- a/packages/plugin-version/sources/versionUtils.ts +++ b/packages/plugin-version/sources/versionUtils.ts @@ -1,8 +1,8 @@ -import {AllDependencies, execUtils, miscUtils, hashUtils, Workspace, structUtils, Project, Manifest, IdentHash, Report, MessageName, WorkspaceResolver} from '@yarnpkg/core'; -import {Filename, PortablePath, npath, ppath, xfs} from '@yarnpkg/fslib'; -import {parseSyml, stringifySyml} from '@yarnpkg/parsers'; -import {UsageError} from 'clipanion'; -import semver from 'semver'; +import {AllDependencies, execUtils, miscUtils, hashUtils, Workspace, structUtils, Project, Manifest, IdentHash, Report, MessageName, WorkspaceResolver, LocatorHash} from '@yarnpkg/core'; +import {Filename, PortablePath, npath, ppath, xfs} from '@yarnpkg/fslib'; +import {parseSyml, stringifySyml} from '@yarnpkg/parsers'; +import {UsageError} from 'clipanion'; +import semver from 'semver'; // Basically we only support auto-upgrading the ranges that are very simple (^x.y.z, ~x.y.z, >=x.y.z, and of course x.y.z) const SUPPORTED_UPGRADE_REGEXP = /^(>=|[~^]|)(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/; @@ -385,6 +385,33 @@ export function getUndecidedDependentWorkspaces(versionFile: Pick) { + const dependentWorkspaces = new Set(); + + for (const workspace of project.workspaces) { + // Let's assume that packages without versions don't need to see their version increased + if (workspace.manifest.version === null) + continue; + + if (baseWorkspaces.has(workspace.anchoredLocator.locatorHash)) + continue; + + for (const dependencyType of Manifest.hardDependencies) { + for (const descriptor of workspace.manifest.getForScope(dependencyType).values()) { + const matchingWorkspace = project.tryWorkspaceByDescriptor(descriptor); + if (matchingWorkspace === null) + continue; + + if (baseWorkspaces.has(matchingWorkspace.anchoredLocator.locatorHash)) { + dependentWorkspaces.add(workspace); + } + } + } + } + + return dependentWorkspaces; +} + export function suggestStrategy(from: string, to: string) { const cleaned = semver.clean(to);