Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/cli/fixtures/fixtures_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:celest/src/runtime/serve.dart';
import 'package:celest_ast/celest_ast.dart' as ast;
import 'package:celest_cli/src/analyzer/analysis_result.dart';
import 'package:celest_cli/src/analyzer/celest_analyzer.dart';
import 'package:celest_cli/src/cli/stop_signal.dart';
import 'package:celest_cli/src/codegen/client_code_generator.dart';
import 'package:celest_cli/src/codegen/cloud_code_generator.dart';
import 'package:celest_cli/src/compiler/api/local_api_runner.dart';
Expand Down Expand Up @@ -407,7 +408,7 @@ class TestRunner {
expect(errors, isEmpty);
expect(project, isNotNull);

final frontend = CelestFrontend();
final frontend = CelestFrontend(stopSignal: StopSignal());
final buildDir = fileSystem.directory(projectPaths.buildDir);
if (buildDir.existsSync()) {
buildDir.deleteSync(recursive: true);
Expand Down
2 changes: 2 additions & 0 deletions apps/cli/fixtures/standalone/api/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ dependency_overrides:
path: ../../../../../packages/celest_cloud
celest_cloud_auth:
path: ../../../../../services/celest_cloud_auth
celest_cloud_core:
path: ../../../../../services/celest_cloud_core
celest_core:
path: ../../../../../packages/celest_core

Expand Down
2 changes: 2 additions & 0 deletions apps/cli/fixtures/standalone/auth/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ dependency_overrides:
path: ../../../../../packages/celest_cloud
celest_cloud_auth:
path: ../../../../../services/celest_cloud_auth
celest_cloud_core:
path: ../../../../../services/celest_cloud_core
celest_core:
path: ../../../../../packages/celest_core

Expand Down
2 changes: 2 additions & 0 deletions apps/cli/fixtures/standalone/data/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ dependency_overrides:
path: ../../../../../packages/celest_cloud
celest_cloud_auth:
path: ../../../../../services/celest_cloud_auth
celest_cloud_core:
path: ../../../../../services/celest_cloud_core
celest_core:
path: ../../../../../packages/celest_core

Expand Down
2 changes: 2 additions & 0 deletions apps/cli/fixtures/standalone/env_vars/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ dependency_overrides:
path: ../../../../../packages/celest_cloud
celest_cloud_auth:
path: ../../../../../services/celest_cloud_auth
celest_cloud_core:
path: ../../../../../services/celest_cloud_core
celest_core:
path: ../../../../../packages/celest_core
dev_dependencies:
Expand Down
2 changes: 2 additions & 0 deletions apps/cli/fixtures/standalone/exceptions/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ dependency_overrides:
path: ../../../../../packages/celest_cloud
celest_cloud_auth:
path: ../../../../../services/celest_cloud_auth
celest_cloud_core:
path: ../../../../../services/celest_cloud_core
celest_core:
path: ../../../../../packages/celest_core

Expand Down
2 changes: 2 additions & 0 deletions apps/cli/fixtures/standalone/flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ dependency_overrides:
path: ../../../../../packages/celest_cloud
celest_cloud_auth:
path: ../../../../../services/celest_cloud_auth
celest_cloud_core:
path: ../../../../../services/celest_cloud_core
celest_core:
path: ../../../../../packages/celest_core
celest:
Expand Down
2 changes: 2 additions & 0 deletions apps/cli/fixtures/standalone/http/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ dependency_overrides:
path: ../../../../../packages/celest_cloud
celest_cloud_auth:
path: ../../../../../services/celest_cloud_auth
celest_cloud_core:
path: ../../../../../services/celest_cloud_core
celest_core:
path: ../../../../../packages/celest_core

Expand Down
2 changes: 2 additions & 0 deletions apps/cli/fixtures/standalone/marcelo/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ dependency_overrides:
path: ../../../../../packages/celest_cloud
celest_cloud_auth:
path: ../../../../../services/celest_cloud_auth
celest_cloud_core:
path: ../../../../../services/celest_cloud_core
celest_core:
path: ../../../../../packages/celest_core
dev_dependencies:
Expand Down
2 changes: 2 additions & 0 deletions apps/cli/fixtures/standalone/streaming/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ dependency_overrides:
path: ../../../../../packages/celest_cloud
celest_cloud_auth:
path: ../../../../../services/celest_cloud_auth
celest_cloud_core:
path: ../../../../../services/celest_cloud_core
celest_core:
path: ../../../../../packages/celest_core

Expand Down
28 changes: 28 additions & 0 deletions apps/cli/lib/src/cli/stop_signal.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'dart:async';
import 'dart:io';

import 'package:celest_cli/src/exceptions.dart';

/// {@template celest.cli.stop_signal}
/// Signals that a `SIGINT` or `SIGTERM` event has fired and the CLI needs to
/// shutdown.
/// {@endtemplate}
extension type StopSignal._(Completer<ProcessSignal> _it) {
factory StopSignal() => StopSignal._(Completer<ProcessSignal>.sync());

Future<ProcessSignal> get future => _it.future;

void complete(ProcessSignal signal) => _it.complete(signal);

/// Whether a SIGINT or SIGTERM signal has been received and the frontend
/// is no longer operational.
bool get isStopped => _it.isCompleted;

/// Checks if the signal has been received and throws a [CancellationException]
/// if it has.
void check() {
if (isStopped) {
throw const CancellationException('Celest was interrupted');
}
}
}
26 changes: 26 additions & 0 deletions apps/cli/lib/src/commands/celest_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import 'dart:convert';
import 'dart:io';

import 'package:args/command_runner.dart';
import 'package:async/async.dart';
import 'package:celest_cli/src/cli/cli_runtime.dart';
import 'package:celest_cli/src/cli/stop_signal.dart';
import 'package:celest_cli/src/commands/auth/auth_command.dart';
import 'package:celest_cli/src/context.dart';
import 'package:celest_cli/src/models.dart';
Expand All @@ -19,6 +21,22 @@ import 'package:pub_semver/pub_semver.dart';

/// Base class for all commands in this package providing common functionality.
abstract base class CelestCommand extends Command<int> {
CelestCommand() {
// Initialize immediately instead of lazily since _stopSub is never accessed
// directly until `close`.
_stopSub = StreamGroup.merge([
ProcessSignal.sigint.watch(),
// SIGTERM is not supported on Windows. Attempting to register a SIGTERM
// handler raises an exception.
if (!Platform.isWindows) ProcessSignal.sigterm.watch(),
]).listen((signal) {
logger.fine('Got exit signal: $signal');
if (!stopSignal.isStopped) {
stopSignal.complete(signal);
}
});
}

late final Logger logger = Logger(name);

/// The version of the CLI.
Expand Down Expand Up @@ -115,6 +133,13 @@ abstract base class CelestCommand extends Command<int> {
)!;
}

/// {@macro celest.cli.stop_signal}
final stopSignal = StopSignal();

/// Subscription to [ProcessSignal.sigint] and [ProcessSignal.sigterm] which
/// forwards to [stopSignal] when triggered.
late final StreamSubscription<ProcessSignal> _stopSub;

@override
@mustCallSuper
Future<int> run() async {
Expand Down Expand Up @@ -147,6 +172,7 @@ abstract base class CelestCommand extends Command<int> {
@mustCallSuper
Future<void> close() async {
await Future.wait([
_stopSub.cancel(),
for (final deferred in _deferred) Future.value(deferred()),
]);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/cli/lib/src/commands/project/build_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ final class BuildCommand extends CelestCommand

final needsMigration = await configure();

return CelestFrontend().build(
return CelestFrontend(stopSignal: stopSignal).build(
migrateProject: needsMigration,
currentProgress: cliLogger.progress('Building project'),
environmentId: 'production', // TODO(dnys1): Allow setting environment
Expand Down
3 changes: 2 additions & 1 deletion apps/cli/lib/src/commands/project/deploy_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ final class DeployCommand extends CelestCommand
return code;
}

return CelestFrontend().deploy(migrateProject: needsMigration);
return CelestFrontend(stopSignal: stopSignal)
.deploy(migrateProject: needsMigration);
}
}
64 changes: 11 additions & 53 deletions apps/cli/lib/src/commands/project/init_command.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import 'dart:io';

import 'package:celest_cli/src/cli/cli_runtime.dart';
import 'package:celest_cli/src/commands/auth/authenticate.dart';
import 'package:celest_cli/src/commands/celest_command.dart';
import 'package:celest_cli/src/context.dart';
import 'package:celest_cli/src/init/project_creator.dart';
import 'package:celest_cli/src/init/project_init.dart';
import 'package:celest_cli/src/repositories/cloud_repository.dart';
import 'package:mason_logger/mason_logger.dart';

final class InitCommand extends CelestCommand with Configure, ProjectCreator {
final class InitCommand extends CelestCommand
with Configure, ProjectCreator, Authenticate, CloudRepository {
InitCommand() {
argParser.addFlag(
'precache',
help: 'Precache assets and warm up analyzer in the background.',
negatable: true,
hide: true,
defaultsTo: true,
);
argParser.addOption(
'template',
abbr: 't',
Expand All @@ -26,6 +22,10 @@ final class InitCommand extends CelestCommand with Configure, ProjectCreator {
},
defaultsTo: 'hello',
);
argParser.addOption(
'name',
help: 'The project name.',
);
}

@override
Expand All @@ -43,57 +43,15 @@ final class InitCommand extends CelestCommand with Configure, ProjectCreator {
@override
late final String template = argResults!.option('template')!;

/// Precache assets in the background.
Future<void> _precacheInBackground() async {
final command = switch (CliRuntime.current) {
CliRuntime.pubGlobal => <String>[
platform.resolvedExecutable,
'pub',
'global',
'run',
'celest_cli:celest',
'precache',
projectPaths.projectRoot,
if (verbose) '--verbose',
],
CliRuntime.local => <String>[
platform.resolvedExecutable,
platform.script.toFilePath(),
'precache',
projectPaths.projectRoot,
if (verbose) '--verbose',
],
CliRuntime.aot => <String>[
platform.resolvedExecutable,
'precache',
projectPaths.projectRoot,
if (verbose) '--verbose',
],
};
try {
logger.fine('Precaching assets in background...');
await processManager.start(
command,
mode: ProcessStartMode.detached,
workingDirectory: projectPaths.projectRoot,
);
} on Object catch (e, st) {
logger.fine('Failed to precache assets', e, st);
performance.captureError(e, stackTrace: st, extra: {'command': command});
}
}

bool get precache => argResults!.flag('precache');
@override
String? get projectName => argResults!.option('name');

@override
Future<int> run() async {
await super.run();

await checkForLatestVersion();
await configure();
if (precache) {
await _precacheInBackground();
}

final projectRoot = projectPaths.projectRoot;

Expand Down
3 changes: 2 additions & 1 deletion apps/cli/lib/src/commands/project/start_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:celest_cli/src/commands/celest_command.dart';
import 'package:celest_cli/src/context.dart';
import 'package:celest_cli/src/frontend/celest_frontend.dart';
import 'package:celest_cli/src/frontend/child_process.dart';
import 'package:celest_cli/src/init/project_creator.dart';
import 'package:celest_cli/src/init/project_init.dart';
import 'package:celest_cli/src/init/project_migrate.dart';
import 'package:mason_logger/mason_logger.dart';
Expand Down Expand Up @@ -53,7 +54,7 @@ final class StartCommand extends CelestCommand
}

// Start the Celest Frontend Loop
return CelestFrontend().run(
return CelestFrontend(stopSignal: stopSignal).run(
migrateProject: needsMigration,
currentProgress: currentProgress,
childProcess: childProcess,
Expand Down
Loading