From 7f7726ecf0003e9078255ec8fefb6265c7f4d3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20So=C3=B3s?= Date: Wed, 3 Jan 2024 16:54:46 +0100 Subject: [PATCH] Trigger API exporter after a package is uploaded. (#7328) --- app/lib/package/backend.dart | 23 +++++++------------ app/lib/package/export_api_to_bucket.dart | 5 ++++ .../package/export_api_to_bucket_test.dart | 23 +++++++++++++++++++ 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/app/lib/package/backend.dart b/app/lib/package/backend.dart index c3a564896..0555121d6 100644 --- a/app/lib/package/backend.dart +++ b/app/lib/package/backend.dart @@ -17,6 +17,7 @@ import 'package:gcloud/storage.dart'; import 'package:logging/logging.dart'; import 'package:meta/meta.dart'; import 'package:pool/pool.dart'; +import 'package:pub_dev/package/export_api_to_bucket.dart'; import 'package:pub_dev/service/async_queue/async_queue.dart'; import 'package:pub_dev/task/backend.dart'; import 'package:pub_package_reader/pub_package_reader.dart'; @@ -1047,8 +1048,6 @@ class PackageBackend { final outgoingEmail = emailBackend.prepareEntity(email); Package? package; - String? prevLatestStableVersion; - String? prevLatestPrereleaseVersion; // Add the new package to the repository by storing the tarball and // inserting metadata to datastore (which happens atomically). @@ -1058,8 +1057,6 @@ class PackageBackend { final tuple = (await tx.lookup([newVersion.key, newVersion.packageKey!])); final version = tuple[0] as PackageVersion?; package = tuple[1] as Package?; - prevLatestStableVersion = package?.latestVersion; - prevLatestPrereleaseVersion = package?.latestPrereleaseVersion; // If the version already exists, we fail. if (version != null) { @@ -1144,13 +1141,8 @@ class PackageBackend { // Let's not block the upload response on these post-upload tasks. // The operations should either be non-critical, or should be retried // automatically. - asyncQueue.addAsyncFn(() => _postUploadTasks( - package, - newVersion, - outgoingEmail, - prevLatestStableVersion: prevLatestStableVersion, - prevLatestPrereleaseVersion: prevLatestPrereleaseVersion, - )); + asyncQueue + .addAsyncFn(() => _postUploadTasks(package, newVersion, outgoingEmail)); _logger.info('Post-upload tasks completed in ${sw.elapsed}.'); return pv; @@ -1163,14 +1155,15 @@ class PackageBackend { Future _postUploadTasks( Package? package, PackageVersion newVersion, - OutgoingEmail outgoingEmail, { - String? prevLatestStableVersion, - String? prevLatestPrereleaseVersion, - }) async { + OutgoingEmail outgoingEmail, + ) async { try { await Future.wait([ emailBackend.trySendOutgoingEmail(outgoingEmail), taskBackend.trackPackage(newVersion.package, updateDependants: true), + if (apiExporter != null) + apiExporter! + .updatePackageVersion(newVersion.package, newVersion.version!), ]); } catch (e, st) { final v = newVersion.qualifiedVersionKey; diff --git a/app/lib/package/export_api_to_bucket.dart b/app/lib/package/export_api_to_bucket.dart index c87828286..4a6879978 100644 --- a/app/lib/package/export_api_to_bucket.dart +++ b/app/lib/package/export_api_to_bucket.dart @@ -178,6 +178,11 @@ class ApiExporter { await pool.close(); } + /// Updates the API files after a version has changed (e.g. new version was uploaded). + Future updatePackageVersion(String package, String version) async { + await _uploadPackageToBucket(package); + } + /// Uploads the package version API response bytes to the bucket, mirroring /// the endpoint name in the file location. Future _uploadPackageToBucket(String package) async { diff --git a/app/test/package/export_api_to_bucket_test.dart b/app/test/package/export_api_to_bucket_test.dart index 2d85ddcad..473d87430 100644 --- a/app/test/package/export_api_to_bucket_test.dart +++ b/app/test/package/export_api_to_bucket_test.dart @@ -8,11 +8,14 @@ import 'dart:io'; import 'package:clock/clock.dart'; import 'package:gcloud/storage.dart'; import 'package:pub_dev/package/export_api_to_bucket.dart'; +import 'package:pub_dev/shared/configuration.dart'; import 'package:pub_dev/shared/storage.dart'; import 'package:pub_dev/shared/versions.dart'; import 'package:test/test.dart'; +import '../shared/test_models.dart'; import '../shared/test_services.dart'; +import 'backend_test_utils.dart'; void main() { group('export API to bucket', () { @@ -71,5 +74,25 @@ void main() { ); }, ); + + testWithProfile('new upload', fn: () async { + await apiExporter!.fullPkgScanAndUpload(); + + final bucket = + storageService.bucket(activeConfiguration.exportedApiBucketName!); + final originalBytes = + await bucket.readAsBytes('current/api/packages/oxygen'); + + final pubspecContent = generatePubspecYaml('oxygen', '9.0.0'); + final message = await createPubApiClient(authToken: adminClientToken) + .uploadPackageBytes( + await packageArchiveBytes(pubspecContent: pubspecContent)); + expect(message.success.message, contains('Successfully uploaded')); + + await Future.delayed(Duration(seconds: 1)); + final updatedBytes = + await bucket.readAsBytes('current/api/packages/oxygen'); + expect(originalBytes.length, lessThan(updatedBytes.length)); + }); }); }