Unverified Commit 62d00c6d authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

Migrate flutter conductor out of dev/tools and into its own directory (#83313)

* Migrate flutter conductor out of dev/tools and into its own directory

* flesh out documentation

* fix analysis options

* fix integration test
parent 36eea758
...@@ -41,7 +41,7 @@ analyzer: ...@@ -41,7 +41,7 @@ analyzer:
exclude: exclude:
- "bin/cache/**" - "bin/cache/**"
# Ignore protoc generated files # Ignore protoc generated files
- "dev/tools/lib/proto/*" - "dev/conductor/lib/proto/*"
linter: linter:
rules: rules:
......
...@@ -707,7 +707,8 @@ Future<void> _runFrameworkTests() async { ...@@ -707,7 +707,8 @@ Future<void> _runFrameworkTests() async {
await _pubRunTest(path.join(flutterRoot, 'dev', 'bots')); await _pubRunTest(path.join(flutterRoot, 'dev', 'bots'));
await _pubRunTest(path.join(flutterRoot, 'dev', 'devicelab')); await _pubRunTest(path.join(flutterRoot, 'dev', 'devicelab'));
await _pubRunTest(path.join(flutterRoot, 'dev', 'snippets')); await _pubRunTest(path.join(flutterRoot, 'dev', 'snippets'));
await _pubRunTest(path.join(flutterRoot, 'dev', 'tools'), forceSingleCore: true); // TODO(fujino): Move this to its own test shard
await _pubRunTest(path.join(flutterRoot, 'dev', 'conductor'), forceSingleCore: true);
await _runFlutterTest(path.join(flutterRoot, 'dev', 'integration_tests', 'android_semantics_testing')); await _runFlutterTest(path.join(flutterRoot, 'dev', 'integration_tests', 'android_semantics_testing'));
await _runFlutterTest(path.join(flutterRoot, 'dev', 'manual_tests')); await _runFlutterTest(path.join(flutterRoot, 'dev', 'manual_tests'));
await _runFlutterTest(path.join(flutterRoot, 'dev', 'tools', 'vitool')); await _runFlutterTest(path.join(flutterRoot, 'dev', 'tools', 'vitool'));
......
# Flutter Conductor
Command-line tool for managing a release of the Flutter SDK.
## Requirements
Some basic requirements to conduct a release are:
- a Linux or macOS computer set up for Flutter development. The conductor does
not support Windows.
- git
- Mirrors on GitHub of the Flutter
[framework](https://github.com/flutter/flutter) and
[engine](https://github.com/flutter/engine) repositories.
## Usage
The main entrypoint for the conductor is [bin/conductor](bin/conductor). For
brevity, the rest of this document will assume that this entrypoint is on the
shell path.
All available commands can be seen via:
`conductor help`
Releases are initialized with the `start` sub-command, like:
```
conductor start \
--candidate-branch=flutter-2.2-candidate.10 \
--release-channel=beta \
--framework-mirror=git@github.com:flutter-contributor/flutter.git \
--engine-mirror=git@github.com:flutter-contributor/engine.git \
--engine-cherrypicks=72114dafe28c8700f1d5d629c6ae9d34172ba395 \
--framework-cherrypicks=a3e66b396746f6581b2b7efd1b0d0f0074215128,d8d853436206e86f416236b930e97779b143a100 \
--dart-revision=4511eb2a779a612d9d6b2012123575013e0aef12
```
For more details on these command line arguments, see `conductor help start`.
This command will write to disk a state file that will persist until the release
is completed. To see the current status of the release (at any time), issue the
command:
`conductor status`
Once initializing the release, the conductor tool will issue instructions for
manual steps that must be executed by the user. At any time these instructions
can be seen via `conductor status`. Once these manual steps have been completed,
you can proceed to the next step by using the command:
`conductor next`
Upon successful completion of the release, the following command will remove the
persistent state file:
`conductor clean`
#!/usr/bin/env bash
set -euo pipefail
# Needed because if it is set, cd may print the path it changed to.
unset CDPATH
# On Mac OS, readlink -f doesn't work, so follow_links traverses the path one
# link at a time, and then cds into the link destination and find out where it
# ends up.
#
# The returned filesystem path must be a format usable by Dart's URI parser,
# since the Dart command line tool treats its argument as a file URI, not a
# filename. For instance, multiple consecutive slashes should be reduced to a
# single slash, since double-slashes indicate a URI "authority", and these are
# supposed to be filenames. There is an edge case where this will return
# multiple slashes: when the input resolves to the root directory. However, if
# that were the case, we wouldn't be running this shell, so we don't do anything
# about it.
#
# The function is enclosed in a subshell to avoid changing the working directory
# of the caller.
function follow_links() (
cd -P "$(dirname -- "$1")"
file="$PWD/$(basename -- "$1")"
while [[ -h "$file" ]]; do
cd -P "$(dirname -- "$file")"
file="$(readlink -- "$file")"
cd -P "$(dirname -- "$file")"
file="$PWD/$(basename -- "$file")"
done
echo "$file"
)
PROG_NAME="$(follow_links "${BASH_SOURCE[0]}")"
BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
REPO_DIR="$BIN_DIR/../../.."
DART_BIN="$REPO_DIR/bin/dart"
"$DART_BIN" --enable-asserts "$REPO_DIR/dev/conductor/bin/conductor.dart" "$@"
...@@ -9,20 +9,22 @@ ...@@ -9,20 +9,22 @@
import 'dart:io' as io; import 'dart:io' as io;
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:dev_tools/candidates.dart'; import 'package:conductor/candidates.dart';
import 'package:dev_tools/clean.dart'; import 'package:conductor/clean.dart';
import 'package:dev_tools/codesign.dart'; import 'package:conductor/codesign.dart';
import 'package:dev_tools/globals.dart'; import 'package:conductor/globals.dart';
import 'package:dev_tools/repository.dart'; import 'package:conductor/repository.dart';
import 'package:dev_tools/roll_dev.dart'; import 'package:conductor/roll_dev.dart';
import 'package:dev_tools/start.dart'; import 'package:conductor/start.dart';
import 'package:dev_tools/status.dart'; import 'package:conductor/status.dart';
import 'package:dev_tools/stdio.dart'; import 'package:conductor/stdio.dart';
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/local.dart'; import 'package:file/local.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
const String readmeUrl = 'https://github.com/flutter/flutter/tree/master/dev/conductor/README.md';
Future<void> main(List<String> args) async { Future<void> main(List<String> args) async {
const FileSystem fileSystem = LocalFileSystem(); const FileSystem fileSystem = LocalFileSystem();
const ProcessManager processManager = LocalProcessManager(); const ProcessManager processManager = LocalProcessManager();
...@@ -42,7 +44,8 @@ Future<void> main(List<String> args) async { ...@@ -42,7 +44,8 @@ Future<void> main(List<String> args) async {
final CommandRunner<void> runner = CommandRunner<void>( final CommandRunner<void> runner = CommandRunner<void>(
'conductor', 'conductor',
'A tool for coordinating Flutter releases.', 'A tool for coordinating Flutter releases. For more documentation on '
'usage, please see $readmeUrl.',
usageLineLength: 80, usageLineLength: 80,
); );
......
...@@ -51,7 +51,7 @@ Directory get localFlutterRoot { ...@@ -51,7 +51,7 @@ Directory get localFlutterRoot {
// If a test // If a test
if (platform.script.scheme == 'data') { if (platform.script.scheme == 'data') {
final RegExp pattern = RegExp( final RegExp pattern = RegExp(
r'(file:\/\/[^"]*[/\\]dev\/tools[/\\][^"]+\.dart)', r'(file:\/\/[^"]*[/\\]dev\/conductor[/\\][^"]+\.dart)',
multiLine: true, multiLine: true,
); );
final Match? match = final Match? match =
......
name: conductor
description: Flutter Automated Release Tool
publish_to: none
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
archive: 3.1.2
args: 2.1.0
http: 0.13.3
intl: 0.17.0
meta: 1.3.0
path: 1.8.0
process: 4.2.1
protobuf: 1.1.3
async: 2.6.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
charcode: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
clock: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
collection: 1.15.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
crypto: 3.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
file: 6.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
fixnum: 0.10.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
http_parser: 4.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
pedantic: 1.11.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
platform: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
source_span: 1.8.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
string_scanner: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
term_glyph: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
dev_dependencies:
test: 1.16.8
test_api: 0.3.0
_fe_analyzer_shared: 21.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
analyzer: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
boolean_selector: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
cli_util: 0.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
convert: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
coverage: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
glob: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
http_multi_server: 3.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
io: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
js: 0.6.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
logging: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
matcher: 0.12.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
mime: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
node_preamble: 2.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
package_config: 2.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
pool: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
pub_semver: 2.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
shelf: 1.1.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
shelf_packages_handler: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
shelf_static: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
shelf_web_socket: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
source_map_stack_trace: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
source_maps: 0.10.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
stack_trace: 1.10.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
stream_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
test_core: 0.3.19 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
vm_service: 6.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
watcher: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
yaml: 3.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
# PUBSPEC CHECKSUM: 0007
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:dev_tools/candidates.dart'; import 'package:conductor/candidates.dart';
import 'package:dev_tools/repository.dart'; import 'package:conductor/repository.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
...@@ -147,7 +147,6 @@ void main() { ...@@ -147,7 +147,6 @@ void main() {
expect(stdio.stdout.contains(newBranch), true); expect(stdio.stdout.contains(newBranch), true);
expect(stdio.stdout.contains(oldBranch), false); expect(stdio.stdout.contains(oldBranch), false);
expect(stdio.stdout.contains(currentBranch), false); expect(stdio.stdout.contains(currentBranch), false);
print(stdio.stdout);
}); });
}, onPlatform: <String, dynamic>{ }, onPlatform: <String, dynamic>{
'windows': const Skip('Flutter Conductor only supported on macos/linux'), 'windows': const Skip('Flutter Conductor only supported on macos/linux'),
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
// @dart = 2.8 // @dart = 2.8
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:dev_tools/clean.dart'; import 'package:conductor/clean.dart';
import 'package:dev_tools/repository.dart'; import 'package:conductor/repository.dart';
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:dev_tools/codesign.dart' show CodesignCommand; import 'package:conductor/codesign.dart' show CodesignCommand;
import 'package:dev_tools/globals.dart'; import 'package:conductor/globals.dart';
import 'package:dev_tools/repository.dart' show Checkouts; import 'package:conductor/repository.dart' show Checkouts;
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/local.dart'; import 'package:file/local.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:dev_tools/codesign.dart'; import 'package:conductor/codesign.dart';
import 'package:dev_tools/globals.dart'; import 'package:conductor/globals.dart';
import 'package:dev_tools/repository.dart'; import 'package:conductor/repository.dart';
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
......
...@@ -4,26 +4,11 @@ ...@@ -4,26 +4,11 @@
import 'package:args/args.dart'; import 'package:args/args.dart';
import 'package:dev_tools/stdio.dart'; import 'package:conductor/stdio.dart';
import 'package:file/file.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
export 'package:test/test.dart' hide isInstanceOf; export 'package:test/test.dart' hide isInstanceOf;
/// A matcher that compares the type of the actual value to the type argument T.
TypeMatcher<T> isInstanceOf<T>() => isA<T>();
void tryToDelete(Directory directory) {
// This should not be necessary, but it turns out that
// on Windows it's common for deletions to fail due to
// bogus (we think) "access denied" errors.
try {
directory.deleteSync(recursive: true);
} on FileSystemException catch (error) {
print('Failed to delete ${directory.path}: $error');
}
}
Matcher throwsExceptionWith(String messageSubString) { Matcher throwsExceptionWith(String messageSubString) {
return throwsA( return throwsA(
isA<Exception>().having( isA<Exception>().having(
......
...@@ -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 'package:dev_tools/repository.dart'; import 'package:conductor/repository.dart';
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
// 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 'package:dev_tools/repository.dart'; import 'package:conductor/repository.dart';
import 'package:dev_tools/roll_dev.dart' show rollDev; import 'package:conductor/roll_dev.dart' show rollDev;
import 'package:dev_tools/version.dart'; import 'package:conductor/version.dart';
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/local.dart'; import 'package:file/local.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
// @dart = 2.8 // @dart = 2.8
import 'package:dev_tools/globals.dart'; import 'package:conductor/globals.dart';
import 'package:dev_tools/repository.dart'; import 'package:conductor/repository.dart';
import 'package:dev_tools/roll_dev.dart'; import 'package:conductor/roll_dev.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
......
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
import 'dart:convert' show jsonDecode; import 'dart:convert' show jsonDecode;
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:dev_tools/proto/conductor_state.pb.dart' as pb; import 'package:conductor/proto/conductor_state.pb.dart' as pb;
import 'package:dev_tools/proto/conductor_state.pbenum.dart' show ReleasePhase; import 'package:conductor/proto/conductor_state.pbenum.dart' show ReleasePhase;
import 'package:dev_tools/repository.dart'; import 'package:conductor/repository.dart';
import 'package:dev_tools/start.dart'; import 'package:conductor/start.dart';
import 'package:dev_tools/state.dart'; import 'package:conductor/state.dart';
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
......
...@@ -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 'package:dev_tools/version.dart'; import 'package:conductor/version.dart';
import './common.dart'; import './common.dart';
......
...@@ -34,6 +34,7 @@ function follow_links() ( ...@@ -34,6 +34,7 @@ function follow_links() (
PROG_NAME="$(follow_links "${BASH_SOURCE[0]}")" PROG_NAME="$(follow_links "${BASH_SOURCE[0]}")"
BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)" BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
DART_BIN="$BIN_DIR/../../../bin/dart" REPO_DIR="$BIN_DIR/../../.."
DART_BIN="$REPO_DIR/bin/dart"
"$DART_BIN" --enable-asserts "$BIN_DIR/conductor.dart" "$@" "$DART_BIN" --enable-asserts "$REPO_DIR/dev/conductor/bin/conductor.dart" "$@"
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