Remove AppEngine Flex support (#686)

fixes: https://github.com/dart-lang/dart-pad/issues/1797
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index a37b2ac..0000000
--- a/Dockerfile
+++ /dev/null
@@ -1,40 +0,0 @@
-FROM google/dart:2.12.2
-
-# We install unzip and remove the apt-index again to keep the
-# docker image diff small.
-RUN apt-get update && \
-  apt-get install -y unzip && \
-  rm -rf /var/lib/apt/lists/*
-
-WORKDIR /app
-RUN groupadd --system dart && \
-  useradd --no-log-init --system --home /home/dart --create-home -g dart dart
-RUN chown dart:dart /app
-
-# Switch to a new, non-root user to use the flutter tool.
-# The Flutter tool won't perform its actions when run as root.
-USER dart
-
-COPY --chown=dart:dart tool/dart_run.sh /dart_runtime/
-COPY --chown=dart:dart pubspec.* /app/
-RUN pub get
-COPY --chown=dart:dart . /app
-RUN pub get --offline
-
-ENV PATH="/home/dart/.pub-cache/bin:${PATH}"
-
-# Set the Flutter SDK up for web compilation.
-RUN dart pub run grinder setup-flutter-sdk
-
-# Build the dill file
-RUN dart pub run grinder build-storage-artifacts validate-storage-artifacts
-
-EXPOSE 8080
-
-# Clear out any arguments the base images might have set and ensure we start
-# the Dart app using custom script enabling debug modes.
-CMD []
-
-ENTRYPOINT ["/dart_runtime/dart_run.sh", \
-  "--port", "8080", \
-  "--proxy-target", "https://v1.api.dartpad.dev/"]
diff --git a/app.yaml b/app.yaml
deleted file mode 100644
index bfa5820..0000000
--- a/app.yaml
+++ /dev/null
@@ -1,44 +0,0 @@
-runtime: custom
-env: flex
-
-resources:
-  cpu: 1
-  memory_gb: 4
-  disk_size_gb: 50
-
-automatic_scaling:
-  min_num_instances: 2
-  max_num_instances: 40
-  cool_down_period_sec: 60
-  cpu_utilization:
-    target_utilization: 0.6
-
-env_variables:
-  REDIS_SERVER_URI: 'redis://10.0.0.4:6379'
-
-network:
-  name: vpc-dart-services
-
-service: default
-
-skip_files:
-- ^\.git/.*$
-
-# Health checks, for detail please see:
-# https://cloud.google.com/appengine/docs/flexible/custom-runtimes/configuring-your-app-with-app-yaml#updated_health_checks
-
-# liveness_check:
-#   path: "/liveness_check"
-#   check_interval_sec: 30
-#   timeout_sec: 5
-#   failure_threshold: 2
-#   success_threshold: 2
-#   initial_delay_sec: 600
-
-# readiness_check:
-#   path: "/readiness_check"
-#   check_interval_sec: 5
-#   timeout_sec: 4
-#   failure_threshold: 2
-#   success_threshold: 2
-#   app_start_timeout_sec: 300
diff --git a/bin/server.dart b/bin/server.dart
deleted file mode 100644
index 49bc5ab..0000000
--- a/bin/server.dart
+++ /dev/null
@@ -1,20 +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.
-
-// To meet GAE needs this file must be called 'server.dart'.
-
-library appengine.services.bin;
-
-import 'dart:async';
-
-import 'package:dart_services/services_gae.dart' as server;
-import 'package:dart_services/src/sdk_manager.dart';
-
-Future<void> main(List<String> args) async {
-  // Ensure the Dart SDK is downloaded (if already up-to-date, no work is
-  // performed).
-  await SdkManager.sdk.init();
-
-  server.main(args);
-}
diff --git a/lib/services_gae.dart b/lib/services_gae.dart
deleted file mode 100644
index 577efe0..0000000
--- a/lib/services_gae.dart
+++ /dev/null
@@ -1,191 +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.
-
-library services_gae;
-
-import 'dart:io' as io;
-import 'dart:math';
-
-import 'package:appengine/appengine.dart' as ae;
-import 'package:args/args.dart';
-import 'package:logging/logging.dart';
-import 'package:shelf/shelf_io.dart' as shelf_io;
-
-import 'src/common_server_api.dart';
-import 'src/common_server_impl.dart';
-import 'src/sdk_manager.dart';
-import 'src/server_cache.dart';
-
-const String _API_PREFIX = '/api/dartservices/';
-const String _livenessCheck = '/liveness_check';
-const String _readinessCheck = '/readiness_check';
-
-// Serve content for 1.5 hours, +- 30 minutes.
-final DateTime _serveUntil = DateTime.now()
-    .add(Duration(hours: 1))
-    .add(Duration(minutes: Random().nextInt(60)));
-
-final Logger _logger = Logger('gae_server');
-
-void main(List<String> args) {
-  final parser = ArgParser()
-    ..addOption('proxy-target',
-        help: 'URL base to proxy compilation requests to')
-    ..addOption('port',
-        abbr: 'p', defaultsTo: '8080', help: 'Port to attach to');
-  final results = parser.parse(args);
-
-  final gaePort = int.tryParse(results['port'] as String ?? '') ?? 8080;
-
-  if (SdkManager.sdk.sdkPath == null) {
-    throw 'No Dart SDK is available; set the DART_SDK env var.';
-  }
-
-  // Log to stdout/stderr.  AppEngine's logging package is disabled in 0.6.0
-  // and AppEngine copies stdout/stderr to the dashboards.
-  _logger.onRecord.listen((LogRecord rec) {
-    final out = ('${rec.level.name}: ${rec.time}: ${rec.message}\n');
-    if (rec.level > Level.INFO) {
-      io.stderr.write(out);
-    } else {
-      io.stdout.write(out);
-    }
-  });
-  log.info('''Initializing dart-services:
-    --port: $gaePort
-    --proxy-target: ${results['proxy-target']}
-    sdkPath: ${SdkManager.sdk?.sdkPath}
-    \$REDIS_SERVER_URI: ${io.Platform.environment['REDIS_SERVER_URI']}
-    \$GAE_VERSION: ${io.Platform.environment['GAE_VERSION']}
-  ''');
-
-  final server = GaeServer(io.Platform.environment['REDIS_SERVER_URI'],
-      results['proxy-target'].toString());
-  server.start(gaePort);
-}
-
-class GaeServer {
-  final String redisServerUri;
-
-  CommonServerImpl commonServerImpl;
-  CommonServerApi commonServerApi;
-  bool proxying = false;
-
-  GaeServer(this.redisServerUri, String proxyTarget) {
-    hierarchicalLoggingEnabled = true;
-    recordStackTraceAtLevel = Level.SEVERE;
-
-    _logger.level = Level.ALL;
-
-    if (proxyTarget != null && proxyTarget.isNotEmpty) {
-      commonServerImpl = CommonServerImplProxy(proxyTarget);
-      proxying = true;
-    } else {
-      commonServerImpl = CommonServerImpl(
-        GaeServerContainer(),
-        redisServerUri == null
-            ? InMemoryCache()
-            : RedisCache(
-                redisServerUri,
-                io.Platform.environment['GAE_VERSION'],
-              ),
-      );
-    }
-    commonServerApi = CommonServerApi(commonServerImpl);
-  }
-
-  Future<dynamic> start([int gaePort = 8080]) async {
-    await commonServerImpl.init();
-    return ae.runAppEngine(requestHandler, port: gaePort);
-  }
-
-  Future<void> requestHandler(io.HttpRequest request) async {
-    request.response.headers
-      ..add('Access-Control-Allow-Origin', '*')
-      ..add('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
-      ..add('Access-Control-Allow-Headers',
-          'Origin, X-Requested-With, Content-Type, Accept');
-
-    if (request.method == 'OPTIONS') {
-      await _processOptionsRequest(request);
-    } else if (request.uri.path == _readinessCheck) {
-      await _processReadinessRequest(request);
-    } else if (request.uri.path == _livenessCheck) {
-      await _processLivenessRequest(request);
-    } else if (request.uri.path.startsWith(_API_PREFIX)) {
-      await shelf_io.handleRequest(request, commonServerApi.router);
-    } else {
-      await _processDefaultRequest(request);
-    }
-  }
-
-  Future<void> _processOptionsRequest(io.HttpRequest request) async {
-    final statusCode = io.HttpStatus.ok;
-    request.response.statusCode = statusCode;
-    await request.response.close();
-  }
-
-  Future<void> _processReadinessRequest(io.HttpRequest request) async {
-    _logger.info('Processing readiness check');
-    if (proxying) {
-      request.response.statusCode = io.HttpStatus.ok;
-    } else if (!commonServerImpl.isRestarting &&
-        DateTime.now().isBefore(_serveUntil)) {
-      request.response.statusCode = io.HttpStatus.ok;
-    } else {
-      request.response.statusCode = io.HttpStatus.serviceUnavailable;
-      _logger.severe('CommonServer not running - failing readiness check.');
-    }
-
-    await request.response.close();
-  }
-
-  Future<void> _processLivenessRequest(io.HttpRequest request) async {
-    _logger.info('Processing liveness check');
-    if (proxying) {
-      request.response.statusCode = io.HttpStatus.ok;
-    } else if (!commonServerImpl.isHealthy ||
-        DateTime.now().isAfter(_serveUntil)) {
-      _logger.severe('CommonServer is no longer healthy.'
-          ' Intentionally failing health check.');
-      request.response.statusCode = io.HttpStatus.serviceUnavailable;
-    } else {
-      try {
-        final tempDir = await io.Directory.systemTemp.createTemp('healthz');
-        try {
-          final file = io.File('${tempDir.path}/livecheck.txt');
-          await file.writeAsString('testing123\n' * 1000, flush: true);
-          final stat = await file.stat();
-          if (stat.size > 10000) {
-            _logger.info('CommonServer healthy and file system working.'
-                ' Passing health check.');
-            request.response.statusCode = io.HttpStatus.ok;
-          } else {
-            _logger.severe('CommonServer healthy, but filesystem is not.'
-                ' Intentionally failing health check.');
-            request.response.statusCode = io.HttpStatus.serviceUnavailable;
-          }
-        } finally {
-          await tempDir.delete(recursive: true);
-        }
-      } catch (e) {
-        _logger.severe('CommonServer healthy, but failed to create temporary'
-            ' file: $e');
-        request.response.statusCode = io.HttpStatus.serviceUnavailable;
-      }
-    }
-
-    await request.response.close();
-  }
-
-  Future<void> _processDefaultRequest(io.HttpRequest request) async {
-    request.response.statusCode = io.HttpStatus.notFound;
-    await request.response.close();
-  }
-}
-
-class GaeServerContainer implements ServerContainer {
-  @override
-  String get version => io.Platform.version;
-}
diff --git a/pubspec.lock b/pubspec.lock
index 65deb24..e667b2d 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,13 +1,6 @@
 # Generated by pub
 # See https://dart.dev/tools/pub/glossary#lockfile
 packages:
-  _discoveryapis_commons:
-    dependency: transitive
-    description:
-      name: _discoveryapis_commons
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.2.1"
   _fe_analyzer_shared:
     dependency: transitive
     description:
@@ -29,13 +22,6 @@
       url: "https://pub.dartlang.org"
     source: hosted
     version: "0.41.2"
-  appengine:
-    dependency: "direct main"
-    description:
-      name: appengine
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.12.0"
   args:
     dependency: "direct main"
     description:
@@ -218,13 +204,6 @@
       url: "https://pub.dartlang.org"
     source: hosted
     version: "0.10.11"
-  gcloud:
-    dependency: transitive
-    description:
-      name: gcloud
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.7.3"
   glob:
     dependency: transitive
     description:
@@ -232,20 +211,6 @@
       url: "https://pub.dartlang.org"
     source: hosted
     version: "2.0.1"
-  googleapis:
-    dependency: transitive
-    description:
-      name: googleapis
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.56.1"
-  googleapis_auth:
-    dependency: transitive
-    description:
-      name: googleapis_auth
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.2.12+1"
   graphs:
     dependency: transitive
     description:
@@ -260,13 +225,6 @@
       url: "https://pub.dartlang.org"
     source: hosted
     version: "0.9.0"
-  grpc:
-    dependency: transitive
-    description:
-      name: grpc
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.8.0"
   http:
     dependency: "direct main"
     description:
@@ -274,13 +232,6 @@
       url: "https://pub.dartlang.org"
     source: hosted
     version: "0.12.2"
-  http2:
-    dependency: transitive
-    description:
-      name: http2
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.0.1"
   http_methods:
     dependency: transitive
     description:
@@ -302,13 +253,6 @@
       url: "https://pub.dartlang.org"
     source: hosted
     version: "3.1.4"
-  http_server:
-    dependency: transitive
-    description:
-      name: http_server
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.9.8+3"
   io:
     dependency: transitive
     description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 450b715..80d041b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -8,7 +8,6 @@
 dependencies:
   analysis_server_lib: ^0.1.4
   analyzer: ^0.41.2
-  appengine: ^0.12.0
   args: ^2.0.0
   bazel_worker: ^0.1.23
   crypto: ^2.0.0
diff --git a/tool/grind.dart b/tool/grind.dart
index 8bca75a..0a28b09 100644
--- a/tool/grind.dart
+++ b/tool/grind.dart
@@ -57,20 +57,23 @@
   ]);
 }
 
-final _dockerVersionMatcher = RegExp(r'^FROM google/dart-runtime:(.*)$');
+const _dartImageName = 'google/dart';
+final _dockerVersionMatcher = RegExp('^FROM $_dartImageName:(.*)\$');
+const _dockerFileName = 'cloud_run.Dockerfile';
 
 @Task('Update the docker and SDK versions')
 void updateDockerVersion() {
   final platformVersion = Platform.version.split(' ').first;
-  final dockerImageLines = File('Dockerfile').readAsLinesSync().map((String s) {
+  final dockerFile = File(_dockerFileName);
+  final dockerImageLines = dockerFile.readAsLinesSync().map((String s) {
     if (s.contains(_dockerVersionMatcher)) {
-      return 'FROM google/dart-runtime:$platformVersion';
+      return 'FROM $_dartImageName:$platformVersion';
     }
     return s;
   }).toList();
   dockerImageLines.add('');
 
-  File('Dockerfile').writeAsStringSync(dockerImageLines.join('\n'));
+  dockerFile.writeAsStringSync(dockerImageLines.join('\n'));
 }
 
 final List<String> compilationArtifacts = [
@@ -303,7 +306,7 @@
 @Depends(sdkInit, updateDockerVersion, generateProtos, analyze, test, fuzz,
     validateStorageArtifacts)
 void deploy() {
-  log('Run: gcloud app deploy --project=dart-services --no-promote');
+  log('Deploy via Google Cloud Console');
 }
 
 @Task()