versionWorkspace function
Future<WorkspaceVersionResult>
versionWorkspace({
- required Directory gitRoot,
- required WorkspaceInfo workspace,
- String? baseRef,
- required bool tag,
- String? newRef,
- required bool isPreRelease,
- required String preReleasePrefix,
- required bool commit,
- required bool badge,
- required bool generateChangelog,
- required bool cache,
- String? dartFile,
- WorkspaceTagFormat tagFormat = const WorkspaceTagFormat(),
Versions all packages in a workspace
Implementation
Future<WorkspaceVersionResult> versionWorkspace({
required Directory gitRoot,
required WorkspaceInfo workspace,
String? baseRef,
required bool tag,
String? newRef,
required bool isPreRelease,
required String preReleasePrefix,
required bool commit,
required bool badge,
required bool generateChangelog,
required bool cache,
String? dartFile,
WorkspaceTagFormat tagFormat = const WorkspaceTagFormat(),
}) async {
final packages = getWorkspacePackages(workspace);
final effectiveNewRef = newRef ?? 'HEAD';
logger.info('Found ${packages.length} packages in workspace');
// Sort packages so dependencies are versioned before their consumers.
// This ensures that when a consumer is versioned, its pubspec already
// reflects the updated sibling constraint, making the dep bump part of
// the same versioned commit and preventing cascade bumps on the next run.
final sortedPackages = sortPackagesTopologically(packages);
// Track which packages were versioned and their new versions
final packageResults = <String, VersionResult>{};
final packageVersions = <String, Version>{};
// Version each changed package in topological order.
// After each versioned package, immediately update its consumers' pubspecs
// so that subsequent packages in the loop see the new constraint when they
// are checked for changes and versioned.
for (final package in sortedPackages) {
logger.info('Processing package: ${package.name}');
// Determine the base ref for this package
// If baseRef is provided, use it; otherwise get the previous tag for this package
final packageBaseRef =
baseRef ??
(await GitUtils.getPreviousRefForPackage(
gitRoot.path,
package.name,
tagPrefix: tagFormat.versionPrefix,
separator: tagFormat.separator,
) ??
effectiveNewRef);
// Check if package has changes
final hasChanges = await packageHasChanges(package.relativePath, packageBaseRef, effectiveNewRef, gitRoot);
if (!hasChanges) {
logger.info('Package ${package.name} has no changes, skipping versioning');
continue;
}
logger.info('Package ${package.name} has changes, versioning...');
// Determine tag prefix for this package from the tag format (e.g. package-name/v)
final tagPrefix = tagFormat.prefixFor(package.name);
// Version the package
try {
final result = await version(
gitRoot: gitRoot,
dartRoot: package.directory,
baseRef: baseRef,
tag: tag,
newRef: effectiveNewRef,
isPreRelease: isPreRelease,
preReleasePrefix: preReleasePrefix,
commit: commit,
badge: badge,
generateChangelog: generateChangelog,
cache: cache,
tagPrefix: tagPrefix,
dartFile: dartFile != null ? path.join(package.directory.path, dartFile) : null,
packageName: package.name,
tagFormat: tagFormat,
);
packageResults[package.name] = result;
packageVersions[package.name] = result.version;
logger.success('Versioned ${package.name} to ${result.version}');
// Immediately propagate this package's new version into the pubspecs of
// any workspace packages that depend on it, so they see the updated
// constraint when they are versioned later in this same loop.
await updateWorkspaceDependencies(
workspace: workspace,
packages: sortedPackages,
updatedVersions: {package.name: result.version},
);
} catch (e) {
logger.err('Failed to version package ${package.name}: $e');
rethrow;
}
}
return WorkspaceVersionResult(packageResults: packageResults, packageVersions: packageVersions);
}