diff --git a/.github/workflows/dart_services.yml b/.github/workflows/dart_services.yml index c7fa99cad..2f0ded4d6 100644 --- a/.github/workflows/dart_services.yml +++ b/.github/workflows/dart_services.yml @@ -12,12 +12,11 @@ on: - '.github/workflows/dart_services.yml' - 'pkgs/dart_services/**' schedule: - - cron: '0 0 * * 0' # weekly + - cron: '0 0 * * *' # daily jobs: - # Check code formatting, static analysis, and build on a single OS (linux) - # against Dart stable and beta. - analyze: + # Check code formatting, static analysis, and build on a single OS (linux). + verify: runs-on: ubuntu-latest defaults: run: @@ -29,39 +28,27 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: subosito/flutter-action@aa6d9b984461fff0e0e0673f96483607df98db84 - - name: Install dependencies + with: + channel: ${{ matrix.sdk }} + + - name: Install apt dependencies run: sudo apt-get install -y protobuf-compiler redis - - name: Install dependencies + + - name: Install dart dependencies run: dart pub get - - name: Analyze code - run: dart analyze --fatal-infos . - - name: check formatting - run: dart format --set-exit-if-changed lib test tool + + - name: Analyze project source + run: dart analyze --fatal-infos + + - name: Verify formatting + run: dart format --set-exit-if-changed bin lib test tool + + - name: Create template projects and populate the custom pub cache + run: dart run grinder build-project-templates + - name: Run tests - env: - FLUTTER_CHANNEL: ${{ matrix.sdk }} - run: | - export PATH=$PATH:$HOME/.pub-cache/bin - dart pub global activate protoc_plugin - dart run grinder test + run: dart test - # Run the benchmarks on the bots to ensure they don't regress. - benchmark: - runs-on: ubuntu-latest - defaults: - run: - working-directory: pkgs/dart_services/ - steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: subosito/flutter-action@aa6d9b984461fff0e0e0673f96483607df98db84 - - run: sudo apt-get install -y protobuf-compiler redis - - run: dart pub get - - name: Download the Flutter SDK - run: | - flutter doctor -v - - name: Prep the repo - env: - FLUTTER_CHANNEL: stable - run: dart run grinder buildbot - - name: Run benchmarks - run: dart benchmark/bench.dart + # Build the web artifacts on the bots to ensure they don't regress. + - name: Build web artifacts + run: dart run grinder build-storage-artifacts diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml index 1846d3a57..19166dd2a 100644 --- a/.github/workflows/samples.yml +++ b/.github/workflows/samples.yml @@ -30,4 +30,3 @@ jobs: - run: dart format --set-exit-if-changed . - run: dart tool/samples.dart --verify - run: flutter build web - # - run: flutter test diff --git a/.github/workflows/sketch_pad.yml b/.github/workflows/sketch_pad.yml index 3776427c0..ba06c5357 100644 --- a/.github/workflows/sketch_pad.yml +++ b/.github/workflows/sketch_pad.yml @@ -25,8 +25,6 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: subosito/flutter-action@cc97e1648fff6ca5cc647fa67f47e70f7895510b - with: - channel: 'stable' - run: flutter pub get - run: flutter analyze - run: dart format --set-exit-if-changed . diff --git a/pkgs/dart_services/README.md b/pkgs/dart_services/README.md index 3ee531be3..e2c3c2561 100644 --- a/pkgs/dart_services/README.md +++ b/pkgs/dart_services/README.md @@ -67,11 +67,7 @@ The server will run from port 8080 and export several JSON APIs, like To run tests: -`dart tool/grind.dart test` - -or: - -`grind deploy` for all tests and checks. +`dart test` ## Redis diff --git a/pkgs/dart_services/benchmark/bench.dart b/pkgs/dart_services/benchmark/bench.dart deleted file mode 100644 index a9b823d0a..000000000 --- a/pkgs/dart_services/benchmark/bench.dart +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright (c) 2014, 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. - -// ignore_for_file: only_throw_errors - -import 'dart:async'; - -import 'package:dart_services/src/analysis_server.dart'; -import 'package:dart_services/src/common.dart'; -import 'package:dart_services/src/compiler.dart'; -import 'package:dart_services/src/logging.dart'; -import 'package:dart_services/src/protos/dart_services.pb.dart' as proto; -import 'package:dart_services/src/sdk.dart'; -import 'package:logging/logging.dart'; - -import 'bench_impl.dart'; - -void main(List args) async { - final json = args.contains('--json'); - final harness = BenchmarkHarness(asJson: json); - final compiler = Compiler(Sdk(), storageBucket: 'nnbd_artifacts'); - - Logger.root.level = Level.INFO; - emitLogsToStdout(); - - final benchmarks = [ - AnalyzerBenchmark('hello', sampleCode), - AnalyzerBenchmark('hellohtml', sampleCodeWeb), - AnalyzerBenchmark('sunflower', _sunflower), - AnalyzerBenchmark('spinning_square', _spinningSquare), - AnalysisServerBenchmark('hello', sampleCode), - AnalysisServerBenchmark('hellohtml', sampleCodeWeb), - AnalysisServerBenchmark('sunflower', _sunflower), - AnalysisServerBenchmark('spinning_square', _spinningSquare), - Dart2jsBenchmark('hello', sampleCode, compiler), - Dart2jsBenchmark('hellohtml', sampleCodeWeb, compiler), - Dart2jsBenchmark('sunflower', _sunflower, compiler), - // TODO: dart-services dart2js compile path doesn't currently support - // compiling Flutter apps. - // Dart2jsBenchmark('spinning_square', _spinningSquare, compiler), - DevCompilerBenchmark('hello', sampleCode, compiler), - DevCompilerBenchmark('hellohtml', sampleCodeWeb, compiler), - DevCompilerBenchmark('sunflower', _sunflower, compiler), - DevCompilerBenchmark('spinning_square', _spinningSquare, compiler), - ]; - - await harness.benchmark(benchmarks); - await compiler.dispose(); -} - -class AnalyzerBenchmark extends Benchmark { - final String source; - final AnalysisServerWrapper analysisServer; - - AnalyzerBenchmark( - String name, - this.source, - ) : analysisServer = - DartAnalysisServerWrapper(dartSdkPath: Sdk().dartSdkPath), - super('analyzer.$name'); - - @override - Future init() => analysisServer.init(); - - @override - Future perform() => analysisServer.analyze(source); - - @override - Future tearDown() => analysisServer.shutdown(); -} - -class Dart2jsBenchmark extends Benchmark { - final String source; - final Compiler compiler; - - Dart2jsBenchmark(String name, this.source, this.compiler) - : super('dart2js.$name'); - - @override - Future perform() { - return compiler.compile(source).then((CompilationResults result) { - if (!result.success) throw result; - }); - } -} - -class DevCompilerBenchmark extends Benchmark { - final String source; - final Compiler compiler; - - DevCompilerBenchmark(String name, this.source, this.compiler) - : super('dartdevc.$name'); - - @override - Future perform() { - return compiler.compileDDC(source).then((DDCCompilationResults result) { - if (!result.success) throw result; - }); - } -} - -class AnalysisServerBenchmark extends Benchmark { - final String source; - final AnalysisServerWrapper analysisServer; - - AnalysisServerBenchmark(String name, this.source) - : analysisServer = - DartAnalysisServerWrapper(dartSdkPath: Sdk().dartSdkPath), - super('completion.$name'); - - @override - Future init() => analysisServer.init(); - - @override - Future perform() => - analysisServer.complete(source, 30); - - @override - Future tearDown() => analysisServer.shutdown(); -} - -final String _sunflower = ''' -library sunflower; - -import 'dart:html'; -import 'dart:math' as math; - -main() { - Sunflower(); -} - -class Sunflower { - static const String orange = "orange"; - static const seedRadius = 2; - static const scaleFactor = 4; - static const tau = math.pi * 2; - static const maxD = 300; - - late CanvasRenderingContext2D ctx; - late num xc, yc; - num seeds = 0; - late num phi; - - Sunflower() { - phi = (math.sqrt(5) + 1) / 2; - - CanvasElement canvas = querySelector("#canvas") as CanvasElement; - xc = yc = maxD / 2; - ctx = canvas.getContext("2d") as CanvasRenderingContext2D; - - var slider = querySelector("#slider") as InputElement; - slider.onChange.listen((Event e) { - seeds = int.parse(slider.value!); - drawFrame(); - }); - - seeds = int.parse(slider.value!); - - drawFrame(); - } - - // Draw the complete figure for the current number of seeds. - void drawFrame() { - ctx.clearRect(0, 0, maxD, maxD); - for (var i = 0; i < seeds; i++) { - var theta = i * tau / phi; - var r = math.sqrt(i) * scaleFactor; - var x = xc + r * math.cos(theta); - var y = yc - r * math.sin(theta); - drawSeed(x, y); - } - } - - // Draw a small circle representing a seed centered at (x,y). - void drawSeed(num x, num y) { - ctx.beginPath(); - ctx.lineWidth = 2; - ctx.fillStyle = orange; - ctx.strokeStyle = orange; - ctx.arc(x, y, seedRadius, 0, tau, false); - ctx.fill(); - ctx.closePath(); - ctx.stroke(); - } -} -'''; - -final _spinningSquare = ''' -import 'package:flutter/material.dart'; - -class SpinningSquare extends StatefulWidget { - @override - SpinningSquareState createState() => SpinningSquareState(); -} - -class SpinningSquareState extends State - with SingleTickerProviderStateMixin { - late AnimationController _animation; - - @override - void initState() { - super.initState(); - // We use 3600 milliseconds instead of 1800 milliseconds because 0.0 -> 1.0 - // represents an entire turn of the square whereas in the other examples - // we used 0.0 -> math.pi, which is only half a turn. - _animation = AnimationController( - duration: const Duration(milliseconds: 3600), - vsync: this, - )..repeat(); - } - - @override - Widget build(BuildContext context) { - return RotationTransition( - turns: _animation, - child: Container( - width: 200.0, - height: 200.0, - color: const Color(0xFF00FF00), - ), - ); - } - - @override - void dispose() { - _animation.dispose(); - super.dispose(); - } -} - -main() async { - runApp(Center(child: SpinningSquare())); -} -'''; diff --git a/pkgs/dart_services/benchmark/bench_impl.dart b/pkgs/dart_services/benchmark/bench_impl.dart deleted file mode 100644 index 83d8c75e6..000000000 --- a/pkgs/dart_services/benchmark/bench_impl.dart +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2014, 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. - -/// A benchmark library. This library supports running benchmarks which can -/// run asynchronously. -library; - -import 'dart:async'; -import 'dart:convert' show json; - -abstract class Benchmark { - final String name; - - Benchmark(this.name); - - Future init() => Future.value(); - - Future perform(); - - /// Called once when this benchmark will no longer be used. - Future tearDown() => Future.value(); - - @override - String toString() => name; -} - -typedef BenchmarkLogger = void Function(String str); - -class BenchmarkHarness { - final bool asJson; - final BenchmarkLogger logger; - - BenchmarkHarness({required this.asJson, this.logger = print}); - - Future benchmark(List benchmarks) async { - log('Running ${benchmarks.length} benchmarks.'); - log(''); - - final results = []; - - await Future.forEach(benchmarks, (Benchmark benchmark) => benchmark.init()); - - return Future.forEach(benchmarks, (Benchmark benchmark) { - return benchmarkSingle(benchmark).then(results.add); - }).then((_) { - if (asJson) { - logger(json.encode(results - .map((BenchMarkResult r) => - {r.benchmark.name: r.averageMilliseconds()}) - .toList())); - } - }); - } - - Future benchmarkSingle(Benchmark benchmark) { - return _warmup(benchmark).then((_) { - return _measure(benchmark); - }).then((BenchMarkResult result) { - logResult(result); - return result; - }).whenComplete(() { - return benchmark.tearDown().catchError((dynamic e) => null); - }); - } - - void log(String message) { - if (!asJson) logger(message); - } - - void logResult(BenchMarkResult result) { - if (!asJson) logger(result.toString()); - } - - Future _warmup(Benchmark benchmark) { - return _time(benchmark, 2, 1000); - } - - Future _measure(Benchmark benchmark) { - return _time(benchmark, 10, 2000, 10000); - } - - Future _time( - Benchmark benchmark, int minIterations, int minMillis, - [int? maxMillis]) { - final result = BenchMarkResult(benchmark); - final timer = Stopwatch()..start(); - - return Future.doWhile(() { - if (result.iteration >= minIterations && - timer.elapsedMilliseconds >= minMillis) { - return false; - } - - if (maxMillis != null && timer.elapsedMilliseconds >= maxMillis) { - return false; - } - - result.iteration++; - return benchmark.perform().then((_) => true); - }).then((_) { - timer.stop(); - result.microseconds = timer.elapsedMicroseconds; - return result; - }); - } -} - -class BenchMarkResult { - final Benchmark benchmark; - int iteration = 0; - int microseconds = 0; - - BenchMarkResult(this.benchmark); - - double averageMilliseconds() => (microseconds / iteration) / 1000.0; - - @override - String toString() => '[${benchmark.name.padRight(26)}: ' - '${averageMilliseconds().toStringAsFixed(3).padLeft(8)}ms]'; -} diff --git a/pkgs/dart_services/tool/grind.dart b/pkgs/dart_services/tool/grind.dart index d9af97cd4..05bbec33f 100644 --- a/pkgs/dart_services/tool/grind.dart +++ b/pkgs/dart_services/tool/grind.dart @@ -22,20 +22,6 @@ Future main(List args) async { return grind(args); } -@Task() -@Depends(buildProjectTemplates) -void analyze() async { - await _run('dart', arguments: ['analyze']); -} - -@Task() -@Depends(buildStorageArtifacts) -Future test() => _run(Platform.executable, arguments: ['test']); - -@DefaultTask() -@Depends(analyze, test) -void analyzeTest() {} - @Task() @Depends(buildStorageArtifacts) Future serve() async { @@ -46,34 +32,9 @@ Future serve() async { ]); } -const _dartImageName = 'dart'; -final _dockerVersionMatcher = RegExp('^FROM $_dartImageName:(.*)\$'); -const _dockerFileNames = [ - 'cloud_run_beta.Dockerfile', - 'cloud_run_main.Dockerfile', - 'cloud_run_stable.Dockerfile', -]; - /// Creates an SDK. Sdk _getSdk() => Sdk(); -@Task('Update the docker and SDK versions') -void updateDockerVersion() { - final platformVersion = Platform.version.split(' ').first; - for (final dockerFileName in _dockerFileNames) { - final dockerFile = File(dockerFileName); - final dockerImageLines = dockerFile.readAsLinesSync().map((String s) { - if (s.contains(_dockerVersionMatcher)) { - return 'FROM $_dartImageName:$platformVersion'; - } - return s; - }).toList(); - dockerImageLines.add(''); - - dockerFile.writeAsStringSync(dockerImageLines.join('\n')); - } -} - final List compilationArtifacts = [ 'dart_sdk.js', 'flutter_web.js', @@ -288,16 +249,11 @@ Future _buildStorageArtifacts(Directory dir, Sdk sdk, } @Task('Update generated files and run all checks prior to deployment') -@Depends(updateDockerVersion, generateProtos, analyze, test, - validateStorageArtifacts) +@Depends(buildProjectTemplates, validateStorageArtifacts) void deploy() { log('Deploy via Google Cloud Console'); } -@Task() -@Depends(analyze, buildStorageArtifacts) -void buildbot() {} - @Task('Generate Protobuf classes') void generateProtos() async { try {