Unverified Commit 40877c02 authored by godofredoc's avatar godofredoc Committed by GitHub

Update prepare_package to upload artifacts to old and new buckets. (#75389)

* Update prepare_package to upload to old and new infra buckets.

Bug: https://github.com/flutter/flutter/issues/75363

* Fix failing tests.

* Add duplicated code to a loop.
parent c0ea3bc5
...@@ -17,12 +17,15 @@ import 'package:process/process.dart'; ...@@ -17,12 +17,15 @@ import 'package:process/process.dart';
const String chromiumRepo = 'https://chromium.googlesource.com/external/github.com/flutter/flutter'; const String chromiumRepo = 'https://chromium.googlesource.com/external/github.com/flutter/flutter';
const String githubRepo = 'https://github.com/flutter/flutter.git'; const String githubRepo = 'https://github.com/flutter/flutter.git';
const String mingitForWindowsUrl = 'https://storage.googleapis.com/flutter_infra/mingit/' const String mingitForWindowsUrl = 'https://storage.googleapis.com/flutter_infra_release/mingit/'
'603511c649b00bbef0a6122a827ac419b656bc19/mingit.zip'; '603511c649b00bbef0a6122a827ac419b656bc19/mingit.zip';
const String gsBase = 'gs://flutter_infra'; const String oldGsBase = 'gs://flutter_infra';
const String releaseFolder = '/releases'; const String releaseFolder = '/releases';
const String gsReleaseFolder = '$gsBase$releaseFolder'; const String oldGsReleaseFolder = '$oldGsBase$releaseFolder';
const String baseUrl = 'https://storage.googleapis.com/flutter_infra'; const String oldBaseUrl = 'https://storage.googleapis.com/flutter_infra';
const String newGsBase = 'gs://flutter_infra_release';
const String newGsReleaseFolder = '$newGsBase$releaseFolder';
const String newBaseUrl = 'https://storage.googleapis.com/flutter_infra_release';
/// Exception class for when a process fails to run, so we can catch /// Exception class for when a process fails to run, so we can catch
/// it and provide something more readable than a stack trace. /// it and provide something more readable than a stack trace.
...@@ -470,13 +473,14 @@ class ArchivePublisher { ...@@ -470,13 +473,14 @@ class ArchivePublisher {
this.revision, this.revision,
this.branch, this.branch,
this.version, this.version,
this.outputFile, { this.outputFile,
this.dryRun, {
ProcessManager processManager, ProcessManager processManager,
bool subprocessOutput = true, bool subprocessOutput = true,
this.platform = const LocalPlatform(), this.platform = const LocalPlatform(),
}) : assert(revision.length == 40), }) : assert(revision.length == 40),
platformName = platform.operatingSystem.toLowerCase(), platformName = platform.operatingSystem.toLowerCase(),
metadataGsPath = '$gsReleaseFolder/${getMetadataFilename(platform)}', metadataGsPath = '$newGsReleaseFolder/${getMetadataFilename(platform)}',
_processRunner = ProcessRunner( _processRunner = ProcessRunner(
processManager: processManager, processManager: processManager,
subprocessOutput: subprocessOutput, subprocessOutput: subprocessOutput,
...@@ -491,6 +495,7 @@ class ArchivePublisher { ...@@ -491,6 +495,7 @@ class ArchivePublisher {
final Directory tempDir; final Directory tempDir;
final File outputFile; final File outputFile;
final ProcessRunner _processRunner; final ProcessRunner _processRunner;
final bool dryRun;
String get branchName => getBranchName(branch); String get branchName => getBranchName(branch);
String get destinationArchivePath => '$branchName/$platformName/${path.basename(outputFile.path)}'; String get destinationArchivePath => '$branchName/$platformName/${path.basename(outputFile.path)}';
static String getMetadataFilename(Platform platform) => 'releases_${platform.operatingSystem.toLowerCase()}.json'; static String getMetadataFilename(Platform platform) => 'releases_${platform.operatingSystem.toLowerCase()}.json';
...@@ -512,21 +517,24 @@ class ArchivePublisher { ...@@ -512,21 +517,24 @@ class ArchivePublisher {
/// This method will throw if the target archive already exists on cloud /// This method will throw if the target archive already exists on cloud
/// storage. /// storage.
Future<void> publishArchive([bool forceUpload = false]) async { Future<void> publishArchive([bool forceUpload = false]) async {
final String destGsPath = '$gsReleaseFolder/$destinationArchivePath'; for (final String releaseFolder in <String>[oldGsReleaseFolder, newGsReleaseFolder]) {
if (!forceUpload) { final String destGsPath = '$releaseFolder/$destinationArchivePath';
if (await _cloudPathExists(destGsPath)) { if (!forceUpload) {
throw PreparePackageException( if (await _cloudPathExists(destGsPath) && !dryRun) {
'File $destGsPath already exists on cloud storage!', throw PreparePackageException(
); 'File $destGsPath already exists on cloud storage!',
);
}
} }
await _cloudCopy(outputFile.absolute.path, destGsPath);
assert(tempDir.existsSync());
await _updateMetadata('$releaseFolder/${getMetadataFilename(platform)}', newBucket: false);
} }
await _cloudCopy(outputFile.absolute.path, destGsPath);
assert(tempDir.existsSync());
await _updateMetadata();
} }
Future<Map<String, dynamic>> _addRelease(Map<String, dynamic> jsonData) async { Future<Map<String, dynamic>> _addRelease(Map<String, dynamic> jsonData, {bool newBucket=true}) async {
jsonData['base_url'] = '$baseUrl$releaseFolder'; final String tmpBaseUrl = newBucket ? newBaseUrl : oldBaseUrl;
jsonData['base_url'] = '$tmpBaseUrl$releaseFolder';
if (!jsonData.containsKey('current_release')) { if (!jsonData.containsKey('current_release')) {
jsonData['current_release'] = <String, String>{}; jsonData['current_release'] = <String, String>{};
} }
...@@ -558,7 +566,7 @@ class ArchivePublisher { ...@@ -558,7 +566,7 @@ class ArchivePublisher {
return jsonData; return jsonData;
} }
Future<void> _updateMetadata() async { Future<void> _updateMetadata(String gsPath, {bool newBucket=true}) async {
// We can't just cat the metadata from the server with 'gsutil cat', because // We can't just cat the metadata from the server with 'gsutil cat', because
// Windows wants to echo the commands that execute in gsutil.bat to the // Windows wants to echo the commands that execute in gsutil.bat to the
// stdout when we do that. So, we copy the file locally and then read it // stdout when we do that. So, we copy the file locally and then read it
...@@ -566,24 +574,26 @@ class ArchivePublisher { ...@@ -566,24 +574,26 @@ class ArchivePublisher {
final File metadataFile = File( final File metadataFile = File(
path.join(tempDir.absolute.path, getMetadataFilename(platform)), path.join(tempDir.absolute.path, getMetadataFilename(platform)),
); );
await _runGsUtil(<String>['cp', metadataGsPath, metadataFile.absolute.path]); await _runGsUtil(<String>['cp', gsPath, metadataFile.absolute.path]);
final String currentMetadata = metadataFile.readAsStringSync(); if (!dryRun) {
if (currentMetadata.isEmpty) { final String currentMetadata = metadataFile.readAsStringSync();
throw PreparePackageException('Empty metadata received from server'); if (currentMetadata.isEmpty) {
} throw PreparePackageException('Empty metadata received from server');
}
Map<String, dynamic> jsonData; Map<String, dynamic> jsonData;
try { try {
jsonData = json.decode(currentMetadata) as Map<String, dynamic>; jsonData = json.decode(currentMetadata) as Map<String, dynamic>;
} on FormatException catch (e) { } on FormatException catch (e) {
throw PreparePackageException('Unable to parse JSON metadata received from cloud: $e'); throw PreparePackageException('Unable to parse JSON metadata received from cloud: $e');
} }
jsonData = await _addRelease(jsonData); jsonData = await _addRelease(jsonData, newBucket: newBucket);
const JsonEncoder encoder = JsonEncoder.withIndent(' '); const JsonEncoder encoder = JsonEncoder.withIndent(' ');
metadataFile.writeAsStringSync(encoder.convert(jsonData)); metadataFile.writeAsStringSync(encoder.convert(jsonData));
await _cloudCopy(metadataFile.absolute.path, metadataGsPath); }
await _cloudCopy(metadataFile.absolute.path, gsPath);
} }
Future<String> _runGsUtil( Future<String> _runGsUtil(
...@@ -591,6 +601,10 @@ class ArchivePublisher { ...@@ -591,6 +601,10 @@ class ArchivePublisher {
Directory workingDirectory, Directory workingDirectory,
bool failOk = false, bool failOk = false,
}) async { }) async {
if (dryRun) {
print('gsutil.py -- $args');
return '';
}
if (platform.isWindows) { if (platform.isWindows) {
return _processRunner.runProcess( return _processRunner.runProcess(
<String>['python', path.join(platform.environment['DEPOT_TOOLS'], 'gsutil.py'), '--', ...args], <String>['python', path.join(platform.environment['DEPOT_TOOLS'], 'gsutil.py'), '--', ...args],
...@@ -686,7 +700,7 @@ Future<void> main(List<String> rawArguments) async { ...@@ -686,7 +700,7 @@ Future<void> main(List<String> rawArguments) async {
defaultsTo: false, defaultsTo: false,
help: 'If set, will publish the archive to Google Cloud Storage upon ' help: 'If set, will publish the archive to Google Cloud Storage upon '
'successful creation of the archive. Will publish under this ' 'successful creation of the archive. Will publish under this '
'directory: $baseUrl$releaseFolder', 'directory: $newBaseUrl$releaseFolder',
); );
argParser.addFlag( argParser.addFlag(
'force', 'force',
...@@ -694,6 +708,12 @@ Future<void> main(List<String> rawArguments) async { ...@@ -694,6 +708,12 @@ Future<void> main(List<String> rawArguments) async {
defaultsTo: false, defaultsTo: false,
help: 'Overwrite a previously uploaded package.', help: 'Overwrite a previously uploaded package.',
); );
argParser.addFlag(
'dry_run',
defaultsTo: false,
negatable: false,
help: 'Prints gsutil commands instead of executing them.',
);
argParser.addFlag( argParser.addFlag(
'help', 'help',
defaultsTo: false, defaultsTo: false,
...@@ -763,6 +783,7 @@ Future<void> main(List<String> rawArguments) async { ...@@ -763,6 +783,7 @@ Future<void> main(List<String> rawArguments) async {
branch, branch,
version, version,
outputFile, outputFile,
parsedArguments['dry_run'] as bool,
); );
await publisher.publishArchive(parsedArguments['force'] as bool); await publisher.publishArchive(parsedArguments['force'] as bool);
} }
......
...@@ -241,6 +241,7 @@ void main() { ...@@ -241,6 +241,7 @@ void main() {
final String archiveName = platform.isLinux ? 'archive.tar.xz' : 'archive.zip'; final String archiveName = platform.isLinux ? 'archive.tar.xz' : 'archive.zip';
final String archiveMime = platform.isLinux ? 'application/x-gtar' : 'application/zip'; final String archiveMime = platform.isLinux ? 'application/x-gtar' : 'application/zip';
final String gsArchivePath = 'gs://flutter_infra/releases/stable/$platformName/$archiveName'; final String gsArchivePath = 'gs://flutter_infra/releases/stable/$platformName/$archiveName';
final String newGsArchivePath = 'gs://flutter_infra_release/releases/stable/$platformName/$archiveName';
setUp(() async { setUp(() async {
processManager = FakeProcessManager(); processManager = FakeProcessManager();
...@@ -255,6 +256,7 @@ void main() { ...@@ -255,6 +256,7 @@ void main() {
final String archivePath = path.join(tempDir.absolute.path, archiveName); final String archivePath = path.join(tempDir.absolute.path, archiveName);
final String jsonPath = path.join(tempDir.absolute.path, releasesName); final String jsonPath = path.join(tempDir.absolute.path, releasesName);
final String gsJsonPath = 'gs://flutter_infra/releases/$releasesName'; final String gsJsonPath = 'gs://flutter_infra/releases/$releasesName';
final String newGsJsonPath = 'gs://flutter_infra_release/releases/$releasesName';
final String releasesJson = ''' final String releasesJson = '''
{ {
"base_url": "https://storage.googleapis.com/flutter_infra/releases", "base_url": "https://storage.googleapis.com/flutter_infra/releases",
...@@ -300,9 +302,16 @@ void main() { ...@@ -300,9 +302,16 @@ void main() {
'$gsutilCall -- cp $gsJsonPath $jsonPath': null, '$gsutilCall -- cp $gsJsonPath $jsonPath': null,
'$gsutilCall -- rm $gsJsonPath': null, '$gsutilCall -- rm $gsJsonPath': null,
'$gsutilCall -- -h Content-Type:application/json cp $jsonPath $gsJsonPath': null, '$gsutilCall -- -h Content-Type:application/json cp $jsonPath $gsJsonPath': null,
'$gsutilCall -- stat $newGsArchivePath': <ProcessResult>[ProcessResult(0, 1, '', '')],
'$gsutilCall -- rm $newGsArchivePath': null,
'$gsutilCall -- -h Content-Type:$archiveMime cp $archivePath $newGsArchivePath': null,
'$gsutilCall -- cp $newGsJsonPath $jsonPath': null,
'$gsutilCall -- rm $newGsJsonPath': null,
'$gsutilCall -- -h Content-Type:application/json cp $jsonPath $newGsJsonPath': null,
}; };
processManager.fakeResults = calls; processManager.fakeResults = calls;
final File outputFile = File(path.join(tempDir.absolute.path, archiveName)); final File outputFile = File(path.join(tempDir.absolute.path, archiveName));
outputFile.createSync();
assert(tempDir.existsSync()); assert(tempDir.existsSync());
final ArchivePublisher publisher = ArchivePublisher( final ArchivePublisher publisher = ArchivePublisher(
tempDir, tempDir,
...@@ -310,6 +319,7 @@ void main() { ...@@ -310,6 +319,7 @@ void main() {
Branch.stable, Branch.stable,
'v1.2.3', 'v1.2.3',
outputFile, outputFile,
false,
processManager: processManager, processManager: processManager,
subprocessOutput: false, subprocessOutput: false,
platform: platform, platform: platform,
...@@ -354,6 +364,7 @@ void main() { ...@@ -354,6 +364,7 @@ void main() {
Branch.stable, Branch.stable,
'v1.2.3', 'v1.2.3',
outputFile, outputFile,
false,
processManager: processManager, processManager: processManager,
subprocessOutput: false, subprocessOutput: false,
platform: platform, platform: platform,
...@@ -376,6 +387,7 @@ void main() { ...@@ -376,6 +387,7 @@ void main() {
Branch.stable, Branch.stable,
'v1.2.3', 'v1.2.3',
outputFile, outputFile,
false,
processManager: processManager, processManager: processManager,
subprocessOutput: false, subprocessOutput: false,
platform: platform, platform: platform,
...@@ -383,6 +395,7 @@ void main() { ...@@ -383,6 +395,7 @@ void main() {
final String archivePath = path.join(tempDir.absolute.path, archiveName); final String archivePath = path.join(tempDir.absolute.path, archiveName);
final String jsonPath = path.join(tempDir.absolute.path, releasesName); final String jsonPath = path.join(tempDir.absolute.path, releasesName);
final String gsJsonPath = 'gs://flutter_infra/releases/$releasesName'; final String gsJsonPath = 'gs://flutter_infra/releases/$releasesName';
final String newGsJsonPath = 'gs://flutter_infra_release/releases/$releasesName';
final String releasesJson = ''' final String releasesJson = '''
{ {
"base_url": "https://storage.googleapis.com/flutter_infra/releases", "base_url": "https://storage.googleapis.com/flutter_infra/releases",
...@@ -426,6 +439,11 @@ void main() { ...@@ -426,6 +439,11 @@ void main() {
'$gsutilCall -- cp $gsJsonPath $jsonPath': null, '$gsutilCall -- cp $gsJsonPath $jsonPath': null,
'$gsutilCall -- rm $gsJsonPath': null, '$gsutilCall -- rm $gsJsonPath': null,
'$gsutilCall -- -h Content-Type:application/json cp $jsonPath $gsJsonPath': null, '$gsutilCall -- -h Content-Type:application/json cp $jsonPath $gsJsonPath': null,
'$gsutilCall -- rm $newGsArchivePath': null,
'$gsutilCall -- -h Content-Type:$archiveMime cp $archivePath $newGsArchivePath': null,
'$gsutilCall -- cp $newGsJsonPath $jsonPath': null,
'$gsutilCall -- rm $newGsJsonPath': null,
'$gsutilCall -- -h Content-Type:application/json cp $jsonPath $newGsJsonPath': null,
}; };
processManager.fakeResults = calls; processManager.fakeResults = calls;
assert(tempDir.existsSync()); assert(tempDir.existsSync());
......
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