Repository: ember-cli/ember-cli
Pull request #8678 (2019-06-04 18:04:19)

give ember-cli a progress indicator
learnings from: https://github.com/stefanpenner/ember-cli-progress
asciinema: https://asciinema.org/a/jYyqWp3096aWqUgNNSnBo9hb2

I have been running this in several non-trivial apps for the last few months, so far the feedback has been positive and we have not been running into any issues. So I would like to propose adding the functionality directly to ember-cli. 

- [x] feedback

Plan (assuming accepted):

- [x] deprecate https://github.com/stefanpenner/ember-cli-progress
- [x] change ember-cli-progress to warn + disable itself if a new version of cli with built-in progress is used.


Patch:
diff --git a/lib/models/builder.js b/lib/models/builder.js
index cdaa13474..1324b8f93 100644
--- a/lib/models/builder.js
+++ b/lib/models/builder.js
@@ -12,6 +12,7 @@ const _resetTreeCache = require('./addon')._resetTreeCache;
 const Sync = require('tree-sync');
 const heimdall = require('heimdalljs');
 const { isExperimentEnabled } = require('../experiments');
+const progress = require('../utilities/heimdall-progress');
 
 /**
  * Wrapper for the Broccoli [Builder](https://github.com/broccolijs/broccoli/blob/master/lib/builder.js) class.
@@ -209,6 +210,12 @@ class Builder extends CoreObject {
       }
     }
 
+    this.ui.startProgress(progress.format(progress()));
+
+    const intervalID = setInterval(() => {
+      this.ui.spinner.text = progress.format(progress());
+    }, this.ui.spinner.interval);
+
     return this.processAddonBuildSteps('preBuild')
       .then(() => this.builder.build(this.broccoliBuilderFallback ? addWatchDirCallback : null))
       .then(this.compatNode.bind(this), this.compatBroccoliPayload.bind(this))
@@ -226,6 +233,10 @@ class Builder extends CoreObject {
         }
       )
       .then(this.checkForPostBuildEnvironmentIssues.bind(this))
+      .finally(() => {
+        clearInterval(intervalID);
+        this.ui.stopProgress();
+      })
       .catch(error => {
         this.processAddonBuildSteps('buildError', error);
         throw error;
diff --git a/lib/utilities/heimdall-progress.js b/lib/utilities/heimdall-progress.js
new file mode 100644
index 000000000..ee9eb7702
--- /dev/null
+++ b/lib/utilities/heimdall-progress.js
@@ -0,0 +1,19 @@
+'use strict';
+
+module.exports = function progress(heimdalljs = require('heimdalljs')) {
+  let current = heimdalljs.current;
+  const stack = [current.id.name];
+
+  while (current = current.parent) { // eslint-disable-line
+    stack.push(current.id.name);
+  }
+
+  return stack
+    .filter(name => name !== 'heimdall')
+    .reverse()
+    .join(' > ');
+};
+
+module.exports.format = function(text) {
+  return require('chalk').green('building... ') + (text ? `[${text}]` : '');
+};


Test patch:
diff --git a/tests/unit/models/builder-test.js b/tests/unit/models/builder-test.js
index e670b2ec1..028ce5fc8 100644
--- a/tests/unit/models/builder-test.js
+++ b/tests/unit/models/builder-test.js
@@ -343,6 +343,7 @@ describe('models/builder.js', function() {
           return Promise.resolve(buildResults);
         },
         project,
+        ui: project.ui,
       });
 
       buildResults = {
diff --git a/tests/unit/utilities/heimdall-progres-test.js b/tests/unit/utilities/heimdall-progres-test.js
new file mode 100644
index 000000000..9c29a33f7
--- /dev/null
+++ b/tests/unit/utilities/heimdall-progres-test.js
@@ -0,0 +1,55 @@
+'use strict';
+const progress = require('../../../lib/utilities/heimdall-progress');
+const { expect } = require('chai');
+const chalk = require('chalk');
+
+describe('heimdall-progress', function() {
+  it('supports the root node', function() {
+    // fake the heimdall graph (public heimdall API);
+    const heimdall = {
+      current: {
+        id: {
+          name: 'heimdall',
+        },
+      },
+    };
+
+    expect(progress(heimdall)).to.eql('');
+  });
+
+  it('complex example', function() {
+    // fake the heimdall graph (public heimdall API);
+    const heimdall = {
+      current: {
+        id: {
+          name: 'applyPatches',
+        },
+
+        parent: {
+          id: {
+            name: 'babel',
+          },
+          parent: {
+            id: {
+              name: 'broccoli',
+            },
+
+            parent: {
+              id: {
+                name: 'heimdall',
+              },
+            },
+          },
+        },
+      },
+    };
+
+    expect(progress(heimdall)).to.eql('broccoli > babel > applyPatches');
+  });
+
+  describe('.format', function() {
+    it('works', function() {
+      expect(progress.format('test content')).to.eql(`${chalk.green('building... ')}[test content]`);
+    });
+  });
+});