mirror of
https://github.com/flutter/flutter
synced 2024-08-27 20:10:11 +00:00
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
This commit is contained in:
parent
36eea758ac
commit
62d00c6d5f
|
@ -41,7 +41,7 @@ analyzer:
|
|||
exclude:
|
||||
- "bin/cache/**"
|
||||
# Ignore protoc generated files
|
||||
- "dev/tools/lib/proto/*"
|
||||
- "dev/conductor/lib/proto/*"
|
||||
|
||||
linter:
|
||||
rules:
|
||||
|
|
|
@ -707,7 +707,8 @@ Future<void> _runFrameworkTests() async {
|
|||
await _pubRunTest(path.join(flutterRoot, 'dev', 'bots'));
|
||||
await _pubRunTest(path.join(flutterRoot, 'dev', 'devicelab'));
|
||||
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', 'manual_tests'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'dev', 'tools', 'vitool'));
|
||||
|
|
56
dev/conductor/README.md
Normal file
56
dev/conductor/README.md
Normal file
|
@ -0,0 +1,56 @@
|
|||
# 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`
|
40
dev/conductor/bin/conductor
Executable file
40
dev/conductor/bin/conductor
Executable file
|
@ -0,0 +1,40 @@
|
|||
#!/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 @@
|
|||
import 'dart:io' as io;
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:dev_tools/candidates.dart';
|
||||
import 'package:dev_tools/clean.dart';
|
||||
import 'package:dev_tools/codesign.dart';
|
||||
import 'package:dev_tools/globals.dart';
|
||||
import 'package:dev_tools/repository.dart';
|
||||
import 'package:dev_tools/roll_dev.dart';
|
||||
import 'package:dev_tools/start.dart';
|
||||
import 'package:dev_tools/status.dart';
|
||||
import 'package:dev_tools/stdio.dart';
|
||||
import 'package:conductor/candidates.dart';
|
||||
import 'package:conductor/clean.dart';
|
||||
import 'package:conductor/codesign.dart';
|
||||
import 'package:conductor/globals.dart';
|
||||
import 'package:conductor/repository.dart';
|
||||
import 'package:conductor/roll_dev.dart';
|
||||
import 'package:conductor/start.dart';
|
||||
import 'package:conductor/status.dart';
|
||||
import 'package:conductor/stdio.dart';
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/local.dart';
|
||||
import 'package:platform/platform.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 {
|
||||
const FileSystem fileSystem = LocalFileSystem();
|
||||
const ProcessManager processManager = LocalProcessManager();
|
||||
|
@ -42,7 +44,8 @@ Future<void> main(List<String> args) async {
|
|||
|
||||
final CommandRunner<void> runner = CommandRunner<void>(
|
||||
'conductor',
|
||||
'A tool for coordinating Flutter releases.',
|
||||
'A tool for coordinating Flutter releases. For more documentation on '
|
||||
'usage, please see $readmeUrl.',
|
||||
usageLineLength: 80,
|
||||
);
|
||||
|
|
@ -51,7 +51,7 @@ Directory get localFlutterRoot {
|
|||
// If a test
|
||||
if (platform.script.scheme == 'data') {
|
||||
final RegExp pattern = RegExp(
|
||||
r'(file:\/\/[^"]*[/\\]dev\/tools[/\\][^"]+\.dart)',
|
||||
r'(file:\/\/[^"]*[/\\]dev\/conductor[/\\][^"]+\.dart)',
|
||||
multiLine: true,
|
||||
);
|
||||
final Match? match =
|
70
dev/conductor/pubspec.yaml
Normal file
70
dev/conductor/pubspec.yaml
Normal file
|
@ -0,0 +1,70 @@
|
|||
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 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:dev_tools/candidates.dart';
|
||||
import 'package:dev_tools/repository.dart';
|
||||
import 'package:conductor/candidates.dart';
|
||||
import 'package:conductor/repository.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:platform/platform.dart';
|
||||
|
||||
|
@ -147,7 +147,6 @@ void main() {
|
|||
expect(stdio.stdout.contains(newBranch), true);
|
||||
expect(stdio.stdout.contains(oldBranch), false);
|
||||
expect(stdio.stdout.contains(currentBranch), false);
|
||||
print(stdio.stdout);
|
||||
});
|
||||
}, onPlatform: <String, dynamic>{
|
||||
'windows': const Skip('Flutter Conductor only supported on macos/linux'),
|
|
@ -5,8 +5,8 @@
|
|||
// @dart = 2.8
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:dev_tools/clean.dart';
|
||||
import 'package:dev_tools/repository.dart';
|
||||
import 'package:conductor/clean.dart';
|
||||
import 'package:conductor/repository.dart';
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:platform/platform.dart';
|
|
@ -3,9 +3,9 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:dev_tools/codesign.dart' show CodesignCommand;
|
||||
import 'package:dev_tools/globals.dart';
|
||||
import 'package:dev_tools/repository.dart' show Checkouts;
|
||||
import 'package:conductor/codesign.dart' show CodesignCommand;
|
||||
import 'package:conductor/globals.dart';
|
||||
import 'package:conductor/repository.dart' show Checkouts;
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/local.dart';
|
||||
import 'package:platform/platform.dart';
|
|
@ -3,9 +3,9 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:dev_tools/codesign.dart';
|
||||
import 'package:dev_tools/globals.dart';
|
||||
import 'package:dev_tools/repository.dart';
|
||||
import 'package:conductor/codesign.dart';
|
||||
import 'package:conductor/globals.dart';
|
||||
import 'package:conductor/repository.dart';
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:platform/platform.dart';
|
|
@ -4,26 +4,11 @@
|
|||
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:dev_tools/stdio.dart';
|
||||
import 'package:file/file.dart';
|
||||
import 'package:conductor/stdio.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
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) {
|
||||
return throwsA(
|
||||
isA<Exception>().having(
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:dev_tools/repository.dart';
|
||||
import 'package:conductor/repository.dart';
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:platform/platform.dart';
|
|
@ -2,9 +2,9 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:dev_tools/repository.dart';
|
||||
import 'package:dev_tools/roll_dev.dart' show rollDev;
|
||||
import 'package:dev_tools/version.dart';
|
||||
import 'package:conductor/repository.dart';
|
||||
import 'package:conductor/roll_dev.dart' show rollDev;
|
||||
import 'package:conductor/version.dart';
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/local.dart';
|
||||
import 'package:platform/platform.dart';
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:dev_tools/globals.dart';
|
||||
import 'package:dev_tools/repository.dart';
|
||||
import 'package:dev_tools/roll_dev.dart';
|
||||
import 'package:conductor/globals.dart';
|
||||
import 'package:conductor/repository.dart';
|
||||
import 'package:conductor/roll_dev.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:platform/platform.dart';
|
||||
|
|
@ -7,11 +7,11 @@
|
|||
import 'dart:convert' show jsonDecode;
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:dev_tools/proto/conductor_state.pb.dart' as pb;
|
||||
import 'package:dev_tools/proto/conductor_state.pbenum.dart' show ReleasePhase;
|
||||
import 'package:dev_tools/repository.dart';
|
||||
import 'package:dev_tools/start.dart';
|
||||
import 'package:dev_tools/state.dart';
|
||||
import 'package:conductor/proto/conductor_state.pb.dart' as pb;
|
||||
import 'package:conductor/proto/conductor_state.pbenum.dart' show ReleasePhase;
|
||||
import 'package:conductor/repository.dart';
|
||||
import 'package:conductor/start.dart';
|
||||
import 'package:conductor/state.dart';
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:platform/platform.dart';
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:dev_tools/version.dart';
|
||||
import 'package:conductor/version.dart';
|
||||
|
||||
import './common.dart';
|
||||
|
|
@ -34,6 +34,7 @@ function follow_links() (
|
|||
|
||||
PROG_NAME="$(follow_links "${BASH_SOURCE[0]}")"
|
||||
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" "$@"
|
||||
|
|
Loading…
Reference in a new issue