Skip to content

Commit a0333a0

Browse files
committed
[ci] Adds repo checks for batch release
1 parent 6f2dd54 commit a0333a0

9 files changed

+812
-228
lines changed

script/tool/lib/src/branch_for_batch_release_command.dart

Lines changed: 22 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import 'dart:math' as math;
88
import 'package:file/file.dart';
99
import 'package:git/git.dart';
1010
import 'package:pub_semver/pub_semver.dart';
11-
import 'package:yaml/yaml.dart';
1211
import 'package:yaml_edit/yaml_edit.dart';
1312

1413
import 'common/core.dart';
@@ -19,10 +18,6 @@ import 'common/repository_package.dart';
1918
const int _kExitPackageMalformed = 3;
2019
const int _kGitFailedToPush = 4;
2120

22-
// The template file name used to draft a pending changelog file.
23-
// This file will not be picked up by the batch release process.
24-
const String _kTemplateFileName = 'template.yaml';
25-
2621
/// A command to create a remote branch with release changes for a single package.
2722
class BranchForBatchReleaseCommand extends PackageCommand {
2823
/// Creates a new `branch-for-batch-release` command.
@@ -69,9 +64,15 @@ class BranchForBatchReleaseCommand extends PackageCommand {
6964
final GitDir repository = await gitDir;
7065

7166
print('Parsing package "${package.displayName}"...');
72-
final _PendingChangelogs pendingChangelogs =
73-
await _getPendingChangelogs(package);
74-
if (pendingChangelogs.entries.isEmpty) {
67+
final List<PendingChangelogEntry> pendingChangelogs;
68+
try {
69+
pendingChangelogs = package.getPendingChangelogs();
70+
} on FormatException catch (e) {
71+
printError('Failed to parse pending changelogs: ${e.message}');
72+
throw ToolExit(_kExitPackageMalformed);
73+
}
74+
75+
if (pendingChangelogs.isEmpty) {
7576
print('No pending changelogs found for ${package.displayName}.');
7677
return;
7778
}
@@ -84,7 +85,7 @@ class BranchForBatchReleaseCommand extends PackageCommand {
8485
throw ToolExit(_kExitPackageMalformed);
8586
}
8687
final _ReleaseInfo releaseInfo =
87-
_getReleaseInfo(pendingChangelogs.entries, pubspec.version!);
88+
_getReleaseInfo(pendingChangelogs, pubspec.version!);
8889

8990
if (releaseInfo.newVersion == null) {
9091
print('No version change specified in pending changelogs for '
@@ -96,67 +97,34 @@ class BranchForBatchReleaseCommand extends PackageCommand {
9697
git: repository,
9798
package: package,
9899
branchName: branchName,
99-
pendingChangelogFiles: pendingChangelogs.files,
100+
pendingChangelogFiles: pendingChangelogs
101+
.map<File>((PendingChangelogEntry e) => e.file)
102+
.toList(),
100103
releaseInfo: releaseInfo,
101104
remoteName: remoteName,
102105
);
103106
}
104107

105-
/// Returns the parsed changelog entries for the given package.
106-
///
107-
/// This method read through the files in the pending_changelogs folder
108-
/// and parsed each file as a changelog entry.
109-
///
110-
/// Throws a [ToolExit] if the package does not have a pending_changelogs folder.
111-
Future<_PendingChangelogs> _getPendingChangelogs(
112-
RepositoryPackage package) async {
113-
final Directory pendingChangelogsDir =
114-
package.directory.childDirectory('pending_changelogs');
115-
if (!pendingChangelogsDir.existsSync()) {
116-
printError(
117-
'No pending_changelogs folder found for ${package.displayName}.');
118-
throw ToolExit(_kExitPackageMalformed);
119-
}
120-
final List<File> pendingChangelogFiles = pendingChangelogsDir
121-
.listSync()
122-
.whereType<File>()
123-
.where((File f) =>
124-
f.basename.endsWith('.yaml') && f.basename != _kTemplateFileName)
125-
.toList();
126-
try {
127-
final List<_PendingChangelogEntry> entries = pendingChangelogFiles
128-
.map<_PendingChangelogEntry>(
129-
(File f) => _PendingChangelogEntry.parse(f.readAsStringSync()))
130-
.toList();
131-
return _PendingChangelogs(entries, pendingChangelogFiles);
132-
} on FormatException catch (e) {
133-
printError('Malformed pending changelog file: $e');
134-
throw ToolExit(_kExitPackageMalformed);
135-
}
136-
}
137-
138108
/// Returns the release info for the given package.
139109
///
140110
/// This method read through the parsed changelog entries decide the new version
141111
/// by following the version change rules. See [_VersionChange] for more details.
142112
_ReleaseInfo _getReleaseInfo(
143-
List<_PendingChangelogEntry> pendingChangelogEntries,
144-
Version oldVersion) {
113+
List<PendingChangelogEntry> pendingChangelogEntries, Version oldVersion) {
145114
final List<String> changelogs = <String>[];
146-
int versionIndex = _VersionChange.skip.index;
147-
for (final _PendingChangelogEntry entry in pendingChangelogEntries) {
115+
int versionIndex = VersionChange.skip.index;
116+
for (final PendingChangelogEntry entry in pendingChangelogEntries) {
148117
changelogs.add(entry.changelog);
149118
versionIndex = math.min(versionIndex, entry.version.index);
150119
}
151-
final _VersionChange effectiveVersionChange =
152-
_VersionChange.values[versionIndex];
120+
final VersionChange effectiveVersionChange =
121+
VersionChange.values[versionIndex];
153122

154123
final Version? newVersion = switch (effectiveVersionChange) {
155-
_VersionChange.skip => null,
156-
_VersionChange.major => Version(oldVersion.major + 1, 0, 0),
157-
_VersionChange.minor =>
158-
Version(oldVersion.major, oldVersion.minor + 1, 0),
159-
_VersionChange.patch =>
124+
VersionChange.skip => null,
125+
VersionChange.major => Version(oldVersion.major + 1, 0, 0),
126+
VersionChange.minor => Version(oldVersion.major, oldVersion.minor + 1, 0),
127+
VersionChange.patch =>
160128
Version(oldVersion.major, oldVersion.minor, oldVersion.patch + 1),
161129
};
162130
return _ReleaseInfo(newVersion, changelogs);
@@ -266,18 +234,6 @@ class BranchForBatchReleaseCommand extends PackageCommand {
266234
}
267235
}
268236

269-
/// A data class for pending changelogs.
270-
class _PendingChangelogs {
271-
/// Creates a new instance.
272-
_PendingChangelogs(this.entries, this.files);
273-
274-
/// The parsed pending changelog entries.
275-
final List<_PendingChangelogEntry> entries;
276-
277-
/// The files that the pending changelog entries were parsed from.
278-
final List<File> files;
279-
}
280-
281237
/// A data class for processed release information.
282238
class _ReleaseInfo {
283239
/// Creates a new instance.
@@ -289,62 +245,3 @@ class _ReleaseInfo {
289245
/// The combined changelog entries.
290246
final List<String> changelogs;
291247
}
292-
293-
/// The type of version change for a release.
294-
///
295-
/// The order of the enum values is important as it is used to determine which version
296-
/// take priority when multiple version changes are specified. The top most value
297-
/// (the samller the index) has the highest priority.
298-
enum _VersionChange {
299-
/// A major version change (e.g., 1.2.3 -> 2.0.0).
300-
major,
301-
302-
/// A minor version change (e.g., 1.2.3 -> 1.3.0).
303-
minor,
304-
305-
/// A patch version change (e.g., 1.2.3 -> 1.2.4).
306-
patch,
307-
308-
/// No version change.
309-
skip,
310-
}
311-
312-
/// Represents a single entry in the pending changelog.
313-
class _PendingChangelogEntry {
314-
/// Creates a new pending changelog entry.
315-
_PendingChangelogEntry({required this.changelog, required this.version});
316-
317-
/// Creates a PendingChangelogEntry from a YAML string.
318-
factory _PendingChangelogEntry.parse(String yamlContent) {
319-
final dynamic yaml = loadYaml(yamlContent);
320-
if (yaml is! YamlMap) {
321-
throw FormatException(
322-
'Expected a YAML map, but found ${yaml.runtimeType}.');
323-
}
324-
325-
final dynamic changelogYaml = yaml['changelog'];
326-
if (changelogYaml is! String) {
327-
throw FormatException(
328-
'Expected "changelog" to be a string, but found ${changelogYaml.runtimeType}.');
329-
}
330-
final String changelog = changelogYaml.trim();
331-
332-
final String? versionString = yaml['version'] as String?;
333-
if (versionString == null) {
334-
throw const FormatException('Missing "version" key.');
335-
}
336-
final _VersionChange version = _VersionChange.values.firstWhere(
337-
(_VersionChange e) => e.name == versionString,
338-
orElse: () =>
339-
throw FormatException('Invalid version type: $versionString'),
340-
);
341-
342-
return _PendingChangelogEntry(changelog: changelog, version: version);
343-
}
344-
345-
/// The changelog messages for this entry.
346-
final String changelog;
347-
348-
/// The type of version change for this entry.
349-
final _VersionChange version;
350-
}

script/tool/lib/src/common/package_state_utils.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ Future<PackageChangeState> checkPackageChangeState(
8080
continue;
8181
}
8282

83+
if (package.parseCiConfig()?.isBatchRelease ?? false) {
84+
if (components.first == 'pending_changelogs') {
85+
hasChangelogChange = true;
86+
continue;
87+
}
88+
}
89+
8390
if (!needsVersionChange) {
8491
// Developer-only changes don't need version changes or changelog changes.
8592
if (await _isDevChange(components, git: git, repoPath: path)) {

0 commit comments

Comments
 (0)