planRelease function
Plans new versions from the commits that touch each package.
commitsholds each package's commits since its last release.constraintsholds each package's version constraints on other workspace packages, as written in its pubspec.- With
sharedVersion, every package gets one version, raised by the largest bump any package needs (the catalogversion). - A package whose constraint on a released workspace package no longer allows the new version gets the constraint raised and a patch release.
forceBumpreplaces the bump from commits for every package.
Implementation
List<PackageRelease> planRelease({
required List<WorkspacePackage> packages,
required Map<String, List<ConventionalCommit>> commits,
Map<String, Map<String, String>> constraints = const {},
Version? sharedVersion,
Bump? forceBump,
String? prerelease,
bool graduate = false,
}) {
Bump bumpOf(WorkspacePackage package) =>
forceBump ??
(commits[package.name] ?? const [])
.map((commit) => commit.bump)
.fold(Bump.none, (a, b) => a.max(b));
final versioned = [
for (final package in packages)
if (package.version != null) package,
];
if (sharedVersion != null) {
final bump = versioned.map(bumpOf).fold(Bump.none, (a, b) => a.max(b));
if (bump == Bump.none && !graduate && prerelease == null) {
return const [];
}
final to = nextVersion(
sharedVersion,
bump == Bump.none ? Bump.patch : bump,
prerelease: prerelease,
graduate: graduate,
);
final releases = [
for (final package in versioned)
PackageRelease(
package: package,
from: Version.parse(package.version!),
to: to,
commits: commits[package.name] ?? const [],
),
];
_raiseConstraints(releases, releases, constraints);
return releases;
}
final releases = <String, PackageRelease>{};
for (final package in versioned) {
final bump = bumpOf(package);
if (bump == Bump.none && !(graduate && _isPre(package))) {
continue;
}
final from = Version.parse(package.version!);
releases[package.name] = PackageRelease(
package: package,
from: from,
to: nextVersion(from, bump, prerelease: prerelease, graduate: graduate),
commits: commits[package.name] ?? const [],
);
}
var changed = true;
while (changed) {
changed = false;
for (final package in versioned) {
final current = releases[package.name];
final needed = _constraintUpdates(
package,
releases.values.toList(),
constraints,
);
final missing = {
for (final MapEntry(:key, :value) in needed.entries)
if (current?.constraintUpdates[key] != value) key: value,
};
if (missing.isEmpty) {
continue;
}
changed = true;
final release =
current ??
(releases[package.name] = PackageRelease(
package: package,
from: Version.parse(package.version!),
to: nextVersion(
Version.parse(package.version!),
Bump.patch,
prerelease: prerelease,
),
commits: commits[package.name] ?? const [],
));
release.constraintUpdates.addAll(missing);
}
}
return [
for (final package in versioned)
if (releases[package.name] case final release?) release,
];
}