diff --git a/lib/web_ui/README.md b/lib/web_ui/README.md index 720e43ccc255f..f43528e2d9db6 100644 --- a/lib/web_ui/README.md +++ b/lib/web_ui/README.md @@ -147,6 +147,12 @@ is needed, follow these steps to roll the new version: If you have questions, contact the Flutter Web team on Flutter Discord on the \#hackers-web-🌍 channel. +#### Firefox + +We test with Firefox on LUCI in the Linux Web Engine builder. The process for +rolling Firefox is even easier than Chromium. Simply update `browser_lock.yaml` +with the latest version of Firefox, and run `browser_roller.dart`. + ##### **browser_roller.dart** The script has the following command-line options: @@ -164,7 +170,7 @@ The script has the following command-line options: In general, the manual process goes like this: -1. Dowload the binaries for the new browser/driver for each operaing system +1. Dowload the binaries for the new browser/driver for each operating system (macOS, linux, windows). 2. Create CIPD packages for these packages (more documentation is available for Googlers at go/cipd-flutter-web) diff --git a/lib/web_ui/dev/browser_lock.yaml b/lib/web_ui/dev/browser_lock.yaml index 38e3e65b7340a..5666ba8df3f92 100644 --- a/lib/web_ui/dev/browser_lock.yaml +++ b/lib/web_ui/dev/browser_lock.yaml @@ -19,8 +19,6 @@ chrome: Win: 1047731 version: '107.0' # CIPD tag for the above Build IDs. Normally "ChromeMajorVersion.UploadAttempt". ;) -## Firefox does not use CIPD. To update the version, simply update it in this -## file. firefox: version: '83.0' diff --git a/lib/web_ui/dev/browser_roller.dart b/lib/web_ui/dev/browser_roller.dart index 58b6a515a73c3..d31db9a0256f0 100644 --- a/lib/web_ui/dev/browser_roller.dart +++ b/lib/web_ui/dev/browser_roller.dart @@ -118,6 +118,10 @@ class _BrowserRoller { for (final _Platform platform in _platforms) { await _rollChromium(platform); await _rollChromeDriver(platform); + // For now, we only test Firefox on Linux. + if (platform.os == 'linux') { + await _rollFirefox(platform); + } } if (dryRun) { print('\nDry Run Done!\nNon-published roll artifacts kept here: ${_rollDir.path}\n'); @@ -163,6 +167,22 @@ data: '''; } + // Returns the contents for the CIPD config required to publish a new Firefox package. + String _getCipdFirefoxConfig({ + required String package, + required String majorVersion, + required String root, + }) { + return ''' +package: $package +description: Firefox $majorVersion used for testing +preserve_writable: true +root: $root +data: + - dir: . +'''; + } + // Download a file from the internet, and put it in a temporary location. Future _downloadTemporaryFile(String url) async { // Use the hash of the Url to temporarily store a file under tmp @@ -193,6 +213,26 @@ data: await zipFile.delete(); } + // Uncompresses a `file` into a `destination` Directory (must exist). + Future _uncompressAndDeleteFile(io.File tarFile, io.Directory destination) async { + vprint(' Uncompressing [${tarFile.path}] into [$destination]'); + final io.ProcessResult unzipResult = await io.Process.run('tar', [ + '-x', + '-f', + tarFile.path, + '-C', + destination.path, + ]); + + if (unzipResult.exitCode != 0) { + throw StateError( + 'Failed to unzip the downloaded archive ${tarFile.path}.\n' + 'The unzip process exited with code ${unzipResult.exitCode}.'); + } + vprint(' Deleting [${tarFile.path}]'); + await tarFile.delete(); + } + // Write String `contents` to a file in `path`. // // This is used to write CIPD config files to disk. @@ -366,4 +406,43 @@ data: // Run CIPD await _uploadToCipd(config: cipdConfigFile, version: majorVersion, buildId: chromeBuild); } + + + // Downloads Firefox from the internet, packs it in the directory structure + // that the LUCI script wants. The result of this will be then uploaded to CIPD. + Future _rollFirefox(_Platform platform) async { + final String version = _lock.firefoxLock.version; + final String url = platform.binding.getFirefoxDownloadUrl(version); + final String cipdPackageName = 'flutter_internal/browsers/firefox/${platform.name}'; + final io.Directory platformDir = io.Directory(path.join(_rollDir.path, platform.name)); + print('\nRolling Firefox for ${platform.name} (version:$version)'); + // Bail out if CIPD already has version:$majorVersion for this package! + if (!dryRun && await _cipdKnowsPackageVersion(package: cipdPackageName, versionTag: version)) { + print(' Skipping $cipdPackageName version:$version. Already uploaded to CIPD!'); + vprint(' Update browser_lock.yaml and use a different version value.'); + return; + } + + await platformDir.create(recursive: true); + vprint(' Created target directory [${platformDir.path}]'); + + final io.File firefoxDownload = await _downloadTemporaryFile(url); + + await _uncompressAndDeleteFile(firefoxDownload, platformDir); + + final io.Directory? actualContentRoot = await _locateContentRoot(platformDir); + assert(actualContentRoot != null); + final String relativePlatformDirPath = path.relative(actualContentRoot!.path, from: _rollDir.path); + + // Create the config manifest to upload to CIPD + final io.File cipdConfigFile = await _writeFile( + path.join(_rollDir.path, 'cipd.firefox.${platform.name}.yaml'), + _getCipdFirefoxConfig( + package: cipdPackageName, + majorVersion: version, + root: relativePlatformDirPath, + )); + // Run CIPD + await _uploadToCipd(config: cipdConfigFile, version: version, buildId: version); + } } diff --git a/lib/web_ui/dev/chrome.dart b/lib/web_ui/dev/chrome.dart index be7667ab8e5e6..8bae9250d4ccf 100644 --- a/lib/web_ui/dev/chrome.dart +++ b/lib/web_ui/dev/chrome.dart @@ -40,7 +40,7 @@ class ChromeEnvironment implements BrowserEnvironment { final String version = browserLock.chromeLock.versionForCurrentPlatform; _installation = await getOrInstallChrome( version, - infoLog: isCirrus ? stdout : DevNull(), + infoLog: isCi ? stdout : DevNull(), ); } diff --git a/lib/web_ui/dev/firefox.dart b/lib/web_ui/dev/firefox.dart index 48772f59cd857..57893c7bcbc4b 100644 --- a/lib/web_ui/dev/firefox.dart +++ b/lib/web_ui/dev/firefox.dart @@ -32,7 +32,7 @@ class FirefoxEnvironment implements BrowserEnvironment { Future prepare() async { _installation = await getOrInstallFirefox( browserLock.firefoxLock.version, - infoLog: isCirrus ? stdout : DevNull(), + infoLog: isCi ? stdout : DevNull(), ); }