From a82255b57abedffd7342b8560f4336acac0cfb4c Mon Sep 17 00:00:00 2001 From: Christopher Fujino Date: Thu, 29 Jul 2021 14:19:04 -0700 Subject: [PATCH] [flutter_conductor] updates (#86452) --- dev/conductor/bin/conductor | 3 + dev/conductor/lib/globals.dart | 17 ++- dev/conductor/lib/next.dart | 36 ++--- .../lib/proto/conductor_state.pb.dart | 18 +++ .../lib/proto/conductor_state.pbjson.dart | 3 +- dev/conductor/lib/proto/conductor_state.proto | 3 + dev/conductor/lib/repository.dart | 4 +- dev/conductor/lib/start.dart | 1 + dev/conductor/lib/state.dart | 127 +++++++++++++++--- dev/conductor/lib/stdio.dart | 8 +- dev/conductor/test/next_test.dart | 35 +++-- dev/conductor/test/start_test.dart | 4 +- 12 files changed, 202 insertions(+), 57 deletions(-) diff --git a/dev/conductor/bin/conductor b/dev/conductor/bin/conductor index 2897339d52..627db251f0 100755 --- a/dev/conductor/bin/conductor +++ b/dev/conductor/bin/conductor @@ -37,4 +37,7 @@ BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)" REPO_DIR="$BIN_DIR/../../.." DART_BIN="$REPO_DIR/bin/dart" +# Ensure pub get has been run in the repo before running the conductor +(cd "$REPO_DIR/dev/conductor"; $DART_BIN pub get 1>&2) + "$DART_BIN" --enable-asserts "$REPO_DIR/dev/conductor/bin/conductor.dart" "$@" diff --git a/dev/conductor/lib/globals.dart b/dev/conductor/lib/globals.dart index 670041c376..ff8adffd5a 100644 --- a/dev/conductor/lib/globals.dart +++ b/dev/conductor/lib/globals.dart @@ -85,11 +85,10 @@ String? getValueFromEnvOrArgs( String name, ArgResults argResults, Map env, { - bool allowNull = false, - } -) { + bool allowNull = false, +}) { final String envName = fromArgToEnvName(name); - if (env[envName] != null ) { + if (env[envName] != null) { return env[envName]; } final String? argValue = argResults[name] as String?; @@ -139,3 +138,13 @@ List getValuesFromEnvOrArgs( String fromArgToEnvName(String argName) { return argName.toUpperCase().replaceAll(r'-', r'_'); } + +/// Return a web link for the user to open a new PR. +String getNewPrLink({ + required String userName, + required String repoName, + required String candidateBranch, + required String workingBranch, +}) { + return 'https://github.com/flutter/$repoName/compare/$candidateBranch...$userName:$workingBranch?expand=1'; +} diff --git a/dev/conductor/lib/next.dart b/dev/conductor/lib/next.dart index cef5e89b67..d3686c5145 100644 --- a/dev/conductor/lib/next.dart +++ b/dev/conductor/lib/next.dart @@ -102,7 +102,7 @@ void runNext({ } } - if (state.engine.cherrypicks.isEmpty && state.engine.dartRevision.isEmpty) { + if (!requiresEnginePR(state)) { stdio.printStatus( 'This release has no engine cherrypicks. No Engine PR is necessary.\n', ); @@ -110,18 +110,16 @@ void runNext({ } if (unappliedCherrypicks.isEmpty) { - stdio.printStatus('All engine cherrypicks have been auto-applied by ' - 'the conductor.\n'); + stdio.printStatus('All engine cherrypicks have been auto-applied by the conductor.\n'); } else { - stdio.printStatus( - 'There were ${unappliedCherrypicks.length} cherrypicks that were not auto-applied.'); + stdio.printStatus('There were ${unappliedCherrypicks.length} cherrypicks that were not auto-applied.'); stdio.printStatus('These must be applied manually in the directory ' - '${state.engine.checkoutPath} before proceeding.\n'); + '${state.engine.checkoutPath} before proceeding.\n'); } if (autoAccept == false) { final bool response = prompt( - 'Are you ready to push your engine branch to the repository ' - '${state.engine.mirror.url}?', + 'Are you ready to push your engine branch to the repository ' + '${state.engine.mirror.url}?', stdio, ); if (!response) { @@ -189,13 +187,15 @@ void runNext({ break; } } + final Remote engineUpstreamRemote = Remote( + name: RemoteName.upstream, + url: state.engine.upstream.url, + ); final EngineRepository engine = EngineRepository( checkouts, - initialRef: state.engine.candidateBranch, - upstreamRemote: Remote( - name: RemoteName.upstream, - url: state.engine.upstream.url, - ), + // We explicitly want to check out the merged version from upstream + initialRef: '${engineUpstreamRemote.name}/${state.engine.candidateBranch}', + upstreamRemote: engineUpstreamRemote, previousCheckoutLocation: state.engine.checkoutPath, ); @@ -215,7 +215,9 @@ void runNext({ stdio.printStatus('Rolling new engine hash $engineRevision to framework checkout...'); framework.updateEngineRevision(engineRevision); - framework.commit('Update Engine revision to $engineRevision for ${state.releaseChannel} release ${state.releaseVersion}', addFirst: true); + framework.commit( + 'Update Engine revision to $engineRevision for ${state.releaseChannel} release ${state.releaseVersion}', + addFirst: true); if (state.framework.cherrypicks.isEmpty) { stdio.printStatus( @@ -262,7 +264,8 @@ void runNext({ ); final FrameworkRepository framework = FrameworkRepository( checkouts, - initialRef: state.framework.candidateBranch, + // We explicitly want to check out the merged version from upstream + initialRef: '${upstream.name}/${state.framework.candidateBranch}', upstreamRemote: upstream, previousCheckoutLocation: state.framework.checkoutPath, ); @@ -288,7 +291,8 @@ void runNext({ ); final FrameworkRepository framework = FrameworkRepository( checkouts, - initialRef: state.framework.candidateBranch, + // We explicitly want to check out the merged version from upstream + initialRef: '${upstream.name}/${state.framework.candidateBranch}', upstreamRemote: upstream, previousCheckoutLocation: state.framework.checkoutPath, ); diff --git a/dev/conductor/lib/proto/conductor_state.pb.dart b/dev/conductor/lib/proto/conductor_state.pb.dart index 7da9b37e4c..1ab4e96b1a 100644 --- a/dev/conductor/lib/proto/conductor_state.pb.dart +++ b/dev/conductor/lib/proto/conductor_state.pb.dart @@ -403,6 +403,8 @@ class ConductorState extends $pb.GeneratedMessage { enumValues: ReleasePhase.values) ..aOS(10, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'conductorVersion', protoName: 'conductorVersion') + ..aOS(11, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'incrementLevel', + protoName: 'incrementLevel') ..hasRequiredFields = false; ConductorState._() : super(); @@ -416,6 +418,7 @@ class ConductorState extends $pb.GeneratedMessage { $core.Iterable<$core.String>? logs, ReleasePhase? currentPhase, $core.String? conductorVersion, + $core.String? incrementLevel, }) { final _result = create(); if (releaseChannel != null) { @@ -445,6 +448,9 @@ class ConductorState extends $pb.GeneratedMessage { if (conductorVersion != null) { _result.conductorVersion = conductorVersion; } + if (incrementLevel != null) { + _result.incrementLevel = incrementLevel; + } return _result; } factory ConductorState.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => @@ -572,4 +578,16 @@ class ConductorState extends $pb.GeneratedMessage { $core.bool hasConductorVersion() => $_has(8); @$pb.TagNumber(10) void clearConductorVersion() => clearField(10); + + @$pb.TagNumber(11) + $core.String get incrementLevel => $_getSZ(9); + @$pb.TagNumber(11) + set incrementLevel($core.String v) { + $_setString(9, v); + } + + @$pb.TagNumber(11) + $core.bool hasIncrementLevel() => $_has(9); + @$pb.TagNumber(11) + void clearIncrementLevel() => clearField(11); } diff --git a/dev/conductor/lib/proto/conductor_state.pbjson.dart b/dev/conductor/lib/proto/conductor_state.pbjson.dart index 6f16e23da6..f35275d028 100644 --- a/dev/conductor/lib/proto/conductor_state.pbjson.dart +++ b/dev/conductor/lib/proto/conductor_state.pbjson.dart @@ -101,9 +101,10 @@ const ConductorState$json = const { const {'1': 'logs', '3': 8, '4': 3, '5': 9, '10': 'logs'}, const {'1': 'currentPhase', '3': 9, '4': 1, '5': 14, '6': '.conductor_state.ReleasePhase', '10': 'currentPhase'}, const {'1': 'conductorVersion', '3': 10, '4': 1, '5': 9, '10': 'conductorVersion'}, + const {'1': 'incrementLevel', '3': 11, '4': 1, '5': 9, '10': 'incrementLevel'}, ], }; /// Descriptor for `ConductorState`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List conductorStateDescriptor = $convert.base64Decode( - 'Cg5Db25kdWN0b3JTdGF0ZRImCg5yZWxlYXNlQ2hhbm5lbBgBIAEoCVIOcmVsZWFzZUNoYW5uZWwSJgoOcmVsZWFzZVZlcnNpb24YAiABKAlSDnJlbGVhc2VWZXJzaW9uEjMKBmVuZ2luZRgEIAEoCzIbLmNvbmR1Y3Rvcl9zdGF0ZS5SZXBvc2l0b3J5UgZlbmdpbmUSOQoJZnJhbWV3b3JrGAUgASgLMhsuY29uZHVjdG9yX3N0YXRlLlJlcG9zaXRvcnlSCWZyYW1ld29yaxIgCgtjcmVhdGVkRGF0ZRgGIAEoA1ILY3JlYXRlZERhdGUSKAoPbGFzdFVwZGF0ZWREYXRlGAcgASgDUg9sYXN0VXBkYXRlZERhdGUSEgoEbG9ncxgIIAMoCVIEbG9ncxJBCgxjdXJyZW50UGhhc2UYCSABKA4yHS5jb25kdWN0b3Jfc3RhdGUuUmVsZWFzZVBoYXNlUgxjdXJyZW50UGhhc2USKgoQY29uZHVjdG9yVmVyc2lvbhgKIAEoCVIQY29uZHVjdG9yVmVyc2lvbg=='); + 'Cg5Db25kdWN0b3JTdGF0ZRImCg5yZWxlYXNlQ2hhbm5lbBgBIAEoCVIOcmVsZWFzZUNoYW5uZWwSJgoOcmVsZWFzZVZlcnNpb24YAiABKAlSDnJlbGVhc2VWZXJzaW9uEjMKBmVuZ2luZRgEIAEoCzIbLmNvbmR1Y3Rvcl9zdGF0ZS5SZXBvc2l0b3J5UgZlbmdpbmUSOQoJZnJhbWV3b3JrGAUgASgLMhsuY29uZHVjdG9yX3N0YXRlLlJlcG9zaXRvcnlSCWZyYW1ld29yaxIgCgtjcmVhdGVkRGF0ZRgGIAEoA1ILY3JlYXRlZERhdGUSKAoPbGFzdFVwZGF0ZWREYXRlGAcgASgDUg9sYXN0VXBkYXRlZERhdGUSEgoEbG9ncxgIIAMoCVIEbG9ncxJBCgxjdXJyZW50UGhhc2UYCSABKA4yHS5jb25kdWN0b3Jfc3RhdGUuUmVsZWFzZVBoYXNlUgxjdXJyZW50UGhhc2USKgoQY29uZHVjdG9yVmVyc2lvbhgKIAEoCVIQY29uZHVjdG9yVmVyc2lvbhImCg5pbmNyZW1lbnRMZXZlbBgLIAEoCVIOaW5jcmVtZW50TGV2ZWw='); diff --git a/dev/conductor/lib/proto/conductor_state.proto b/dev/conductor/lib/proto/conductor_state.proto index 126f9c7060..228bfa13f0 100644 --- a/dev/conductor/lib/proto/conductor_state.proto +++ b/dev/conductor/lib/proto/conductor_state.proto @@ -111,4 +111,7 @@ message ConductorState { // Commit hash of the Conductor tool. string conductorVersion = 10; + + // One of x, y, z, m, or n. + string incrementLevel = 11; } diff --git a/dev/conductor/lib/repository.dart b/dev/conductor/lib/repository.dart index 3a12a4d739..07aeab476f 100644 --- a/dev/conductor/lib/repository.dart +++ b/dev/conductor/lib/repository.dart @@ -74,8 +74,10 @@ abstract class Repository { 'Fetch ${upstreamRemote.name} to ensure we have latest refs', workingDirectory: _checkoutDirectory!.path, ); + // Note: if [initialRef] is a remote ref the checkout will be left in a + // detached HEAD state. git.run( - ['checkout', '${upstreamRemote.name}/$initialRef'], + ['checkout', initialRef!], 'Checking out initialRef $initialRef', workingDirectory: _checkoutDirectory!.path, ); diff --git a/dev/conductor/lib/start.dart b/dev/conductor/lib/start.dart index 932fd9bdfc..b22f790485 100644 --- a/dev/conductor/lib/start.dart +++ b/dev/conductor/lib/start.dart @@ -213,6 +213,7 @@ class StartCommand extends Command { state.releaseChannel = releaseChannel; state.createdDate = unixDate; state.lastUpdatedDate = unixDate; + state.incrementLevel = incrementLetter; final EngineRepository engine = EngineRepository( checkouts, diff --git a/dev/conductor/lib/state.dart b/dev/conductor/lib/state.dart index eb97d1a4a4..c8167ac9d0 100644 --- a/dev/conductor/lib/state.dart +++ b/dev/conductor/lib/state.dart @@ -43,10 +43,8 @@ String presentState(pb.ConductorState state) { buffer.writeln('Release channel: ${state.releaseChannel}'); buffer.writeln('Release version: ${state.releaseVersion}'); buffer.writeln(''); - buffer.writeln( - 'Release started at: ${DateTime.fromMillisecondsSinceEpoch(state.createdDate.toInt())}'); - buffer.writeln( - 'Last updated at: ${DateTime.fromMillisecondsSinceEpoch(state.lastUpdatedDate.toInt())}'); + buffer.writeln('Release started at: ${DateTime.fromMillisecondsSinceEpoch(state.createdDate.toInt())}'); + buffer.writeln('Last updated at: ${DateTime.fromMillisecondsSinceEpoch(state.lastUpdatedDate.toInt())}'); buffer.writeln(''); buffer.writeln('Engine Repo'); buffer.writeln('\tCandidate branch: ${state.engine.candidateBranch}'); @@ -128,15 +126,27 @@ String phaseInstructions(pb.ConductorState state) { return [ 'You must now manually apply the following engine cherrypicks to the checkout', 'at ${state.engine.checkoutPath} in order:', - for (final pb.Cherrypick cherrypick in state.engine.cherrypicks) - '\t${cherrypick.trunkRevision}', + for (final pb.Cherrypick cherrypick in state.engine.cherrypicks) '\t${cherrypick.trunkRevision}', 'See $kReleaseDocumentationUrl for more information.', ].join('\n'); case ReleasePhase.CODESIGN_ENGINE_BINARIES: + if (!requiresEnginePR(state)) { + return 'You must now codesign the engine binaries for commit ' + '${state.engine.startingGitHead}.'; + } + // User's working branch was pushed to their mirror, but a PR needs to be + // opened on GitHub. + final String newPrLink = getNewPrLink( + userName: githubAccount(state.engine.mirror.url), + repoName: 'engine', + candidateBranch: state.engine.candidateBranch, + workingBranch: state.engine.workingBranch, + ); return [ - 'You must verify pre-submit CI builds on your engine pull request are successful,', - 'merge your pull request, validate post-submit CI, and then codesign the binaries ', - 'on the merge commit.', + 'Your working branch ${state.engine.workingBranch} was pushed to your mirror.', + 'You must now open a pull request at $newPrLink, verify pre-submit CI', + 'builds on your engine pull request are successful, merge your pull request,', + 'validate post-submit CI, and then codesign the binaries on the merge commit.', ].join('\n'); case ReleasePhase.APPLY_FRAMEWORK_CHERRYPICKS: final List outstandingCherrypicks = state.framework.cherrypicks.where( @@ -144,17 +154,31 @@ String phaseInstructions(pb.ConductorState state) { return cp.state == pb.CherrypickState.PENDING || cp.state == pb.CherrypickState.PENDING_WITH_CONFLICT; }, ).toList(); - return [ - 'You must now manually apply the following framework cherrypicks to the checkout', - 'at ${state.framework.checkoutPath} in order:', - for (final pb.Cherrypick cherrypick in outstandingCherrypicks) - '\t${cherrypick.trunkRevision}', - ].join('\n'); + if (outstandingCherrypicks.isNotEmpty) { + return [ + 'You must now manually apply the following framework cherrypicks to the checkout', + 'at ${state.framework.checkoutPath} in order:', + for (final pb.Cherrypick cherrypick in outstandingCherrypicks) '\t${cherrypick.trunkRevision}', + ].join('\n'); + } + return ['Either all cherrypicks have been auto-applied or there were none.'].join('\n'); case ReleasePhase.PUBLISH_VERSION: + if (!requiresFrameworkPR(state)) { + return 'Since there are no code changes in this release, no Framework ' + 'PR is necessary.'; + } + + final String newPrLink = getNewPrLink( + userName: githubAccount(state.framework.mirror.url), + repoName: 'framework', + candidateBranch: state.framework.candidateBranch, + workingBranch: state.framework.workingBranch, + ); return [ - 'You must verify pre-submit CI builds on your framework pull request are successful,', - 'merge your pull request, and validate post-submit CI. See $kReleaseDocumentationUrl,', - 'for more information.', + 'Your working branch ${state.framework.workingBranch} was pushed to your mirror.', + 'You must now open a pull request at $newPrLink', + 'verify pre-submit CI builds on your pull request are successful, merge your ', + 'pull request, validate post-submit CI.', ].join('\n'); case ReleasePhase.PUBLISH_CHANNEL: return 'Issue `conductor next` to publish your release to the release branch.'; @@ -163,8 +187,36 @@ String phaseInstructions(pb.ConductorState state) { case ReleasePhase.RELEASE_COMPLETED: return 'This release has been completed.'; } - assert(false); - return ''; // For analyzer + // For analyzer + throw ConductorException('Unimplemented phase ${state.currentPhase}'); +} + +/// Regex pattern for git remote host URLs. +/// +/// First group = git host (currently must be github.com) +/// Second group = account name +/// Third group = repo name +final RegExp githubRemotePattern = + RegExp(r'^(git@github\.com:|https?:\/\/github\.com\/)([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+)(\.git)?$'); + +/// Parses a Git remote URL and returns the account name. +/// +/// Uses [githubRemotePattern]. +String githubAccount(String remoteUrl) { + final String engineUrl = remoteUrl; + final RegExpMatch? match = githubRemotePattern.firstMatch(engineUrl); + if (match == null) { + throw ConductorException( + 'Cannot determine the GitHub account from $engineUrl', + ); + } + final String? accountName = match.group(2); + if (accountName == null || accountName.isEmpty) { + throw ConductorException( + 'Cannot determine the GitHub account from $match', + ); + } + return accountName; } /// Returns the next phase in the ReleasePhase enum. @@ -196,3 +248,38 @@ pb.ConductorState readStateFromFile(File file) { ); return state; } + +/// This release will require a new Engine PR. +/// +/// The logic is if there are engine cherrypicks that have not been abandoned OR +/// there is a new Dart revision, then return true, else false. +bool requiresEnginePR(pb.ConductorState state) { + final bool hasRequiredCherrypicks = state.engine.cherrypicks.any( + (pb.Cherrypick cp) => cp.state != pb.CherrypickState.ABANDONED, + ); + if (hasRequiredCherrypicks) { + return true; + } + return state.engine.dartRevision.isNotEmpty; +} + +/// This release will require a new Framework PR. +/// +/// The logic is if there was an Engine PR OR there are framework cherrypicks +/// that have not been abandoned OR the increment level is 'm', then return +/// true, else false. +bool requiresFrameworkPR(pb.ConductorState state) { + if (requiresEnginePR(state)) { + return true; + } + final bool hasRequiredCherrypicks = + state.framework.cherrypicks.any((pb.Cherrypick cp) => cp.state != pb.CherrypickState.ABANDONED); + if (hasRequiredCherrypicks) { + return true; + } + if (state.incrementLevel == 'm') { + // requires an update to .ci.yaml + return true; + } + return false; +} diff --git a/dev/conductor/lib/stdio.dart b/dev/conductor/lib/stdio.dart index a909996599..90765115f0 100644 --- a/dev/conductor/lib/stdio.dart +++ b/dev/conductor/lib/stdio.dart @@ -46,10 +46,10 @@ class VerboseStdio extends Stdio { }); factory VerboseStdio.local() => VerboseStdio( - stdout: io.stdout, - stderr: io.stderr, - stdin: io.stdin, - ); + stdout: io.stdout, + stderr: io.stderr, + stdin: io.stdin, + ); final io.Stdout stdout; final io.Stdout stderr; diff --git a/dev/conductor/test/next_test.dart b/dev/conductor/test/next_test.dart index e991dc4e07..b519c38b20 100644 --- a/dev/conductor/test/next_test.dart +++ b/dev/conductor/test/next_test.dart @@ -89,6 +89,9 @@ void main() { ); final pb.ConductorState state = pb.ConductorState( currentPhase: ReleasePhase.APPLY_ENGINE_CHERRYPICKS, + engine: pb.Repository( + startingGitHead: revision1, + ), ); writeStateToFile( fileSystem.file(stateFile), @@ -116,10 +119,13 @@ void main() { expect(processManager, hasNoRemainingExpectations); expect(finalState.currentPhase, ReleasePhase.CODESIGN_ENGINE_BINARIES); expect(stdio.error, isEmpty); + expect( + stdio.stdout, + contains('You must now codesign the engine binaries for commit $revision1')); }); test('confirms to stdout when all engine cherrypicks were auto-applied', () async { - const String remoteUrl = 'https://githost.com/org/repo.git'; + const String remoteUrl = 'https://github.com/org/repo.git'; stdio.stdin.add('n'); final FakeProcessManager processManager = FakeProcessManager.empty(); final FakePlatform platform = FakePlatform( @@ -170,13 +176,14 @@ void main() { }); test('updates lastPhase if user responds yes', () async { - const String remoteUrl = 'https://githost.com/org/repo.git'; + const String remoteUrl = 'https://github.com/org/repo.git'; + const String releaseChannel = 'dev'; stdio.stdin.add('y'); final FakeProcessManager processManager = FakeProcessManager.list([ const FakeCommand( command: ['git', 'fetch', 'upstream'], ), - const FakeCommand(command: ['git', 'checkout', 'upstream/$workingBranch']), + const FakeCommand(command: ['git', 'checkout', workingBranch]), const FakeCommand( command: ['git', 'rev-parse', 'HEAD'], stdout: revision1, @@ -191,7 +198,9 @@ void main() { pathSeparator: localPathSeparator, ); final pb.ConductorState state = pb.ConductorState( + currentPhase: ReleasePhase.APPLY_ENGINE_CHERRYPICKS, engine: pb.Repository( + candidateBranch: candidateBranch, cherrypicks: [ pb.Cherrypick( trunkRevision: 'abc123', @@ -202,7 +211,7 @@ void main() { upstream: pb.Remote(name: 'upstream', url: remoteUrl), mirror: pb.Remote(name: 'mirror', url: remoteUrl), ), - currentPhase: ReleasePhase.APPLY_ENGINE_CHERRYPICKS, + releaseChannel: releaseChannel, ); writeStateToFile( fileSystem.file(stateFile), @@ -228,6 +237,9 @@ void main() { ); expect(processManager, hasNoRemainingExpectations); + expect( + stdio.stdout, + contains('You must now open a pull request at https://github.com/flutter/engine/compare/flutter-1.2-candidate.3...org:cherrypicks-flutter-1.2-candidate.3?expand=1')); expect(stdio.stdout, contains( 'Are you ready to push your engine branch to the repository $remoteUrl? (y/n) ')); expect(finalState.currentPhase, ReleasePhase.CODESIGN_ENGINE_BINARIES); @@ -332,9 +344,9 @@ void main() { }); group('APPLY_FRAMEWORK_CHERRYPICKS to PUBLISH_VERSION', () { - const String mirrorRemoteUrl = 'https://githost.com/org/repo.git'; - const String upstreamRemoteUrl = 'https://githost.com/mirror/repo.git'; - const String engineUpstreamRemoteUrl = 'https://githost.com/mirror/engine.git'; + const String mirrorRemoteUrl = 'https://github.com/org/repo.git'; + const String upstreamRemoteUrl = 'https://github.com/mirror/repo.git'; + const String engineUpstreamRemoteUrl = 'https://github.com/mirror/engine.git'; const String frameworkCheckoutPath = '$checkoutsParentDirectory/framework'; const String engineCheckoutPath = '$checkoutsParentDirectory/engine'; const String oldEngineVersion = '000000001'; @@ -441,13 +453,14 @@ void main() { stdio.stdin.add('n'); processManager.addCommands(const [ FakeCommand(command: ['git', 'fetch', 'upstream']), + // we want merged upstream commit, not local working commit FakeCommand(command: ['git', 'checkout', 'upstream/$candidateBranch']), FakeCommand( command: ['git', 'rev-parse', 'HEAD'], stdout: revision1, ), FakeCommand(command: ['git', 'fetch', 'upstream']), - FakeCommand(command: ['git', 'checkout', 'upstream/$workingBranch']), + FakeCommand(command: ['git', 'checkout', workingBranch]), FakeCommand( command: ['git', 'rev-parse', 'HEAD'], stdout: revision2, @@ -509,13 +522,14 @@ void main() { stdio.stdin.add('n'); processManager.addCommands(const [ FakeCommand(command: ['git', 'fetch', 'upstream']), + // we want merged upstream commit, not local working commit FakeCommand(command: ['git', 'checkout', 'upstream/$candidateBranch']), FakeCommand( command: ['git', 'rev-parse', 'HEAD'], stdout: revision1, ), FakeCommand(command: ['git', 'fetch', 'upstream']), - FakeCommand(command: ['git', 'checkout', 'upstream/$workingBranch']), + FakeCommand(command: ['git', 'checkout', workingBranch]), FakeCommand( command: ['git', 'rev-parse', 'HEAD'], stdout: revision2, @@ -564,6 +578,7 @@ void main() { processManager.addCommands(const [ // Engine repo FakeCommand(command: ['git', 'fetch', 'upstream']), + // we want merged upstream commit, not local working commit FakeCommand(command: ['git', 'checkout', 'upstream/$candidateBranch']), FakeCommand( command: ['git', 'rev-parse', 'HEAD'], @@ -571,7 +586,7 @@ void main() { ), // Framework repo FakeCommand(command: ['git', 'fetch', 'upstream']), - FakeCommand(command: ['git', 'checkout', 'upstream/$workingBranch']), + FakeCommand(command: ['git', 'checkout', workingBranch]), FakeCommand( command: ['git', 'rev-parse', 'HEAD'], stdout: revision2, diff --git a/dev/conductor/test/start_test.dart b/dev/conductor/test/start_test.dart index 1eb2826200..24937d4bda 100644 --- a/dev/conductor/test/start_test.dart +++ b/dev/conductor/test/start_test.dart @@ -115,6 +115,7 @@ void main() { const String nextDartRevision = 'f6c91128be6b77aef8351e1e3a9d07c85bc2e46e'; const String previousVersion = '1.2.0-1.0.pre'; const String nextVersion = '1.2.0-3.0.pre'; + const String incrementLevel = 'm'; final Directory engine = fileSystem.directory(checkoutsParentDirectory) .childDirectory('flutter_conductor_checkouts') @@ -261,7 +262,7 @@ void main() { '--$kDartRevisionOption', nextDartRevision, '--$kIncrementOption', - 'm', + incrementLevel, ]); final File stateFile = fileSystem.file(stateFilePath); @@ -281,6 +282,7 @@ void main() { expect(state.framework.startingGitHead, revision3); expect(state.currentPhase, ReleasePhase.APPLY_ENGINE_CHERRYPICKS); expect(state.conductorVersion, revision); + expect(state.incrementLevel, incrementLevel); }); }, onPlatform: { 'windows': const Skip('Flutter Conductor only supported on macos/linux'),