Skip to content

Commit

Permalink
Add update packages roller (flutter#100982)
Browse files Browse the repository at this point in the history
  • Loading branch information
christopherfujino authored Jun 23, 2022
1 parent 0dd0c2e commit a30012b
Show file tree
Hide file tree
Showing 12 changed files with 760 additions and 24 deletions.
1 change: 1 addition & 0 deletions dev/bots/analyze.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1778,6 +1778,7 @@ const Set<String> kExecutableAllowlist = <String>{
'dev/bots/docs.sh',

'dev/conductor/bin/conductor',
'dev/conductor/bin/roll-packages',
'dev/conductor/core/lib/src/proto/compile_proto.sh',

'dev/customer_testing/ci.sh',
Expand Down
2 changes: 1 addition & 1 deletion dev/conductor/bin/conductor
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ DART_BIN="$REPO_DIR/bin/dart"
# Ensure pub get has been run in the repo before running the conductor
(cd "$REPO_DIR/dev/conductor/core"; "$DART_BIN" pub get 1>&2)

"$DART_BIN" --enable-asserts "$REPO_DIR/dev/conductor/core/bin/cli.dart" "$@"
exec "$DART_BIN" --enable-asserts "$REPO_DIR/dev/conductor/core/bin/cli.dart" "$@"
46 changes: 46 additions & 0 deletions dev/conductor/bin/roll-packages
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# Copyright 2014 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

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"

# Ensure pub get has been run in the repo before running the conductor
(cd "$REPO_DIR/dev/conductor/core"; "$DART_BIN" pub get 1>&2)

exec "$DART_BIN" --enable-asserts "$REPO_DIR/dev/conductor/core/bin/roll_packages.dart" "$@"
128 changes: 128 additions & 0 deletions dev/conductor/core/bin/packages_autoroller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io' as io;

import 'package:args/args.dart';
import 'package:conductor_core/conductor_core.dart';
import 'package:conductor_core/packages_autoroller.dart';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:platform/platform.dart';
import 'package:process/process.dart';

const String kTokenOption = 'token';
const String kGithubClient = 'github-client';
const String kMirrorRemote = 'mirror-remote';
const String kUpstreamRemote = 'upstream-remote';

Future<void> main(List<String> args) async {
final ArgParser parser = ArgParser();
parser.addOption(
kTokenOption,
help: 'GitHub access token env variable name.',
defaultsTo: 'GITHUB_TOKEN',
);
parser.addOption(
kGithubClient,
help: 'Path to GitHub CLI client. If not provided, it is assumed `gh` is '
'present on the PATH.',
);
parser.addOption(
kMirrorRemote,
help: 'The mirror git remote that the feature branch will be pushed to. '
'Required',
mandatory: true,
);
parser.addOption(
kUpstreamRemote,
help: 'The upstream git remote that the feature branch will be merged to.',
hide: true,
defaultsTo: 'https://github.com/flutter/flutter.git',
);

final ArgResults results;
try {
results = parser.parse(args);
} on FormatException {
io.stdout.writeln('''
Usage:
${parser.usage}
''');
rethrow;
}

final String mirrorUrl = results[kMirrorRemote]! as String;
final String upstreamUrl = results[kUpstreamRemote]! as String;
const Platform platform = LocalPlatform();
final String tokenName = results[kTokenOption]! as String;
final String? token = platform.environment[tokenName];
if (token == null || token.isEmpty) {
throw FormatException(
'Tried to read a GitHub access token from env variable \$$tokenName but it was undefined or empty',
);
}

final FrameworkRepository framework = FrameworkRepository(
_localCheckouts,
mirrorRemote: Remote.mirror(mirrorUrl),
upstreamRemote: Remote.upstream(upstreamUrl),
);

await PackageAutoroller(
framework: framework,
githubClient: results[kGithubClient] as String? ?? 'gh',
orgName: _parseOrgName(mirrorUrl),
token: token,
processManager: const LocalProcessManager(),
).roll();
}

String _parseOrgName(String remoteUrl) {
final RegExp pattern = RegExp(r'^https:\/\/github\.com\/(.*)\/');
final RegExpMatch? match = pattern.firstMatch(remoteUrl);
if (match == null) {
throw FormatException(
'Malformed upstream URL "$remoteUrl", should start with "https://github.com/"',
);
}
return match.group(1)!;
}

Checkouts get _localCheckouts {
const FileSystem fileSystem = LocalFileSystem();
const ProcessManager processManager = LocalProcessManager();
const Platform platform = LocalPlatform();
final Stdio stdio = VerboseStdio(
stdout: io.stdout,
stderr: io.stderr,
stdin: io.stdin,
);
return Checkouts(
fileSystem: fileSystem,
parentDirectory: _localFlutterRoot.parent,
platform: platform,
processManager: processManager,
stdio: stdio,
);
}

Directory get _localFlutterRoot {
String filePath;
const FileSystem fileSystem = LocalFileSystem();
const Platform platform = LocalPlatform();

filePath = platform.script.toFilePath();
final String checkoutsDirname = fileSystem.path.normalize(
fileSystem.path.join(
fileSystem.path.dirname(filePath), // flutter/dev/conductor/core/bin
'..', // flutter/dev/conductor/core
'..', // flutter/dev/conductor
'..', // flutter/dev
'..', // flutter
),
);
return fileSystem.directory(checkoutsDirname);
}
5 changes: 5 additions & 0 deletions dev/conductor/core/lib/packages_autoroller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

export 'src/packages_autoroller.dart';
Loading

0 comments on commit a30012b

Please sign in to comment.