blob: 9f562489188c8aa3076f255f6c1e1edfb3f12216 [file] [log] [blame]
#!/usr/bin/env dart
// Copyright 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// Updates the CIPD packages used for browser testing on Luci.
import 'dart:async';
import 'dart:io' as io;
import 'package:args/args.dart';
import 'package:deps/browsers/chrome.dart';
import 'package:deps/browsers/firefox.dart';
import 'package:deps/package.dart';
import 'package:deps/provenance.dart';
import 'package:file/local.dart';
import 'package:io/io.dart';
import 'package:logging/logging.dart';
const platforms = {
'chrome': {
'linux-amd64': 'linux64',
'mac-amd64': 'mac64',
'mac-arm64': 'mac-arm64',
'windows-amd64': 'win64-clang'
'firefox': {'linux-amd64': 'linux-x86_64', 'windows-amd64': 'win64'},
const chromedriverPlatforms = {
'linux-amd64': 'linux64',
'mac-amd64': 'mac64',
'mac-arm64': 'mac64_m1',
'windows-amd64': 'win32'
void main(List<String> args) async {
final options = _parse(args);
if (options['verbose'] == true) {
Logger.root.level = Level.ALL;
} else {
Logger.root.level = Level.WARNING;
Logger.root.onRecord.listen((record) {
print('${} (${record.time}): ${record.message}');
final isDryRun = options['dry-run'];
final version = options['version'];
final browser = options['browser'];
final provenance = options['provenance'];
final temp = await LocalFileSystem().systemTempDirectory.createTemp();
// TODO: Restructure to download and upload all the packages in phases.
if (provenance) {
await provenanceReportStage('compile');
await provenanceReportStage('upload');
Future<void> updateFirefox(String platform, String os) async {
await FirefoxPackage(platform, os, version).create(temp, provenance);
Future<void> updateChrome(String platform, String os) async {
await ChromeDriverPackage(platform, version).create(temp, provenance);
await ChromePackage(platform, version).create(temp, provenance);
final update = {
'chrome': updateChrome,
'firefox': updateFirefox,
try {
await dryRun(() async {
for (final entry in platforms[browser]!.entries) {
await update(entry.key, entry.value);
}, isDryRun);
} on FormatException catch (e) {
io.exitCode =;
} on StateError catch (e) {
io.exitCode = ExitCode.config.code;
} on io.IOException catch (e) {
io.exitCode = ExitCode.ioError.code;
} finally {
await temp.delete(recursive: true);
if (provenance) {
await provenanceReportStage('upload-complete');
ArgResults _parse(List<String> args) {
final parser = ArgParser();
abbr: 'b',
allowed: ['chrome', 'firefox'],
help: 'Which browser to update.');
parser.addOption('version', abbr: 'V', help: '''
The version of the browser to update to.
For Firefox, specify the candidate build number with "+": 67.0.4+1''');
abbr: 'v', help: 'Produce verbose output.', negatable: false);
parser.addFlag('help', help: 'Show the program usage.', negatable: false);
abbr: 'n', help: 'Run without creating packages', negatable: false);
abbr: 'p', help: 'Attach provenance to the packages', negatable: false);
final options = parser.parse(args);
if (options['help'] ||
options['browser'] == null ||
options['version'] == null) {
Usage: deps.dart --browser=BROWSER --version=VERSION [OPTION...]
Downloads the version of BROWSER and re-packages and uploads it as a CIPD
package. Update the test_matrix.json to use the new version.
The options are as follows:
io.exit(options['help'] ? 0 : 1);
return options;