halkyon/tool/release_push.dart

77 lines
2.3 KiB
Dart
Raw Normal View History

// Says whether a push to main brings release commits alone (exit 0) or
// anything else (exit 1), for tool/pre-push, which then skips the checks: a
// release commit changes an app's version and its texts of what's new alone
// (tool/src/release/release_push.dart says why that is enough). Reads what
// git hands a pre-push hook: the remote as the argument, a line per ref pushed
// on stdin (local ref, local commit, remote ref, remote commit), and looks at
// the commits pushed to main that no ref of that remote has yet, as
// tool/check_signatures.sh does.
import 'dart:convert';
import 'dart:io';
import 'src/release/log.dart';
import 'src/release/release_push.dart';
import 'src/release/version.dart';
Future<void> main(List<String> arguments) async {
final remote = arguments.firstOrNull ?? 'origin';
final commits = <(Commit, List<String>)>[];
var pushesMain = false;
await for (final line
in stdin.transform(utf8.decoder).transform(const LineSplitter())) {
final fields = line.trim().split(RegExp(r'\s+'));
if (fields.length != 4 || fields[2] != 'refs/heads/main') {
continue;
}
final local = fields[1];
if (RegExp(r'^0+$').hasMatch(local)) {
continue;
}
pushesMain = true;
final log = await _git([
'log',
'--format=$logFormat',
'--name-only',
local,
'--not',
'--remotes=$remote',
]);
for (final commit in parseLog(log)) {
final diff = await _git([
'show',
'--format=',
'--unified=0',
commit.hash,
'--',
'*pubspec.yaml',
]);
commits.add((
commit,
[
for (final line in const LineSplitter().convert(diff))
if ((line.startsWith('+') || line.startsWith('-')) &&
!line.startsWith('+++') &&
!line.startsWith('---'))
line,
],
));
}
}
if (pushesMain && onlyReleaseCommits(commits)) {
stdout.writeln(
'▸ Release commits alone (${commits.map((c) => c.$1.subject).join('; ')}): '
'no checks needed.',
);
exit(0);
}
exit(1);
}
Future<String> _git(List<String> arguments) async {
final result = await Process.run('git', arguments);
if (result.exitCode != 0) {
stderr.writeln('git ${arguments.join(' ')}: ${result.stderr}');
exit(1);
}
return '${result.stdout}';
}