Repository: VeryGoodOpenSource/very_good_cli (dart)

Issue:
feat: Install Dependencies Automatically
**Description**
(More like an improvement than a bug) Creating a new project is not running `flutter pub get` to install dependencies automatically.

**Steps To Reproduce**
1. Create a new project: `very_good create hello`
2. Open with vscode
3. Need to run `flutter pub get` manually

**Expected Behavior**
When creating the project, automatically install the dependencies from `pubspec.yaml`

**Additional Context**
Only want to say, awesome work! thanks for sharing with the community this powerful CLI.

Pull request description:
<!--
  Thanks for contributing!

  Provide a description of your changes below and a general summary in the title

  Please look at the following checklist to ensure that your PR can be accepted quickly:
-->

## Description

<!--- Describe your changes in detail -->
- feat: install packages automatically (closes #90)
- ci: generate new project and run tests on the newly generated project

Running `very_good create my_app` will now do the following:

1. Bootstrap the project
2. Check if Flutter is installed (NEW)
3. If Flutter is installed, run flutter packages get (NEW)
4. Output summary of generated files

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [X] ✨ New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
- [ ] 🧹 Code refactor
- [X] ✅ Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore

Patch:
diff --git a/.github/workflows/very_good_cli.yaml b/.github/workflows/very_good_cli.yaml
index 49c46e1a7..501932372 100644
--- a/.github/workflows/very_good_cli.yaml
+++ b/.github/workflows/very_good_cli.yaml
@@ -21,24 +21,22 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2.3.4
-      - uses: dart-lang/setup-dart@v1
+      - uses: subosito/flutter-action@v1.5.0
 
       - name: Install Dependencies
-        run: dart pub get
+        run: flutter pub get
 
       - name: Format
-        run: dart format --set-exit-if-changed .
+        run: flutter format --set-exit-if-changed .
 
       - name: Analyze
-        run: |
-          dart analyze --fatal-infos --fatal-warnings lib
-          dart analyze --fatal-infos --fatal-warnings test
+        run: flutter analyze lib test
 
       - name: Verify Build
-        run: dart test --run-skipped -t pull-request-only
+        run: flutter pub run test --run-skipped -t pull-request-only
 
       - name: Run Tests
-        run: dart test -x pull-request-only --coverage=coverage && pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.packages --report-on=lib
+        run: flutter test -x pull-request-only --no-pub --coverage --test-randomize-ordering-seed random
 
       - name: Check Code Coverage
         uses: VeryGoodOpenSource/very_good_coverage@v1.1.1
diff --git a/lib/src/commands/create.dart b/lib/src/commands/create.dart
index a94bf4b89..ed591912d 100644
--- a/lib/src/commands/create.dart
+++ b/lib/src/commands/create.dart
@@ -9,6 +9,7 @@ import 'package:universal_io/io.dart';
 import 'package:usage/usage_io.dart';
 import 'package:very_good_analysis/very_good_analysis.dart';
 import 'package:very_good_cli/src/command_runner.dart';
+import 'package:very_good_cli/src/flutter_cli.dart';
 import 'package:very_good_cli/src/templates/very_good_core_bundle.dart';
 
 // A valid Dart identifier that can be used for a package, i.e. no
@@ -72,8 +73,17 @@ class CreateCommand extends Command<int> {
       DirectoryGeneratorTarget(outputDirectory, _logger),
       vars: {'project_name': projectName},
     );
-
     generateDone('Bootstrapping complete');
+
+    final isFlutterInstalled = await Flutter.installed();
+    if (isFlutterInstalled) {
+      final installDependenciesDone = _logger.progress(
+        'Running "flutter packages get" in ${outputDirectory.path}',
+      );
+      await Flutter.packagesGet(outputDirectory.path);
+      installDependenciesDone();
+    }
+
     _logSummary(fileCount);
 
     unawaited(_analytics.sendEvent(
diff --git a/lib/src/flutter_cli.dart b/lib/src/flutter_cli.dart
new file mode 100644
index 000000000..3570efff0
--- /dev/null
+++ b/lib/src/flutter_cli.dart
@@ -0,0 +1,56 @@
+import 'package:universal_io/io.dart';
+
+/// Flutter CLI
+class Flutter {
+  /// Install flutter dependencies (`flutter packages get`).
+  static Future<void> packagesGet([String? cwd]) {
+    return _Cmd.run('flutter', ['packages', 'get'], workingDirectory: cwd);
+  }
+
+  /// Determine whether flutter is installed
+  static Future<bool> installed() async {
+    try {
+      await _Cmd.run('flutter', []);
+      return true;
+    } catch (_) {
+      return false;
+    }
+  }
+}
+
+class _Cmd {
+  static Future<ProcessResult> run(
+    String cmd,
+    List<String> args, {
+    bool throwOnError = true,
+    String? workingDirectory,
+  }) async {
+    final result = await Process.run(cmd, args,
+        workingDirectory: workingDirectory, runInShell: true);
+
+    if (throwOnError) {
+      _throwIfProcessFailed(result, cmd, args);
+    }
+    return result;
+  }
+
+  static void _throwIfProcessFailed(
+    ProcessResult pr,
+    String process,
+    List<String> args,
+  ) {
+    if (pr.exitCode != 0) {
+      final values = {
+        'Standard out': pr.stdout.toString().trim(),
+        'Standard error': pr.stderr.toString().trim()
+      }..removeWhere((k, v) => v.isEmpty);
+
+      var message = 'Unknown error';
+      if (values.isNotEmpty) {
+        message = values.entries.map((e) => '${e.key}\n${e.value}').join('\n');
+      }
+
+      throw ProcessException(process, args, message, pr.exitCode);
+    }
+  }
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index f18bf9dc8..a980966f8 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -20,7 +20,6 @@ dev_dependencies:
   build_runner: ^2.0.0
   build_verify: ^2.0.0
   build_version: ^2.0.0
-  coverage: ^1.0.2
   mocktail: ^0.1.1
   test: ^1.17.0
 


Test patch:
diff --git a/test/src/commands/create_test.dart b/test/src/commands/create_test.dart
index 529737e88..dc7c02189 100644
--- a/test/src/commands/create_test.dart
+++ b/test/src/commands/create_test.dart
@@ -107,10 +107,12 @@ void main() {
       final result = await command.run();
       expect(result, equals(ExitCode.success.code));
       verify(() => logger.progress('Bootstrapping')).called(1);
-      verify(() => logger.info(
-            '${lightGreen.wrap('✓')} '
-            'Generated 62 file(s):',
-          ));
+      verify(
+        () => logger.info(
+          '${lightGreen.wrap('✓')} '
+          'Generated 62 file(s):',
+        ),
+      );
       verify(() => logger.alert('Created a Very Good App! 🦄')).called(1);
       verify(
         () => generator.generate(
diff --git a/test/src/flutter_cli_test.dart b/test/src/flutter_cli_test.dart
new file mode 100644
index 000000000..e219ba5c4
--- /dev/null
+++ b/test/src/flutter_cli_test.dart
@@ -0,0 +1,20 @@
+import 'package:test/test.dart';
+import 'package:universal_io/io.dart';
+import 'package:very_good_cli/src/flutter_cli.dart';
+
+void main() {
+  group('Flutter CLI', () {
+    group('packages get', () {
+      test('throws when there is no pubspec.yaml', () {
+        expectLater(
+          Flutter.packagesGet(Directory.systemTemp.path),
+          throwsException,
+        );
+      });
+
+      test('completes when there is a pubspec.yaml', () {
+        expectLater(Flutter.packagesGet(), completes);
+      });
+    });
+  });
+}