Unverified Commit 481dfec0 authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

[flutter_conductor] Support publishing to multiple channels (#94770)

parent 3b1e3ba7
...@@ -16,7 +16,7 @@ const List<String> kBaseReleaseChannels = <String>['stable', 'beta', 'dev']; ...@@ -16,7 +16,7 @@ const List<String> kBaseReleaseChannels = <String>['stable', 'beta', 'dev'];
const List<String> kReleaseChannels = <String>[...kBaseReleaseChannels, FrameworkRepository.defaultBranch]; const List<String> kReleaseChannels = <String>[...kBaseReleaseChannels, FrameworkRepository.defaultBranch];
const List<String> KReleaseIncrements = <String>['y', 'z', 'm', 'n']; const List<String> kReleaseIncrements = <String>['y', 'z', 'm', 'n'];
const String kReleaseDocumentationUrl = 'https://github.com/flutter/flutter/wiki/Flutter-Cherrypick-Process'; const String kReleaseDocumentationUrl = 'https://github.com/flutter/flutter/wiki/Flutter-Cherrypick-Process';
...@@ -28,6 +28,10 @@ final RegExp releaseCandidateBranchRegex = RegExp( ...@@ -28,6 +28,10 @@ final RegExp releaseCandidateBranchRegex = RegExp(
r'flutter-(\d+)\.(\d+)-candidate\.(\d+)', r'flutter-(\d+)\.(\d+)-candidate\.(\d+)',
); );
/// Whether all releases published to the beta channel should be mirrored to
/// dev.
const bool kSynchronizeDevWithBeta = true;
/// Cast a dynamic to String and trim. /// Cast a dynamic to String and trim.
String stdoutToString(dynamic input) { String stdoutToString(dynamic input) {
final String str = input as String; final String str = input as String;
......
...@@ -48,7 +48,7 @@ class NextCommand extends Command<void> { ...@@ -48,7 +48,7 @@ class NextCommand extends Command<void> {
String get description => 'Proceed to the next release phase.'; String get description => 'Proceed to the next release phase.';
@override @override
Future<void> run() async { Future<void> run() {
final File stateFile = checkouts.fileSystem.file(argResults![kStateOption]); final File stateFile = checkouts.fileSystem.file(argResults![kStateOption]);
if (!stateFile.existsSync()) { if (!stateFile.existsSync()) {
throw ConductorException( throw ConductorException(
...@@ -57,7 +57,7 @@ class NextCommand extends Command<void> { ...@@ -57,7 +57,7 @@ class NextCommand extends Command<void> {
} }
final pb.ConductorState state = state_import.readStateFromFile(stateFile); final pb.ConductorState state = state_import.readStateFromFile(stateFile);
await NextContext( return NextContext(
autoAccept: argResults![kYesFlag] as bool, autoAccept: argResults![kYesFlag] as bool,
checkouts: checkouts, checkouts: checkouts,
force: argResults![kForceFlag] as bool, force: argResults![kForceFlag] as bool,
...@@ -324,17 +324,24 @@ class NextContext extends Context { ...@@ -324,17 +324,24 @@ class NextContext extends Context {
previousCheckoutLocation: state.framework.checkoutPath, previousCheckoutLocation: state.framework.checkoutPath,
); );
final String headRevision = await framework.reverseParse('HEAD'); final String headRevision = await framework.reverseParse('HEAD');
final List<String> releaseRefs = <String>[state.releaseChannel];
if (kSynchronizeDevWithBeta && state.releaseChannel == 'beta') {
releaseRefs.add('dev');
}
for (final String releaseRef in releaseRefs) {
if (autoAccept == false) { if (autoAccept == false) {
// dryRun: true means print out git command // dryRun: true means print out git command
await framework.pushRef( await framework.pushRef(
fromRef: headRevision, fromRef: headRevision,
toRef: state.releaseChannel, toRef: releaseRef,
remote: state.framework.upstream.url, remote: state.framework.upstream.url,
force: force, force: force,
dryRun: true, dryRun: true,
); );
final bool response = await prompt('Are you ready to publish this release?'); final bool response = await prompt(
'Are you ready to publish version ${state.releaseVersion} to $releaseRef?',
);
if (!response) { if (!response) {
stdio.printError('Aborting command.'); stdio.printError('Aborting command.');
updateState(state, stdio.logs); updateState(state, stdio.logs);
...@@ -343,10 +350,11 @@ class NextContext extends Context { ...@@ -343,10 +350,11 @@ class NextContext extends Context {
} }
await framework.pushRef( await framework.pushRef(
fromRef: headRevision, fromRef: headRevision,
toRef: state.releaseChannel, toRef: releaseRef,
remote: state.framework.upstream.url, remote: state.framework.upstream.url,
force: force, force: force,
); );
}
break; break;
case pb.ReleasePhase.VERIFY_RELEASE: case pb.ReleasePhase.VERIFY_RELEASE:
stdio.printStatus( stdio.printStatus(
......
...@@ -93,7 +93,7 @@ class StartCommand extends Command<void> { ...@@ -93,7 +93,7 @@ class StartCommand extends Command<void> {
kIncrementOption, kIncrementOption,
help: 'Specifies which part of the x.y.z version number to increment. Required.', help: 'Specifies which part of the x.y.z version number to increment. Required.',
valueHelp: 'level', valueHelp: 'level',
allowed: KReleaseIncrements, allowed: kReleaseIncrements,
allowedHelp: <String, String>{ allowedHelp: <String, String>{
'y': 'Indicates the first dev release after a beta release.', 'y': 'Indicates the first dev release after a beta release.',
'z': 'Indicates a hotfix to a stable release.', 'z': 'Indicates a hotfix to a stable release.',
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import './globals.dart' show ConductorException, KReleaseIncrements, releaseCandidateBranchRegex; import './globals.dart' show ConductorException, kReleaseIncrements, releaseCandidateBranchRegex;
/// Possible string formats that `flutter --version` can return. /// Possible string formats that `flutter --version` can return.
enum VersionType { enum VersionType {
...@@ -262,7 +262,7 @@ class Version { ...@@ -262,7 +262,7 @@ class Version {
/// Will throw a [ConductorException] if the version is not possible given the /// Will throw a [ConductorException] if the version is not possible given the
/// [candidateBranch] and [incrementLetter]. /// [candidateBranch] and [incrementLetter].
void ensureValid(String candidateBranch, String incrementLetter) { void ensureValid(String candidateBranch, String incrementLetter) {
if (!KReleaseIncrements.contains(incrementLetter)) { if (!kReleaseIncrements.contains(incrementLetter)) {
throw ConductorException('Invalid incrementLetter: $incrementLetter'); throw ConductorException('Invalid incrementLetter: $incrementLetter');
} }
final RegExpMatch? branchMatch = releaseCandidateBranchRegex.firstMatch(candidateBranch); final RegExpMatch? branchMatch = releaseCandidateBranchRegex.firstMatch(candidateBranch);
......
...@@ -48,7 +48,7 @@ class TestStdio extends Stdio { ...@@ -48,7 +48,7 @@ class TestStdio extends Stdio {
@override @override
String readLineSync() { String readLineSync() {
if (stdin.isEmpty) { if (stdin.isEmpty) {
throw Exception('Unexpected call to readLineSync!'); throw Exception('Unexpected call to readLineSync! Last stdout was ${logs.last}');
} }
return stdin.removeAt(0); return stdin.removeAt(0);
} }
......
...@@ -966,6 +966,8 @@ void main() { ...@@ -966,6 +966,8 @@ void main() {
}); });
test('updates currentPhase if user responds yes', () async { test('updates currentPhase if user responds yes', () async {
stdio.stdin.add('y');
// for kSynchronizeDevWithBeta
stdio.stdin.add('y'); stdio.stdin.add('y');
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand( const FakeCommand(
...@@ -981,6 +983,10 @@ void main() { ...@@ -981,6 +983,10 @@ void main() {
const FakeCommand( const FakeCommand(
command: <String>['git', 'push', FrameworkRepository.defaultUpstream, '$revision1:$releaseChannel'], command: <String>['git', 'push', FrameworkRepository.defaultUpstream, '$revision1:$releaseChannel'],
), ),
// for kSynchronizeDevWithBeta
const FakeCommand(
command: <String>['git', 'push', FrameworkRepository.defaultUpstream, '$revision1:dev'],
),
]); ]);
writeStateToFile( writeStateToFile(
fileSystem.file(stateFile), fileSystem.file(stateFile),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment