diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a943443..e5e625a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 1.3.1 +* Add `deploy nginx` and `deploy systemd`. + # 1.3.0 * Focus on Dart2 from here on out. * Update `code_builder`. diff --git a/bin/angel.dart b/bin/angel.dart index 2c510a07..bdeddff4 100644 --- a/bin/angel.dart +++ b/bin/angel.dart @@ -20,6 +20,7 @@ main(List args) async { .addFlag('verbose', help: 'Print verbose output.', negatable: false); runner + ..addCommand(new DeployCommand()) ..addCommand(new DoctorCommand()) ..addCommand(new KeyCommand()) ..addCommand(new InitCommand()) diff --git a/lib/src/commands/commands.dart b/lib/src/commands/commands.dart index 3cd8fdb7..a6db230d 100644 --- a/lib/src/commands/commands.dart +++ b/lib/src/commands/commands.dart @@ -1,5 +1,6 @@ library angel_cli.commands; +export "deploy.dart"; export "doctor.dart"; export "key.dart"; export "init.dart"; diff --git a/lib/src/commands/deploy.dart b/lib/src/commands/deploy.dart new file mode 100644 index 00000000..92b5f82e --- /dev/null +++ b/lib/src/commands/deploy.dart @@ -0,0 +1,17 @@ +import 'package:args/command_runner.dart'; +import 'deploy/nginx.dart'; +import 'deploy/systemd.dart'; + +class DeployCommand extends Command { + @override + String get name => 'deploy'; + + @override + String get description => + 'Generates scaffolding + helper functionality for deploying servers. Run this in your project root.'; + + DeployCommand() { + addSubcommand(new NginxCommand()); + addSubcommand(new SystemdCommand()); + } +} diff --git a/lib/src/commands/deploy/nginx.dart b/lib/src/commands/deploy/nginx.dart new file mode 100644 index 00000000..638f70ac --- /dev/null +++ b/lib/src/commands/deploy/nginx.dart @@ -0,0 +1,52 @@ +import 'dart:io'; +import 'package:args/command_runner.dart'; +import 'package:io/ansi.dart'; +import 'package:path/path.dart' as p; +import '../../util.dart'; + +class NginxCommand extends Command { + @override + String get name => 'nginx'; + + @override + String get description => + 'Generates a NGINX configuration for a reverse proxy + static server.'; + + NginxCommand() { + argParser.addOption('out', + abbr: 'o', + help: + 'An optional output file to write to; otherwise prints to stdout.'); + } + + @override + run() async { + var webPath = p.join(p.current, 'web'); + var nginxText = ''' +server { + listen 80 default_server; + root ${p.absolute(webPath)}; # Set to your static files directory + + location / { + try_files \$uri @proxy; # Try to serve static files; fallback to proxied Angel server + } + + location @proxy { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; # Important, do not omit + } +} + ''' + .trim(); + + if (!argResults.wasParsed('out')) { + print(nginxText); + } else { + var file = new File(argResults['out'] as String); + await file.create(recursive: true); + await file.writeAsString(nginxText); + print(green.wrap( + "$checkmark Successfully generated nginx configuration in '${file.path}'.")); + } + } +} diff --git a/lib/src/commands/deploy/systemd.dart b/lib/src/commands/deploy/systemd.dart new file mode 100644 index 00000000..4d4114bd --- /dev/null +++ b/lib/src/commands/deploy/systemd.dart @@ -0,0 +1,58 @@ +import 'dart:io'; +import 'package:args/command_runner.dart'; +import 'package:io/ansi.dart'; +import 'package:path/path.dart' as p; +import '../../util.dart'; + +class SystemdCommand extends Command { + @override + String get name => 'systemd'; + + @override + String get description => + 'Generates a systemd service to continuously run your server.'; + + SystemdCommand() { + argParser + ..addOption('user', + abbr: 'u', + defaultsTo: 'web', + help: 'The name of the unprivileged account to run the server as.') + ..addOption('out', + abbr: 'o', + help: + 'An optional output file to write to; otherwise prints to stdout.'); + } + + @override + run() async { + var projectPath = p.absolute(p.current); + var pubspec = await loadPubspec(); + var user = argResults['user']; + var systemdText = ''' +[Unit] +Description=`${pubspec.name}` server + +[Service] +Environment=ANGEL_ENV=production +User=$user # Name of unprivileged `$user` user +WorkingDirectory=$projectPath # Path to `${pubspec.name}` project +ExecStart=${Platform.resolvedExecutable} bin/prod.dart +Restart=always # Restart process on crash + +[Install] +WantedBy=multi-user.target + ''' + .trim(); + + if (!argResults.wasParsed('out')) { + print(systemdText); + } else { + var file = new File(argResults['out'] as String); + await file.create(recursive: true); + await file.writeAsString(systemdText); + print(green.wrap( + "$checkmark Successfully generated systemd service in '${file.path}'.")); + } + } +} diff --git a/lib/src/commands/make/model.dart b/lib/src/commands/make/model.dart index e0a4c7ba..010752e6 100644 --- a/lib/src/commands/make/model.dart +++ b/lib/src/commands/make/model.dart @@ -46,7 +46,6 @@ class ModelCommand extends Command { } List deps = [ - const MakerDependency('angel_framework', '^1.0.0'), const MakerDependency('angel_model', '^1.0.0'), ]; @@ -63,6 +62,8 @@ class ModelCommand extends Command { modelLib.directives.add(new Directive.import( 'package:angel_serialize/angel_serialize.dart')); deps.add(const MakerDependency('angel_serialize', '^2.0.0')); + deps.add(const MakerDependency('angel_serialize_generator', '^2.0.0')); + deps.add(const MakerDependency('build_runner', '">=0.7.0 <0.10.0"')); } if (argResults['orm'] as bool) { diff --git a/pubspec.yaml b/pubspec.yaml index 15cde314..e4bc78a1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ author: Tobe O description: Command-line tools for the Angel framework. homepage: https://github.com/angel-dart/angel_cli name: angel_cli -version: 1.3.0 +version: 1.3.1 dependencies: analyzer: ">=0.32.0" args: ^1.0.0