Skip to content

Commit

Permalink
End2end test for dockerized pub_worker build and execution. (#7301)
Browse files Browse the repository at this point in the history
  • Loading branch information
isoos authored Dec 15, 2023
1 parent 69b9af1 commit 50dd494
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 43 deletions.
51 changes: 51 additions & 0 deletions pkg/pub_worker/lib/src/testing/docker_utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2023, 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.

import 'dart:convert';
import 'dart:io';

import 'package:pub_worker/payload.dart';

final _ciEnv = Platform.environment['CI']?.toLowerCase();
final _isRunningOnCI = _ciEnv == 'true' || _ciEnv == '1';

Future<void> buildDockerImage() async {
final gitRootDir =
(await Process.run('git', ['rev-parse', '--show-toplevel']))
.stdout
.toString()
.trim();
final pr = await Process.start(
'docker',
[
'build',
'.',
'--tag=pub_worker',
'--file=Dockerfile.worker',
],
workingDirectory: gitRootDir,
mode: ProcessStartMode.inheritStdio,
);
final exitCode = await pr.exitCode;
if (exitCode != 0) {
throw Exception('process returned with exit code $exitCode');
}
}

Future<Process> startDockerAnalysis(Payload payload) async {
return await Process.start(
'docker',
<String>[
'run',
if (!_isRunningOnCI) '-it',
'--network=host',
'--entrypoint=dart',
'--rm',
'pub_worker',
'bin/pub_worker.dart',
json.encode(payload),
],
mode: ProcessStartMode.inheritStdio,
);
}
96 changes: 96 additions & 0 deletions pkg/pub_worker/test/dockerized_end2end_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright (c) 2023, 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.

import 'dart:convert';
import 'dart:io';

import 'package:http/http.dart' as http;
import 'package:pana/pana.dart';
import 'package:pub_worker/payload.dart';
import 'package:pub_worker/src/testing/docker_utils.dart';
import 'package:pub_worker/src/testing/server.dart';
import 'package:test/test.dart';

void main() {
group('Dockerized end2end tests', () {
final server = PubWorkerTestServer(
[],
fallbackPubHostedUrl: 'https://pub.dev',
);
setUpAll(
() async {
await server.start();
},
);

tearDownAll(() async {
await server.stop();
});

Future<String> analyzePackage(String package, [String? version]) async {
if (version == null) {
final url = server.baseUrl.resolve('/api/packages/$package');
final rs = await http.get(url);
if (rs.statusCode != 200) {
throw Exception('Unexpected status code on $url: ${rs.statusCode}');
}
final map = json.decode(rs.body) as Map;
version = (map['latest'] as Map)['version'] as String;
}

final payload = Payload(
package: package,
pubHostedUrl: '${server.baseUrl}',
versions: [
VersionTokenPair(
version: version,
token: 'secret-token',
),
],
);

final p = await startDockerAnalysis(payload);
final exitCode = await p.exitCode;
if (exitCode != 0) {
throw Exception(
'Failed to analyze $package $version with exitCode $exitCode');
}

return version;
}

// TODO: investigate why this is not running on GitHub properly
test(
'build and use docker image to analyze packages',
() async {
await buildDockerImage();

final packages = ['retry', 'url_launcher'];
final versions =
await Future.wait(packages.map((p) => analyzePackage(p)));

for (var i = 0; i < packages.length; i++) {
final package = packages[i];
final version = versions[i];
final result = await server.waitForResult(package, version);

final docIndex = result.index.lookup('doc/index.html');
expect(docIndex, isNotNull);

final panaSummaryBytes = result.lookup('summary.json');
expect(panaSummaryBytes, isNotNull);
final summary = Summary.fromJson(
json.decode(utf8.decode(gzip.decode(panaSummaryBytes!)))
as Map<String, dynamic>);
final report = summary.report!;
expect(report.maxPoints, greaterThan(100));
expect(report.grantedPoints, report.maxPoints);
}

// TODO: consider docker cleanup
},
timeout: Timeout(Duration(minutes: 15)),
);
});
}
61 changes: 18 additions & 43 deletions pkg/pub_worker/tool/trypkg.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'dart:io';
import 'package:args/args.dart';
import 'package:path/path.dart' as p;
import 'package:pub_worker/payload.dart';
import 'package:pub_worker/src/testing/docker_utils.dart';
import 'package:pub_worker/src/testing/server.dart';

final _argParser = ArgParser()
Expand Down Expand Up @@ -42,61 +43,35 @@ void main(List<String> args) async {
final server = PubWorkerTestServer([], fallbackPubHostedUrl: pubHostedUrl);

await server.start();
final payload = Payload(
package: package,
pubHostedUrl: '${server.baseUrl}',
versions: [
VersionTokenPair(
version: version,
token: 'secret-token',
),
],
);

final Process worker;
if (argResults['docker'] == true) {
print('Building worker docker image');
final buildProcess = await Process.start(
'docker',
['build', '.', '--tag=pub_worker', '--file=Dockerfile.worker'],
workingDirectory: Platform.script.resolve('../../..').path,
mode: ProcessStartMode.inheritStdio,
);
final buildExitCode = await buildProcess.exitCode;
if (buildExitCode != 0) {
print('Building docker image failed (exit code $buildExitCode)');
try {
print('Building worker docker image');
await buildDockerImage();
} catch (e) {
print('Building worker docker image failed: $e');
exit(-1);
}
worker = await Process.start(
'docker',
[
'run',
'-it',
'--network=host',
'--entrypoint=dart',
'--rm',
'pub_worker',
'bin/pub_worker.dart',
json.encode(Payload(
package: package,
pubHostedUrl: '${server.baseUrl}',
versions: [
VersionTokenPair(
version: version,
token: 'secret-token',
),
],
)),
],
mode: ProcessStartMode.inheritStdio,
);
worker = await startDockerAnalysis(payload);
} else {
worker = await Process.start(
Platform.resolvedExecutable,
[
'run',
if (argResults['observe'] == true) '--observe',
'pub_worker',
json.encode(Payload(
package: package,
pubHostedUrl: '${server.baseUrl}',
versions: [
VersionTokenPair(
version: version,
token: 'secret-token',
),
],
)),
json.encode(payload),
],
mode: ProcessStartMode.inheritStdio,
);
Expand Down

0 comments on commit 50dd494

Please sign in to comment.