Skip to content

Commit 0f0da62

Browse files
authored
update console output to specify post release steps (#102173)
* update console output to specify post release steps * move post release instructions * update instructions for beta vs stable * add logic to differentiate beta and stable steps
1 parent 760c375 commit 0f0da62

File tree

2 files changed

+49
-18
lines changed

2 files changed

+49
-18
lines changed

dev/conductor/core/lib/src/next.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,8 @@ class NextContext extends Context {
340340
'\t$kLuciPackagingConsoleLink',
341341
);
342342
if (autoAccept == false) {
343-
final bool response = await prompt('Have all packaging builds finished successfully?');
343+
final bool response = await prompt(
344+
'Have all packaging builds finished successfully and post release announcements been completed?');
344345
if (!response) {
345346
stdio.printError('Aborting command.');
346347
updateState(state, stdio.logs);

dev/conductor/core/lib/src/state.dart

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ String luciConsoleLink(String channel, String groupName) {
2222
<String>['flutter', 'engine', 'packaging'].contains(groupName),
2323
'group named $groupName not recognized',
2424
);
25-
final String consoleName = channel == 'master' ? groupName : '${channel}_$groupName';
25+
final String consoleName =
26+
channel == 'master' ? groupName : '${channel}_$groupName';
2627
return 'https://ci.chromium.org/p/flutter/g/$consoleName/console';
2728
}
2829

@@ -43,15 +44,18 @@ String presentState(pb.ConductorState state) {
4344
buffer.writeln('Release channel: ${state.releaseChannel}');
4445
buffer.writeln('Release version: ${state.releaseVersion}');
4546
buffer.writeln();
46-
buffer.writeln('Release started at: ${DateTime.fromMillisecondsSinceEpoch(state.createdDate.toInt())}');
47-
buffer.writeln('Last updated at: ${DateTime.fromMillisecondsSinceEpoch(state.lastUpdatedDate.toInt())}');
47+
buffer.writeln(
48+
'Release started at: ${DateTime.fromMillisecondsSinceEpoch(state.createdDate.toInt())}');
49+
buffer.writeln(
50+
'Last updated at: ${DateTime.fromMillisecondsSinceEpoch(state.lastUpdatedDate.toInt())}');
4851
buffer.writeln();
4952
buffer.writeln('Engine Repo');
5053
buffer.writeln('\tCandidate branch: ${state.engine.candidateBranch}');
5154
buffer.writeln('\tStarting git HEAD: ${state.engine.startingGitHead}');
5255
buffer.writeln('\tCurrent git HEAD: ${state.engine.currentGitHead}');
5356
buffer.writeln('\tPath to checkout: ${state.engine.checkoutPath}');
54-
buffer.writeln('\tPost-submit LUCI dashboard: ${luciConsoleLink(state.releaseChannel, 'engine')}');
57+
buffer.writeln(
58+
'\tPost-submit LUCI dashboard: ${luciConsoleLink(state.releaseChannel, 'engine')}');
5559
if (state.engine.cherrypicks.isNotEmpty) {
5660
buffer.writeln('${state.engine.cherrypicks.length} Engine Cherrypicks:');
5761
for (final pb.Cherrypick cherrypick in state.engine.cherrypicks) {
@@ -60,17 +64,20 @@ String presentState(pb.ConductorState state) {
6064
} else {
6165
buffer.writeln('0 Engine cherrypicks.');
6266
}
63-
if (state.engine.dartRevision != null && state.engine.dartRevision.isNotEmpty) {
67+
if (state.engine.dartRevision != null &&
68+
state.engine.dartRevision.isNotEmpty) {
6469
buffer.writeln('New Dart SDK revision: ${state.engine.dartRevision}');
6570
}
6671
buffer.writeln('Framework Repo');
6772
buffer.writeln('\tCandidate branch: ${state.framework.candidateBranch}');
6873
buffer.writeln('\tStarting git HEAD: ${state.framework.startingGitHead}');
6974
buffer.writeln('\tCurrent git HEAD: ${state.framework.currentGitHead}');
7075
buffer.writeln('\tPath to checkout: ${state.framework.checkoutPath}');
71-
buffer.writeln('\tPost-submit LUCI dashboard: ${luciConsoleLink(state.releaseChannel, 'flutter')}');
76+
buffer.writeln(
77+
'\tPost-submit LUCI dashboard: ${luciConsoleLink(state.releaseChannel, 'flutter')}');
7278
if (state.framework.cherrypicks.isNotEmpty) {
73-
buffer.writeln('${state.framework.cherrypicks.length} Framework Cherrypicks:');
79+
buffer.writeln(
80+
'${state.framework.cherrypicks.length} Framework Cherrypicks:');
7481
for (final pb.Cherrypick cherrypick in state.framework.cherrypicks) {
7582
buffer.writeln('\t${cherrypick.trunkRevision} - ${cherrypick.state}');
7683
}
@@ -125,7 +132,8 @@ String phaseInstructions(pb.ConductorState state) {
125132
return <String>[
126133
'You must now manually apply the following engine cherrypicks to the checkout',
127134
'at ${state.engine.checkoutPath} in order:',
128-
for (final pb.Cherrypick cherrypick in state.engine.cherrypicks) '\t${cherrypick.trunkRevision}',
135+
for (final pb.Cherrypick cherrypick in state.engine.cherrypicks)
136+
'\t${cherrypick.trunkRevision}',
129137
'See $kReleaseDocumentationUrl for more information.',
130138
].join('\n');
131139
case ReleasePhase.CODESIGN_ENGINE_BINARIES:
@@ -147,19 +155,24 @@ String phaseInstructions(pb.ConductorState state) {
147155
'validate post-submit CI, and then codesign the binaries on the merge commit.',
148156
].join('\n');
149157
case ReleasePhase.APPLY_FRAMEWORK_CHERRYPICKS:
150-
final List<pb.Cherrypick> outstandingCherrypicks = state.framework.cherrypicks.where(
158+
final List<pb.Cherrypick> outstandingCherrypicks =
159+
state.framework.cherrypicks.where(
151160
(pb.Cherrypick cp) {
152-
return cp.state == pb.CherrypickState.PENDING || cp.state == pb.CherrypickState.PENDING_WITH_CONFLICT;
161+
return cp.state == pb.CherrypickState.PENDING ||
162+
cp.state == pb.CherrypickState.PENDING_WITH_CONFLICT;
153163
},
154164
).toList();
155165
if (outstandingCherrypicks.isNotEmpty) {
156166
return <String>[
157167
'You must now manually apply the following framework cherrypicks to the checkout',
158168
'at ${state.framework.checkoutPath} in order:',
159-
for (final pb.Cherrypick cherrypick in outstandingCherrypicks) '\t${cherrypick.trunkRevision}',
169+
for (final pb.Cherrypick cherrypick in outstandingCherrypicks)
170+
'\t${cherrypick.trunkRevision}',
160171
].join('\n');
161172
}
162-
return <String>['Either all cherrypicks have been auto-applied or there were none.'].join('\n');
173+
return <String>[
174+
'Either all cherrypicks have been auto-applied or there were none.'
175+
].join('\n');
163176
case ReleasePhase.PUBLISH_VERSION:
164177
if (!requiresFrameworkPR(state)) {
165178
return 'Since there are no code changes in this release, no Framework '
@@ -182,7 +195,24 @@ String phaseInstructions(pb.ConductorState state) {
182195
case ReleasePhase.VERIFY_RELEASE:
183196
return 'Release archive packages must be verified on cloud storage: ${luciConsoleLink(state.releaseChannel, 'packaging')}';
184197
case ReleasePhase.RELEASE_COMPLETED:
185-
return 'This release has been completed.';
198+
if (state.releaseChannel == 'beta') {
199+
return <String>[
200+
'Ensure the following post release steps are complete:',
201+
'\t 1. Post announcement to discord',
202+
'\t 2. Post announcement flutter release hotline chat room',
203+
'-----------------------------------------------------------------------',
204+
'This release has been completed.'
205+
].join('\n');
206+
}
207+
return <String>[
208+
'Ensure the following post release steps are complete:',
209+
'\t 1. Update hotfix to stable wiki following documentation best practices',
210+
'\t 2. Post announcement to flutter-announce group',
211+
'\t 3. Post announcement to discord',
212+
'\t 4. Post announcement flutter release hotline chat room',
213+
'-----------------------------------------------------------------------',
214+
'This release has been completed.'
215+
].join('\n');
186216
}
187217
// For analyzer
188218
throw ConductorException('Unimplemented phase ${state.currentPhase}');
@@ -193,8 +223,8 @@ String phaseInstructions(pb.ConductorState state) {
193223
/// First group = git host (currently must be github.com)
194224
/// Second group = account name
195225
/// Third group = repo name
196-
final RegExp githubRemotePattern =
197-
RegExp(r'^(git@github\.com:|https?:\/\/github\.com\/)([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+)(\.git)?$');
226+
final RegExp githubRemotePattern = RegExp(
227+
r'^(git@github\.com:|https?:\/\/github\.com\/)([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+)(\.git)?$');
198228

199229
/// Parses a Git remote URL and returns the account name.
200230
///
@@ -271,8 +301,8 @@ bool requiresFrameworkPR(pb.ConductorState state) {
271301
if (requiresEnginePR(state)) {
272302
return true;
273303
}
274-
final bool hasRequiredCherrypicks =
275-
state.framework.cherrypicks.any((pb.Cherrypick cp) => cp.state != pb.CherrypickState.ABANDONED);
304+
final bool hasRequiredCherrypicks = state.framework.cherrypicks
305+
.any((pb.Cherrypick cp) => cp.state != pb.CherrypickState.ABANDONED);
276306
if (hasRequiredCherrypicks) {
277307
return true;
278308
}

0 commit comments

Comments
 (0)