1 | 'use strict';
|
2 |
|
3 | const CoreObject = require('core-object');
|
4 | const chalk = require('chalk');
|
5 | const debug = require('debug')('ember-try:task:try-each');
|
6 | const runCommand = require('./../utils/run-command');
|
7 |
|
8 | module.exports = CoreObject.extend({
|
9 | async run(scenarios, options) {
|
10 |
|
11 | let ScenarioManager = require('./../utils/scenario-manager');
|
12 | let DependencyManagerAdapterFactory = require('./../utils/dependency-manager-adapter-factory');
|
13 | this.ResultSummary = require('./../utils/result-summary');
|
14 |
|
15 | let dependencyManagerAdapters =
|
16 | this.dependencyManagerAdapters ||
|
17 | DependencyManagerAdapterFactory.generateFromConfig(this.config, this.project.root);
|
18 | debug(
|
19 | 'DependencyManagerAdapters: %s',
|
20 | dependencyManagerAdapters.map((item) => {
|
21 | return item.configKey;
|
22 | })
|
23 | );
|
24 | this.ScenarioManager = new ScenarioManager({
|
25 | ui: this.ui,
|
26 | dependencyManagerAdapters,
|
27 | });
|
28 |
|
29 | this._canceling = false;
|
30 | this._on('SIGINT', () => {
|
31 | this._canceling = true;
|
32 | this.ui.writeLine('\nGracefully shutting down from SIGINT (Ctrl-C)');
|
33 | return this.ScenarioManager.cleanup();
|
34 | });
|
35 |
|
36 | try {
|
37 | await this.ScenarioManager.setup();
|
38 | debug('Scenario Manager setup');
|
39 |
|
40 | let results = [];
|
41 | for (let scenario of scenarios) {
|
42 | results.push(await this._runCommandForThisScenario(scenario));
|
43 | }
|
44 |
|
45 | await this._optionallyCleanup(options);
|
46 |
|
47 | debug('Output results');
|
48 | this._printResults(results);
|
49 |
|
50 | return this._exitAsAppropriate(results);
|
51 | } catch (err) {
|
52 | this.ui.writeLine(chalk.red('Error!'));
|
53 |
|
54 | if (err) {
|
55 | this.ui.writeLine(chalk.red(err));
|
56 | this.ui.writeLine(chalk.red(err.stack));
|
57 | }
|
58 |
|
59 | return 1;
|
60 | }
|
61 | },
|
62 |
|
63 | async _runCommandForThisScenario(scenario) {
|
64 | if (this._canceling) {
|
65 | return;
|
66 | }
|
67 |
|
68 | let scenarioDependencyState = await this.ScenarioManager.changeTo(scenario);
|
69 |
|
70 | if (this._canceling) {
|
71 | return;
|
72 | }
|
73 |
|
74 | process.env.EMBER_TRY_CURRENT_SCENARIO = scenario.name;
|
75 | this._writeHeader(`Scenario: ${scenario.name}`);
|
76 |
|
77 | let command = this._determineCommandFor(scenario);
|
78 | let runResults = {
|
79 | scenario: scenario.name,
|
80 | allowedToFail: !!scenario.allowedToFail,
|
81 | dependencyState: scenarioDependencyState,
|
82 | envState: scenario.env,
|
83 | command: command.join(' '),
|
84 | };
|
85 |
|
86 | debug('With:\n', runResults);
|
87 |
|
88 | let result = await this._runCommand({
|
89 | commandArgs: command,
|
90 | commandOptions: this._commandOptions(scenario.env),
|
91 | });
|
92 |
|
93 | if (this._canceling) {
|
94 | return;
|
95 | }
|
96 |
|
97 | runResults.result = result;
|
98 | this._writeFooter(`Result: ${result}`);
|
99 |
|
100 | return runResults;
|
101 | },
|
102 |
|
103 | _writeHeader(text) {
|
104 | let count = 75 - text.length;
|
105 | let separator = new Array(count + 1).join('=');
|
106 | this.ui.writeLine(chalk.blue(`\n=== ${text} ${separator}\n`));
|
107 | },
|
108 |
|
109 | _writeFooter(text) {
|
110 | this.ui.writeLine(chalk.blue(`\n${text}`));
|
111 | this.ui.writeLine(chalk.blue('---\n'));
|
112 | },
|
113 |
|
114 | _determineCommandFor(scenario) {
|
115 | if (this.commandArgs && this.commandArgs.length) {
|
116 | return this.commandArgs;
|
117 | }
|
118 |
|
119 | if (scenario.command) {
|
120 | return scenario.command.split(' ');
|
121 | }
|
122 |
|
123 | if (this.config.command) {
|
124 | return this.config.command.split(' ');
|
125 | }
|
126 |
|
127 | return this._defaultCommandArgs();
|
128 | },
|
129 |
|
130 | _runCommand(options) {
|
131 | return runCommand(this.project.root, options.commandArgs, options.commandOptions);
|
132 | },
|
133 |
|
134 | _commandOptions(env) {
|
135 | let options = this.commandOptions || {};
|
136 | if (env) {
|
137 | options.env = Object.assign({}, process.env, env);
|
138 | }
|
139 | return options;
|
140 | },
|
141 |
|
142 | _defaultCommandArgs() {
|
143 | return ['ember', 'test'];
|
144 | },
|
145 |
|
146 | _printResults(results) {
|
147 | new this.ResultSummary({ ui: this.ui, results }).print();
|
148 | },
|
149 |
|
150 | _exitAsAppropriate(results) {
|
151 | let outcomes = results.map((result) => {
|
152 | return result.result || result.allowedToFail;
|
153 | });
|
154 |
|
155 | return this._exitBasedOnCondition(outcomes.indexOf(false) > -1);
|
156 | },
|
157 |
|
158 | async _optionallyCleanup(options) {
|
159 | debug('Cleanup');
|
160 | delete process.env.EMBER_TRY_CURRENT_SCENARIO;
|
161 |
|
162 | if (options && options.skipCleanup) {
|
163 |
|
164 | debug('Skip ScenarioManager cleanup');
|
165 | } else {
|
166 | debug('Cleanup ScenarioManager');
|
167 | return await this.ScenarioManager.cleanup();
|
168 | }
|
169 | },
|
170 |
|
171 | _exitBasedOnCondition(condition) {
|
172 | let exitCode = condition ? 1 : 0;
|
173 | debug('Exit %s', exitCode);
|
174 | return exitCode;
|
175 | },
|
176 |
|
177 | _exit(code) {
|
178 | debug('Exit %s', code);
|
179 | process.exit(code);
|
180 | },
|
181 |
|
182 | _on(signal, fn) {
|
183 | process.on(signal, fn);
|
184 | },
|
185 | });
|