Skip to content

Commit a3c7ab2

Browse files
committed
[ci] Adds repo checks for batch release
1 parent 8a52f44 commit a3c7ab2

9 files changed

+827
-267
lines changed

script/tool/lib/src/branch_for_batch_release_command.dart

Lines changed: 23 additions & 137 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,10 +64,15 @@ class BranchForBatchReleaseCommand extends PackageCommand {
6964
final GitDir repository = await gitDir;
7065

7166
print('Parsing package "${package.displayName}"...');
72-
final _PendingChangelogs pendingChangelogs = await _getPendingChangelogs(
73-
package,
74-
);
75-
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) {
7676
print('No pending changelogs found for ${package.displayName}.');
7777
return;
7878
}
@@ -85,7 +85,7 @@ class BranchForBatchReleaseCommand extends PackageCommand {
8585
throw ToolExit(_kExitPackageMalformed);
8686
}
8787
final _ReleaseInfo releaseInfo = _getReleaseInfo(
88-
pendingChangelogs.entries,
88+
pendingChangelogs,
8989
pubspec.version!,
9090
);
9191

@@ -101,77 +101,36 @@ class BranchForBatchReleaseCommand extends PackageCommand {
101101
git: repository,
102102
package: package,
103103
branchName: branchName,
104-
pendingChangelogFiles: pendingChangelogs.files,
104+
pendingChangelogFiles: pendingChangelogs
105+
.map<File>((PendingChangelogEntry e) => e.file)
106+
.toList(),
105107
releaseInfo: releaseInfo,
106108
remoteName: remoteName,
107109
);
108110
}
109111

110-
/// Returns the parsed changelog entries for the given package.
111-
///
112-
/// This method read through the files in the pending_changelogs folder
113-
/// and parsed each file as a changelog entry.
114-
///
115-
/// Throws a [ToolExit] if the package does not have a pending_changelogs folder.
116-
Future<_PendingChangelogs> _getPendingChangelogs(
117-
RepositoryPackage package,
118-
) async {
119-
final Directory pendingChangelogsDir = package.directory.childDirectory(
120-
'pending_changelogs',
121-
);
122-
if (!pendingChangelogsDir.existsSync()) {
123-
printError(
124-
'No pending_changelogs folder found for ${package.displayName}.',
125-
);
126-
throw ToolExit(_kExitPackageMalformed);
127-
}
128-
final List<File> pendingChangelogFiles = pendingChangelogsDir
129-
.listSync()
130-
.whereType<File>()
131-
.where(
132-
(File f) =>
133-
f.basename.endsWith('.yaml') && f.basename != _kTemplateFileName,
134-
)
135-
.toList();
136-
try {
137-
final List<_PendingChangelogEntry> entries = pendingChangelogFiles
138-
.map<_PendingChangelogEntry>(
139-
(File f) => _PendingChangelogEntry.parse(f.readAsStringSync()),
140-
)
141-
.toList();
142-
return _PendingChangelogs(entries, pendingChangelogFiles);
143-
} on FormatException catch (e) {
144-
printError('Malformed pending changelog file: $e');
145-
throw ToolExit(_kExitPackageMalformed);
146-
}
147-
}
148-
149112
/// Returns the release info for the given package.
150113
///
151114
/// This method read through the parsed changelog entries decide the new version
152115
/// by following the version change rules. See [_VersionChange] for more details.
153116
_ReleaseInfo _getReleaseInfo(
154-
List<_PendingChangelogEntry> pendingChangelogEntries,
117+
List<PendingChangelogEntry> pendingChangelogEntries,
155118
Version oldVersion,
156119
) {
157-
final changelogs = <String>[];
158-
int versionIndex = _VersionChange.skip.index;
159-
for (final entry in pendingChangelogEntries) {
120+
final List<String> changelogs = <String>[];
121+
int versionIndex = VersionChange.skip.index;
122+
for (final PendingChangelogEntry entry in pendingChangelogEntries) {
160123
changelogs.add(entry.changelog);
161124
versionIndex = math.min(versionIndex, entry.version.index);
162125
}
163-
final _VersionChange effectiveVersionChange =
164-
_VersionChange.values[versionIndex];
126+
final VersionChange effectiveVersionChange =
127+
VersionChange.values[versionIndex];
165128

166129
final Version? newVersion = switch (effectiveVersionChange) {
167-
_VersionChange.skip => null,
168-
_VersionChange.major => Version(oldVersion.major + 1, 0, 0),
169-
_VersionChange.minor => Version(
170-
oldVersion.major,
171-
oldVersion.minor + 1,
172-
0,
173-
),
174-
_VersionChange.patch => Version(
130+
VersionChange.skip => null,
131+
VersionChange.major => Version(oldVersion.major + 1, 0, 0),
132+
VersionChange.minor => Version(oldVersion.major, oldVersion.minor + 1, 0),
133+
VersionChange.patch => Version(
175134
oldVersion.major,
176135
oldVersion.minor,
177136
oldVersion.patch + 1,
@@ -305,18 +264,6 @@ class BranchForBatchReleaseCommand extends PackageCommand {
305264
}
306265
}
307266

308-
/// A data class for pending changelogs.
309-
class _PendingChangelogs {
310-
/// Creates a new instance.
311-
_PendingChangelogs(this.entries, this.files);
312-
313-
/// The parsed pending changelog entries.
314-
final List<_PendingChangelogEntry> entries;
315-
316-
/// The files that the pending changelog entries were parsed from.
317-
final List<File> files;
318-
}
319-
320267
/// A data class for processed release information.
321268
class _ReleaseInfo {
322269
/// Creates a new instance.
@@ -328,64 +275,3 @@ class _ReleaseInfo {
328275
/// The combined changelog entries.
329276
final List<String> changelogs;
330277
}
331-
332-
/// The type of version change for a release.
333-
///
334-
/// The order of the enum values is important as it is used to determine which version
335-
/// take priority when multiple version changes are specified. The top most value
336-
/// (the samller the index) has the highest priority.
337-
enum _VersionChange {
338-
/// A major version change (e.g., 1.2.3 -> 2.0.0).
339-
major,
340-
341-
/// A minor version change (e.g., 1.2.3 -> 1.3.0).
342-
minor,
343-
344-
/// A patch version change (e.g., 1.2.3 -> 1.2.4).
345-
patch,
346-
347-
/// No version change.
348-
skip,
349-
}
350-
351-
/// Represents a single entry in the pending changelog.
352-
class _PendingChangelogEntry {
353-
/// Creates a new pending changelog entry.
354-
_PendingChangelogEntry({required this.changelog, required this.version});
355-
356-
/// Creates a PendingChangelogEntry from a YAML string.
357-
factory _PendingChangelogEntry.parse(String yamlContent) {
358-
final dynamic yaml = loadYaml(yamlContent);
359-
if (yaml is! YamlMap) {
360-
throw FormatException(
361-
'Expected a YAML map, but found ${yaml.runtimeType}.',
362-
);
363-
}
364-
365-
final dynamic changelogYaml = yaml['changelog'];
366-
if (changelogYaml is! String) {
367-
throw FormatException(
368-
'Expected "changelog" to be a string, but found ${changelogYaml.runtimeType}.',
369-
);
370-
}
371-
final String changelog = changelogYaml.trim();
372-
373-
final versionString = yaml['version'] as String?;
374-
if (versionString == null) {
375-
throw const FormatException('Missing "version" key.');
376-
}
377-
final _VersionChange version = _VersionChange.values.firstWhere(
378-
(_VersionChange e) => e.name == versionString,
379-
orElse: () =>
380-
throw FormatException('Invalid version type: $versionString'),
381-
);
382-
383-
return _PendingChangelogEntry(changelog: changelog, version: version);
384-
}
385-
386-
/// The changelog messages for this entry.
387-
final String changelog;
388-
389-
/// The type of version change for this entry.
390-
final _VersionChange version;
391-
}

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)