[flutter_conductor] Support publishing to multiple channels (#94770)
This commit is contained in:
parent
3b1e3ba7de
commit
481dfec00e
@ -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(
|
|||||||
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> {
|
|||||||
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> {
|
|||||||
}
|
}
|
||||||
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,29 +324,37 @@ 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');
|
||||||
if (autoAccept == false) {
|
final List<String> releaseRefs = <String>[state.releaseChannel];
|
||||||
// dryRun: true means print out git command
|
if (kSynchronizeDevWithBeta && state.releaseChannel == 'beta') {
|
||||||
await framework.pushRef(
|
releaseRefs.add('dev');
|
||||||
|
}
|
||||||
|
for (final String releaseRef in releaseRefs) {
|
||||||
|
if (autoAccept == false) {
|
||||||
|
// dryRun: true means print out git command
|
||||||
|
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(
|
||||||
if (!response) {
|
'Are you ready to publish version ${state.releaseVersion} to $releaseRef?',
|
||||||
stdio.printError('Aborting command.');
|
);
|
||||||
updateState(state, stdio.logs);
|
if (!response) {
|
||||||
return;
|
stdio.printError('Aborting command.');
|
||||||
|
updateState(state, stdio.logs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
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> {
|
|||||||
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 @@
|
|||||||
// 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 {
|
|||||||
/// 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 {
|
|||||||
@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() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
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() {
|
|||||||
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),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user