Skip to content

Commit

Permalink
add tests and ci checks
Browse files Browse the repository at this point in the history
  • Loading branch information
felangel committed Apr 6, 2023
1 parent 8353a87 commit ae2f422
Show file tree
Hide file tree
Showing 7 changed files with 436 additions and 121 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ jobs:
id: needs_dart_build
with:
filters: |
artifacts_proxy:
- ./.github/actions/dart_package
- packages/artifacts_proxy/**
shorebird_cli:
- ./.github/actions/dart_package
- packages/shorebird_cli/**
- packages/shorebird_code_push_client/**
- packages/shorebird_code_push_client/**
shorebird_code_push_client:
- ./.github/actions/dart_package
- packages/shorebird_code_push_client/**
Expand Down
5 changes: 4 additions & 1 deletion packages/artifact_proxy/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@
.dart_tool/

# Used for local testing of artifact_proxy.
artifacts/
artifacts/

# Test related files
coverage/
119 changes: 9 additions & 110 deletions packages/artifact_proxy/bin/server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
import 'dart:io';

import 'package:args/args.dart';
import 'package:collection/collection.dart';
import 'package:artifact_proxy/artifact_proxy.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_hotreload/shelf_hotreload.dart';
import 'package:yaml/yaml.dart';
import 'package:yaml_edit/yaml_edit.dart';

Future<void> main(List<String> args) async {
final parser = ArgParser()
Expand All @@ -33,121 +32,21 @@ Future<void> main(List<String> args) async {
exit(1);
}

final configPath = results['config'] as String;
final shouldRecord = results['record'] as bool;
final shouldWatch = results['watch'] as bool;
final configPath = results['config'] as String;
final config = loadYaml(File(configPath).readAsStringSync()) as Map;
final handler = artifactProxyHandler(config: config);

if (shouldWatch) {
withHotreload(
() => createServer(configPath: configPath, shouldRecord: shouldRecord),
);
} else {
await createServer(configPath: configPath, shouldRecord: shouldRecord);
}
}

Future<HttpServer> createServer({
required String configPath,
required bool shouldRecord,
}) async {
final configYaml = loadYaml(File(configPath).readAsStringSync()) as Map;
final engineMappings = configYaml['engine_mappings'] as Map;
final shorebirdEngineRevisions = engineMappings.keys.cast<String>();

String flutterLocation({required String artifactPath, String? engine}) {
final adjustedPath = engine != null
? artifactPath.replaceAll(r'$engine', engine)
: artifactPath;

if (adjustedPath.isChromeInfra()) {
return adjustedPath.replaceAll(
'flutter_infra_release/cipd',
'https://chrome-infra-packages.appspot.com/dl',
);
}
return 'https://storage.googleapis.com/$adjustedPath';
}

String shorebirdLocation({
required String artifactPath,
required String engine,
required String bucket,
}) {
final adjustedPath = artifactPath.replaceAll(r'$engine', engine);
return 'https://storage.googleapis.com/$bucket/$adjustedPath';
}

Response proxy(Request request) {
final path = request.url.path;
final shorebirdEngineRevision = shorebirdEngineRevisions.firstWhereOrNull(
path.contains,
);

final normalizedPath = shorebirdEngineRevision != null
? path.replaceAll(shorebirdEngineRevision, r'$engine')
: path;

if (shouldRecord) recordArtifact(configPath, normalizedPath);

if (shorebirdEngineRevision == null) {
final location = flutterLocation(artifactPath: normalizedPath);
print('No engine revision detected, forwarding to: $location');
return Response.found(location);
}

final engineMapping = engineMappings[shorebirdEngineRevision] as Map;
final shorebirdOverrides =
engineMapping['shorebird_artifact_overrides'] as List;
final flutterEngineRevision =
engineMapping['flutter_engine_revision'] as String;
final shorebirdStorageBucket =
engineMapping['shorebird_storage_bucket'] as String;
final shouldOverride = shorebirdOverrides.contains(normalizedPath);

if (shouldOverride) {
final location = shorebirdLocation(
artifactPath: normalizedPath,
engine: shorebirdEngineRevision,
bucket: shorebirdStorageBucket,
);
print('Shorebird artifact detected, forwarding to: $location');
return Response.found(location);
}
// Hot-reload is enabled when the `--watch` flag is passed.
if (shouldWatch) return withHotreload(() => createServer(handler));

final location = flutterLocation(
artifactPath: normalizedPath,
engine: flutterEngineRevision,
);
print('Flutter artifact detected, forwarding to: $location');
return Response.found(location);
}
await createServer(handler);
}

Future<HttpServer> createServer(Handler proxy) async {
final handler =
const Pipeline().addMiddleware(logRequests()).addHandler(proxy);

final server = await shelf_io.serve(handler, 'localhost', 8080);

server.autoCompress = true;

print('Serving at http://${server.address.host}:${server.port}');
return server;
}

void recordArtifact(String configPath, String path) {
final edit = YamlEditor(File(configPath).readAsStringSync());
final existing = edit.parseAt(['known_redirects'], orElse: YamlList.new);
if (existing is! YamlList || existing.isEmpty) {
edit.update(['known_redirects'], [path]);
File(configPath).writeAsStringSync(edit.toString());
} else if (!existing.contains(path)) {
edit.appendToList(['known_redirects'], path);
File(configPath).writeAsStringSync(edit.toString());
}
// Already contains the key, do nothing.
}

extension on String {
bool isChromeInfra() {
return contains('flutter_infra_release/cipd');
}
}
89 changes: 89 additions & 0 deletions packages/artifact_proxy/lib/artifact_proxy.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// ignore_for_file: avoid_print

import 'package:collection/collection.dart';
import 'package:shelf/shelf.dart';

/// A [Handler] that proxies artifact requests to the correct location.
/// This is determined based on the [config].
Handler artifactProxyHandler({
required Map<dynamic, dynamic> config,
}) {
final engineMappings = config['engine_mappings'] as Map;
final shorebirdEngineRevisions = engineMappings.keys.cast<String>();

return (Request request) {
final path = request.url.path;
final shorebirdEngineRevision = shorebirdEngineRevisions.firstWhereOrNull(
path.contains,
);

final normalizedPath = shorebirdEngineRevision != null
? path.replaceAll(shorebirdEngineRevision, r'$engine')
: path;

if (shorebirdEngineRevision == null) {
final location = getFlutterArtifactLocation(artifactPath: normalizedPath);
print('No engine revision detected, forwarding to: $location');
return Response.found(location);
}

final engineMapping = engineMappings[shorebirdEngineRevision] as Map;
final shorebirdOverrides =
engineMapping['shorebird_artifact_overrides'] as List;
final flutterEngineRevision =
engineMapping['flutter_engine_revision'] as String;
final shorebirdStorageBucket =
engineMapping['shorebird_storage_bucket'] as String;
final shouldOverride = shorebirdOverrides.contains(normalizedPath);

if (shouldOverride) {
final location = getShorebirdArtifactLocation(
artifactPath: normalizedPath,
engine: shorebirdEngineRevision,
bucket: shorebirdStorageBucket,
);
print('Shorebird artifact detected, forwarding to: $location');
return Response.found(location);
}

final location = getFlutterArtifactLocation(
artifactPath: normalizedPath,
engine: flutterEngineRevision,
);
print('Flutter artifact detected, forwarding to: $location');
return Response.found(location);
};
}

/// Returns the location of the artifact at [artifactPath] using the
/// specified [engine] revision for original Flutter artifacts.
String getFlutterArtifactLocation({
required String artifactPath,
String? engine,
}) {
final adjustedPath = engine != null
? artifactPath.replaceAll(r'$engine', engine)
: artifactPath;

final isChromeInfra = adjustedPath.contains('flutter_infra_release/cipd');

if (isChromeInfra) {
return adjustedPath.replaceAll(
'flutter_infra_release/cipd',
'https://chrome-infra-packages.appspot.com/dl',
);
}

return 'https://storage.googleapis.com/$adjustedPath';
}

/// Returns the location of the artifact at [artifactPath] using the
/// specified [engine] revision for Shorebird artifacts.
String getShorebirdArtifactLocation({
required String artifactPath,
required String engine,
required String bucket,
}) {
final adjustedPath = artifactPath.replaceAll(r'$engine', engine);
return 'https://storage.googleapis.com/$bucket/$adjustedPath';
}
Loading

0 comments on commit ae2f422

Please sign in to comment.