From 94605c4dfa6a163eddb273cbeae24a3b53111429 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Thu, 18 Mar 2021 00:26:33 +0100 Subject: [PATCH 01/26] Implement WIP approach where we don't display and render large execution result but instead display links to view / download raw result. This way we avoid freezing and blocking the browser when trying to render large execution results. --- apps/st2-history/history-details.component.js | 31 +++++++++--- apps/st2-history/history-panel.component.js | 1 + .../action-reporter.component.js | 49 ++++++++++++++++++- 3 files changed, 74 insertions(+), 7 deletions(-) diff --git a/apps/st2-history/history-details.component.js b/apps/st2-history/history-details.component.js index 56730447a..7cdf58ace 100644 --- a/apps/st2-history/history-details.component.js +++ b/apps/st2-history/history-details.component.js @@ -73,17 +73,36 @@ export default class HistoryDetails extends React.Component { } componentDidUpdate(prevProps) { - const { id } = this.props; + const { id, execution } = this.props; + var reFetchExecution = false; - if (id && id !== prevProps.id) { - this.fetchExecution(id); + if (execution && execution.FETCH_RESULT && !execution.result) { + reFetchExecution = true; + } + + if ((id && id !== prevProps.id) || reFetchExecution) { + this.fetchExecution(id, reFetchExecution); } } - fetchExecution(id) { + fetchExecution(id, includeResult) { + includeResult = includeResult || false; + + var path; + + // NOTE: We don't retrieve result here by defualt because it may be very large. We only retrieve it later + // after we determine the result size. If the result size is too large, we won't display it in + // the output tab since that would freeze the browser, but we will display a link to the raw + // result output instead. + if (includeResult) { + path = `/executions/${id}`; + } else { + path = `/executions/${id}?exclude_attributes=result`; + } + store.dispatch({ type: 'FETCH_EXECUTION', - promise: api.request({ path: `/executions/${id}` }), + promise: api.request({ path: path }), }) .catch((err) => { notification.error(`Unable to retrieve execution "${id}".`, { err }); @@ -183,7 +202,7 @@ export default class HistoryDetails extends React.Component { - + { execution.rule ? ( diff --git a/apps/st2-history/history-panel.component.js b/apps/st2-history/history-panel.component.js index 85438df56..a6999665c 100644 --- a/apps/st2-history/history-panel.component.js +++ b/apps/st2-history/history-panel.component.js @@ -214,6 +214,7 @@ export default class HistoryPanel extends React.Component { 'rule.ref', 'trigger.type', 'context.user', + 'result_size', ], }, raw: true, // so we can extract headers diff --git a/modules/st2-action-reporter/action-reporter.component.js b/modules/st2-action-reporter/action-reporter.component.js index 17fa58870..1d6139af4 100644 --- a/modules/st2-action-reporter/action-reporter.component.js +++ b/modules/st2-action-reporter/action-reporter.component.js @@ -20,21 +20,68 @@ import reporters from './reporters'; import style from './style.css'; +// If action execution result is larger than this value (in bytes) we won't try to render it in +// the code highlighter widget, but display a link to the raw result output instead directly to +// st2api. This way we avoid large results freezing and blocking the browser window +// Can be overriden in the config, but values over 200 KB are not recommended. +// TODO: Do some more research and testing and come up with a good default value +const DEFAULT_MAX_RESULT_SIZE = 200 * 1024; // 200 KB + + export default class ActionReporter extends React.Component { static propTypes = { className: PropTypes.string, runner: PropTypes.string.isRequired, execution: PropTypes.object.isRequired, + foo: PropTypes.string, } render() { - const { className, runner, execution, ...props } = this.props; + const { className, runner, execution, api, ...props } = this.props; const reporter = reporters[runner] || reporters.debug; if (!execution) { return null; } + // TODO: Add methods to the client to retrieve full correct URL? + const viewRawResultUrl = `${window.location.protocol}${api.server.api}/v1/executions/${execution.id}/result?pretty_format=1`; + const downloadRawResultUrl = `${window.location.protocol}${api.server.api}/v1/executions/${execution.id}/result?download=1&pretty_format=1`; + const resultSizeMB = ((execution.result_size / 1024 / 1024)).toFixed(2); + const maxResultSizeForRender = window.st2constants.st2Config.max_execution_result_size_for_render || DEFAULT_MAX_RESULT_SIZE; + + if (execution && execution.result_size && execution.result_size > maxResultSizeForRender) { + return ( +
+
Output
+

+ Action output is too large to be displayed here ({`${resultSizeMB}`} MB).

You can view raw execution output by clicking here or you can download the output by clicking here. +

+
+ ); + } + + // If execution is not too big, we update the attribute to indicate the component to re-fetch the + // execution with the result field + if (!execution.FETCH_RESULT && !execution.result) { + execution.FETCH_RESULT = true; + + return ( +
+
Output
+

Loading execution result...

+
+ ); + } + else if (execution.FETCH_RESULT && !execution.result) { + return ( +
+
Output
+

Loading execution result...

+
+ ); + } + return (
{ reporter(execution) } From 8fbd7c7b8db4490c786f062f6d58537b566bd61b Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 19 Mar 2021 20:20:22 +0100 Subject: [PATCH 02/26] Fix and improve the code. --- apps/st2-history/history-details.component.js | 7 ++++- apps/st2-history/history-panel.component.js | 2 +- .../action-reporter.component.js | 28 +++++++++---------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/apps/st2-history/history-details.component.js b/apps/st2-history/history-details.component.js index 7cdf58ace..f27f6445b 100644 --- a/apps/st2-history/history-details.component.js +++ b/apps/st2-history/history-details.component.js @@ -76,11 +76,16 @@ export default class HistoryDetails extends React.Component { const { id, execution } = this.props; var reFetchExecution = false; - if (execution && execution.FETCH_RESULT && !execution.result) { + if (execution && execution.FETCH_RESULT &&!execution.FETCHING_RESULT && !execution.result) { reFetchExecution = true; } if ((id && id !== prevProps.id) || reFetchExecution) { + if (execution) { + // Indicate we are fetching the result for this execution + execution.FETCHING_RESULT = true; + } + this.fetchExecution(id, reFetchExecution); } } diff --git a/apps/st2-history/history-panel.component.js b/apps/st2-history/history-panel.component.js index a6999665c..b81050997 100644 --- a/apps/st2-history/history-panel.component.js +++ b/apps/st2-history/history-panel.component.js @@ -94,7 +94,7 @@ export default class HistoryPanel extends React.Component { }).isRequired, filter: PropTypes.string, - filters: PropTypes.object, + filters: PropTypes.array, childExecutions: PropTypes.object, groups: PropTypes.array, collapsed: PropTypes.bool, diff --git a/modules/st2-action-reporter/action-reporter.component.js b/modules/st2-action-reporter/action-reporter.component.js index 1d6139af4..8c95927ac 100644 --- a/modules/st2-action-reporter/action-reporter.component.js +++ b/modules/st2-action-reporter/action-reporter.component.js @@ -47,24 +47,30 @@ export default class ActionReporter extends React.Component { // TODO: Add methods to the client to retrieve full correct URL? const viewRawResultUrl = `${window.location.protocol}${api.server.api}/v1/executions/${execution.id}/result?pretty_format=1`; const downloadRawResultUrl = `${window.location.protocol}${api.server.api}/v1/executions/${execution.id}/result?download=1&pretty_format=1`; - const resultSizeMB = ((execution.result_size / 1024 / 1024)).toFixed(2); + const downloadCompressedRawResultUrl = `${window.location.protocol}${api.server.api}/v1/executions/${execution.id}/result?download=1&pretty_format=1&compress=1`; const maxResultSizeForRender = window.st2constants.st2Config.max_execution_result_size_for_render || DEFAULT_MAX_RESULT_SIZE; - if (execution && execution.result_size && execution.result_size > maxResultSizeForRender) { + // For backward compatibility with older executions which may not have result_size attribute + const resultSize = execution.result_size || JSON.stringify(execution.result || {}).length; + const resultSizeMB = ((resultSize / 1024 / 1024)).toFixed(2); + + if (resultSize && resultSize > maxResultSizeForRender) { return (
Output

- Action output is too large to be displayed here ({`${resultSizeMB}`} MB).

You can view raw execution output by clicking here or you can download the output by clicking here. + Action output is too large to be displayed here ({`${resultSizeMB}`} MB).

You can view raw execution output by clicking here or you can download the output by clicking here (uncompressed) or here (compressed).

); } - // If execution is not too big, we update the attribute to indicate the component to re-fetch the - // execution with the result field - if (!execution.FETCH_RESULT && !execution.result) { - execution.FETCH_RESULT = true; + if (!execution.result) { + if (!execution.FETCH_RESULT) { + // If execution is not too big, we update the attribute to indicate the component to re-fetch the + // execution with the result field + execution.FETCH_RESULT = true; + } return (
@@ -73,14 +79,6 @@ export default class ActionReporter extends React.Component {
); } - else if (execution.FETCH_RESULT && !execution.result) { - return ( -
-
Output
-

Loading execution result...

-
- ); - } return (
From 09318b12531ef7b82663e5f19059e791ecef1ba6 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 19 Mar 2021 21:08:45 +0100 Subject: [PATCH 03/26] Improve API url handling. --- .../action-reporter.component.js | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/modules/st2-action-reporter/action-reporter.component.js b/modules/st2-action-reporter/action-reporter.component.js index 8c95927ac..533b15b60 100644 --- a/modules/st2-action-reporter/action-reporter.component.js +++ b/modules/st2-action-reporter/action-reporter.component.js @@ -28,12 +28,36 @@ import style from './style.css'; const DEFAULT_MAX_RESULT_SIZE = 200 * 1024; // 200 KB +function getBaseAPIUrl(api) { + // Return base URL to the api instance + if (!api.server) { + console.log("config.js is not correctlu configured - it's missing API server URL entry") + return null; + } + + if (!api.server.api) { + console.log("config.js is not correctlu configured - it's missing API server URL entry") + return null; + } + + var url = api.server.api; + var baseUrl; + + if (!url.startsWith("http://") && !(url.startsWith("https://"))) { + baseUrl = `${window.location.protocol}${url}`; + } + else { + baseUrl = `${url}`; + } + + return baseUrl; +} + export default class ActionReporter extends React.Component { static propTypes = { className: PropTypes.string, runner: PropTypes.string.isRequired, execution: PropTypes.object.isRequired, - foo: PropTypes.string, } render() { @@ -45,9 +69,10 @@ export default class ActionReporter extends React.Component { } // TODO: Add methods to the client to retrieve full correct URL? - const viewRawResultUrl = `${window.location.protocol}${api.server.api}/v1/executions/${execution.id}/result?pretty_format=1`; - const downloadRawResultUrl = `${window.location.protocol}${api.server.api}/v1/executions/${execution.id}/result?download=1&pretty_format=1`; - const downloadCompressedRawResultUrl = `${window.location.protocol}${api.server.api}/v1/executions/${execution.id}/result?download=1&pretty_format=1&compress=1`; + const baseApiUrl = getBaseAPIUrl(api); + const viewRawResultUrl = `${baseApiUrl}/v1/executions/${execution.id}/result?pretty_format=1`; + const downloadRawResultUrl = `${baseApiUrl}/v1/executions/${execution.id}/result?download=1&pretty_format=1`; + const downloadCompressedRawResultUrl = `${baseApiUrl}/v1/executions/${execution.id}/result?download=1&pretty_format=1&compress=1`; const maxResultSizeForRender = window.st2constants.st2Config.max_execution_result_size_for_render || DEFAULT_MAX_RESULT_SIZE; // For backward compatibility with older executions which may not have result_size attribute @@ -59,7 +84,7 @@ export default class ActionReporter extends React.Component {
Output

- Action output is too large to be displayed here ({`${resultSizeMB}`} MB).

You can view raw execution output by clicking here or you can download the output by clicking here (uncompressed) or here (compressed). + Action output is too large to be displayed here ({`${resultSizeMB}`} MB).

You can view raw execution output by clicking here or you can download the output by clicking here (uncompressed) or here (compressed).

); From d886f4a0fbc1ca29c8d2e8fed8e7e45d46452bd8 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 19 Mar 2021 21:08:56 +0100 Subject: [PATCH 04/26] Update existing affected tests, add new ones. --- .../tests/test-action-reporter.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/modules/st2-action-reporter/tests/test-action-reporter.js b/modules/st2-action-reporter/tests/test-action-reporter.js index 858896c10..f08a566d9 100644 --- a/modules/st2-action-reporter/tests/test-action-reporter.js +++ b/modules/st2-action-reporter/tests/test-action-reporter.js @@ -28,6 +28,7 @@ describe(`${ActionReporter.name} Component`, () => { className="foobar" runner="noop" execution={{}} + api={{server: {api: "https://example.com:3000/v1"}}} /> ); @@ -40,10 +41,26 @@ describe(`${ActionReporter.name} Component`, () => { foo="bar" runner="noop" execution={{}} + api={{server: {api: "https://example.com:3000/v1"}}} /> ); expect(instance.node.props.foo).to.equal('bar'); }); + + it('returns correct message on large result', () => { + const instance = ReactTester.create( + + ); + + const pElem = instance.toJSON()["children"][1].children.join(""); + expect(pElem).to.contain("Action output is too large to be displayed here") + expect(pElem).to.contain("You can view raw") + }); }); }); From 8261cbae9dc11f6d59ad5a1aa3a50445aa106b6f Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 19 Mar 2021 21:32:00 +0100 Subject: [PATCH 05/26] Pick default value based on actual testing. --- .../action-reporter.component.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/modules/st2-action-reporter/action-reporter.component.js b/modules/st2-action-reporter/action-reporter.component.js index 533b15b60..da9eb62ae 100644 --- a/modules/st2-action-reporter/action-reporter.component.js +++ b/modules/st2-action-reporter/action-reporter.component.js @@ -23,9 +23,17 @@ import style from './style.css'; // If action execution result is larger than this value (in bytes) we won't try to render it in // the code highlighter widget, but display a link to the raw result output instead directly to // st2api. This way we avoid large results freezing and blocking the browser window -// Can be overriden in the config, but values over 200 KB are not recommended. -// TODO: Do some more research and testing and come up with a good default value -const DEFAULT_MAX_RESULT_SIZE = 200 * 1024; // 200 KB +// Can be overriden in the config, but values over 500 KB are not recommended. +// Keep in mind that rendering time also depends on the result type (aka deeply +// nested JSON object vs more flat one). +// Based on testing, any larger and more nested JSON object over 100 KB will +// take a while to render and consume a lot of memory (and in case of even +// larger objects, free the whole browser window). +// Technically we could still display and render results up to 300 KB, but the +// whole code widget gets very lagy and slow. +// Testing was also performed on relatively high end PC so on older ones, even +// lower limit may be more appropriate. +const DEFAULT_MAX_RESULT_SIZE = 100 * 1024; // 100 KB function getBaseAPIUrl(api) { From 573b89dd01b204416aed866e1532ee8e3b2426b1 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 19 Mar 2021 21:48:03 +0100 Subject: [PATCH 06/26] Move code innto if scope. --- .../action-reporter.component.js | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/modules/st2-action-reporter/action-reporter.component.js b/modules/st2-action-reporter/action-reporter.component.js index da9eb62ae..02d348c93 100644 --- a/modules/st2-action-reporter/action-reporter.component.js +++ b/modules/st2-action-reporter/action-reporter.component.js @@ -76,18 +76,26 @@ export default class ActionReporter extends React.Component { return null; } - // TODO: Add methods to the client to retrieve full correct URL? - const baseApiUrl = getBaseAPIUrl(api); - const viewRawResultUrl = `${baseApiUrl}/v1/executions/${execution.id}/result?pretty_format=1`; - const downloadRawResultUrl = `${baseApiUrl}/v1/executions/${execution.id}/result?download=1&pretty_format=1`; - const downloadCompressedRawResultUrl = `${baseApiUrl}/v1/executions/${execution.id}/result?download=1&pretty_format=1&compress=1`; - const maxResultSizeForRender = window.st2constants.st2Config.max_execution_result_size_for_render || DEFAULT_MAX_RESULT_SIZE; - // For backward compatibility with older executions which may not have result_size attribute const resultSize = execution.result_size || JSON.stringify(execution.result || {}).length; const resultSizeMB = ((resultSize / 1024 / 1024)).toFixed(2); if (resultSize && resultSize > maxResultSizeForRender) { + // TODO: Add methods to the client to retrieve full correct URL? + const baseApiUrl = getBaseAPIUrl(api); + const viewRawResultUrl = `${baseApiUrl}/v1/executions/${execution.id}/result?pretty_format=1`; + const downloadRawResultUrl = `${baseApiUrl}/v1/executions/${execution.id}/result?download=1&pretty_format=1`; + const downloadCompressedRawResultUrl = `${baseApiUrl}/v1/executions/${execution.id}/result?download=1&pretty_format=1&compress=1`; + + var maxResultSizeForRender + + try { + maxResultSizeForRender = window.st2constants.st2Config.max_execution_result_size_for_render || DEFAULT_MAX_RESULT_SIZE; + } + catch (e) { + maxResultSizeForRender = DEFAULT_MAX_RESULT_SIZE; + } + return (
Output
From 8c8879dcbe2f19e028e684bff9515ab336359e0c Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 19 Mar 2021 21:55:03 +0100 Subject: [PATCH 07/26] Update comment, comment out the line which will fail when running end to end tests with older version of st2. --- apps/st2-history/history-panel.component.js | 2 +- .../action-reporter.component.js | 20 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/apps/st2-history/history-panel.component.js b/apps/st2-history/history-panel.component.js index b81050997..4d08bc877 100644 --- a/apps/st2-history/history-panel.component.js +++ b/apps/st2-history/history-panel.component.js @@ -214,7 +214,7 @@ export default class HistoryPanel extends React.Component { 'rule.ref', 'trigger.type', 'context.user', - 'result_size', + //'result_size', ], }, raw: true, // so we can extract headers diff --git a/modules/st2-action-reporter/action-reporter.component.js b/modules/st2-action-reporter/action-reporter.component.js index 02d348c93..a35a5054e 100644 --- a/modules/st2-action-reporter/action-reporter.component.js +++ b/modules/st2-action-reporter/action-reporter.component.js @@ -77,9 +77,20 @@ export default class ActionReporter extends React.Component { } // For backward compatibility with older executions which may not have result_size attribute + // we fall back to execution.result (if available - would only be available when using newer + // st2web with older version of other StackStorm components). const resultSize = execution.result_size || JSON.stringify(execution.result || {}).length; const resultSizeMB = ((resultSize / 1024 / 1024)).toFixed(2); + var maxResultSizeForRender + + try { + maxResultSizeForRender = window.st2constants.st2Config.max_execution_result_size_for_render || DEFAULT_MAX_RESULT_SIZE; + } + catch (e) { + maxResultSizeForRender = DEFAULT_MAX_RESULT_SIZE; + } + if (resultSize && resultSize > maxResultSizeForRender) { // TODO: Add methods to the client to retrieve full correct URL? const baseApiUrl = getBaseAPIUrl(api); @@ -87,15 +98,6 @@ export default class ActionReporter extends React.Component { const downloadRawResultUrl = `${baseApiUrl}/v1/executions/${execution.id}/result?download=1&pretty_format=1`; const downloadCompressedRawResultUrl = `${baseApiUrl}/v1/executions/${execution.id}/result?download=1&pretty_format=1&compress=1`; - var maxResultSizeForRender - - try { - maxResultSizeForRender = window.st2constants.st2Config.max_execution_result_size_for_render || DEFAULT_MAX_RESULT_SIZE; - } - catch (e) { - maxResultSizeForRender = DEFAULT_MAX_RESULT_SIZE; - } - return (
Output
From 4eea648be55112b7efa6e548d67c53189e0e30cb Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Sat, 20 Mar 2021 16:58:42 +0100 Subject: [PATCH 08/26] Update code to utilize new API changes from https://github.com/StackStorm/st2/pull/5197. This allows us to simplify the code and make it even more efficient by only always performing single "get one" execution API operation. --- apps/st2-history/history-details.component.js | 34 +++------- .../action-reporter.component.js | 66 ++++++++++--------- 2 files changed, 44 insertions(+), 56 deletions(-) diff --git a/apps/st2-history/history-details.component.js b/apps/st2-history/history-details.component.js index f27f6445b..c1eb9e18a 100644 --- a/apps/st2-history/history-details.component.js +++ b/apps/st2-history/history-details.component.js @@ -47,6 +47,7 @@ import HistoryPopup from './history-popup.component'; const { execution } = state; return { execution }; }) + export default class HistoryDetails extends React.Component { static propTypes = { handleNavigate: PropTypes.func.isRequired, @@ -74,36 +75,19 @@ export default class HistoryDetails extends React.Component { componentDidUpdate(prevProps) { const { id, execution } = this.props; - var reFetchExecution = false; - - if (execution && execution.FETCH_RESULT &&!execution.FETCHING_RESULT && !execution.result) { - reFetchExecution = true; - } - - if ((id && id !== prevProps.id) || reFetchExecution) { - if (execution) { - // Indicate we are fetching the result for this execution - execution.FETCHING_RESULT = true; - } - this.fetchExecution(id, reFetchExecution); + if ((id && id !== prevProps.id)) { + this.fetchExecution(id); } } - fetchExecution(id, includeResult) { - includeResult = includeResult || false; - - var path; + fetchExecution(id) { + // We utilize ?max_result_size query parameter filter so we don't retrieve + // large results which we don't render due to that being very slow and + // freezing the browser window + const maxResultSizeForRender = ActionReporter.utils.getMaxExecutionResultSizeForRender(); + const path = `/executions/${id}?max_result_size=${maxResultSizeForRender}`; - // NOTE: We don't retrieve result here by defualt because it may be very large. We only retrieve it later - // after we determine the result size. If the result size is too large, we won't display it in - // the output tab since that would freeze the browser, but we will display a link to the raw - // result output instead. - if (includeResult) { - path = `/executions/${id}`; - } else { - path = `/executions/${id}?exclude_attributes=result`; - } store.dispatch({ type: 'FETCH_EXECUTION', diff --git a/modules/st2-action-reporter/action-reporter.component.js b/modules/st2-action-reporter/action-reporter.component.js index a35a5054e..bd4b7daf8 100644 --- a/modules/st2-action-reporter/action-reporter.component.js +++ b/modules/st2-action-reporter/action-reporter.component.js @@ -21,23 +21,26 @@ import reporters from './reporters'; import style from './style.css'; // If action execution result is larger than this value (in bytes) we won't try to render it in -// the code highlighter widget, but display a link to the raw result output instead directly to -// st2api. This way we avoid large results freezing and blocking the browser window -// Can be overriden in the config, but values over 500 KB are not recommended. +// the code highlighter widget, but display a link to the raw result output instead. +// This way we avoid large results freezing and blocking the browser window. // Keep in mind that rendering time also depends on the result type (aka deeply -// nested JSON object vs more flat one). +// nested JSON object vs a more flat one). // Based on testing, any larger and more nested JSON object over 100 KB will // take a while to render and consume a lot of memory (and in case of even -// larger objects, free the whole browser window). +// larger objects, freeze / block the whole browser window). // Technically we could still display and render results up to 300 KB, but the -// whole code widget gets very lagy and slow. +// whole code widget and browser window gets lagy and slow. // Testing was also performed on relatively high end PC so on older ones, even // lower limit may be more appropriate. +// Can be overriden in the config, but values over 50-100 KB (depending on the client +// resources and how nested the result objects are) are not recommended. const DEFAULT_MAX_RESULT_SIZE = 100 * 1024; // 100 KB +/** + * Return base URL to the API service based on the config value. + */ function getBaseAPIUrl(api) { - // Return base URL to the api instance if (!api.server) { console.log("config.js is not correctlu configured - it's missing API server URL entry") return null; @@ -61,6 +64,25 @@ function getBaseAPIUrl(api) { return baseUrl; } +/** + * Return value for the ?max_result_size query parameter aka the maximum number + * for the result size (in bytes) we will still try to render and display. + * + * We specify a default value which can be overriden inside the config. + */ +function getMaxExecutionResultSizeForRender() { + var maxResultSizeForRender; + + try { + maxResultSizeForRender = window.st2constants.st2Config.max_execution_result_size_for_render || DEFAULT_MAX_RESULT_SIZE; + } + catch (e) { + maxResultSizeForRender = DEFAULT_MAX_RESULT_SIZE; + } + + return maxResultSizeForRender; +} + export default class ActionReporter extends React.Component { static propTypes = { className: PropTypes.string, @@ -68,6 +90,11 @@ export default class ActionReporter extends React.Component { execution: PropTypes.object.isRequired, } + static utils = { + getMaxExecutionResultSizeForRender: getMaxExecutionResultSizeForRender, + getBaseAPIUrl: getBaseAPIUrl, + } + render() { const { className, runner, execution, api, ...props } = this.props; const reporter = reporters[runner] || reporters.debug; @@ -81,15 +108,7 @@ export default class ActionReporter extends React.Component { // st2web with older version of other StackStorm components). const resultSize = execution.result_size || JSON.stringify(execution.result || {}).length; const resultSizeMB = ((resultSize / 1024 / 1024)).toFixed(2); - - var maxResultSizeForRender - - try { - maxResultSizeForRender = window.st2constants.st2Config.max_execution_result_size_for_render || DEFAULT_MAX_RESULT_SIZE; - } - catch (e) { - maxResultSizeForRender = DEFAULT_MAX_RESULT_SIZE; - } + const maxResultSizeForRender = getMaxExecutionResultSizeForRender(); if (resultSize && resultSize > maxResultSizeForRender) { // TODO: Add methods to the client to retrieve full correct URL? @@ -108,21 +127,6 @@ export default class ActionReporter extends React.Component { ); } - if (!execution.result) { - if (!execution.FETCH_RESULT) { - // If execution is not too big, we update the attribute to indicate the component to re-fetch the - // execution with the result field - execution.FETCH_RESULT = true; - } - - return ( -
-
Output
-

Loading execution result...

-
- ); - } - return (
{ reporter(execution) } From 7d8ea37cc99cb5d340acb12cf9d19766c1ea0fea Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Sat, 20 Mar 2021 17:04:02 +0100 Subject: [PATCH 09/26] Fix formatting. --- apps/st2-history/history-details.component.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/st2-history/history-details.component.js b/apps/st2-history/history-details.component.js index c1eb9e18a..6609c6655 100644 --- a/apps/st2-history/history-details.component.js +++ b/apps/st2-history/history-details.component.js @@ -88,7 +88,6 @@ export default class HistoryDetails extends React.Component { const maxResultSizeForRender = ActionReporter.utils.getMaxExecutionResultSizeForRender(); const path = `/executions/${id}?max_result_size=${maxResultSizeForRender}`; - store.dispatch({ type: 'FETCH_EXECUTION', promise: api.request({ path: path }), From 70ddc71b90d574b0b7cef6b99f6d36dab2715d0a Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 18:36:39 +0200 Subject: [PATCH 10/26] Fix formatting and ytpos, remove changes we don't need. --- apps/st2-history/history-details.component.js | 2 +- apps/st2-history/history-panel.component.js | 1 - modules/st2-action-reporter/action-reporter.component.js | 8 ++++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/st2-history/history-details.component.js b/apps/st2-history/history-details.component.js index 6609c6655..566213612 100644 --- a/apps/st2-history/history-details.component.js +++ b/apps/st2-history/history-details.component.js @@ -76,7 +76,7 @@ export default class HistoryDetails extends React.Component { componentDidUpdate(prevProps) { const { id, execution } = this.props; - if ((id && id !== prevProps.id)) { + if (id && id !== prevProps.id) { this.fetchExecution(id); } } diff --git a/apps/st2-history/history-panel.component.js b/apps/st2-history/history-panel.component.js index 4d08bc877..c03542dad 100644 --- a/apps/st2-history/history-panel.component.js +++ b/apps/st2-history/history-panel.component.js @@ -214,7 +214,6 @@ export default class HistoryPanel extends React.Component { 'rule.ref', 'trigger.type', 'context.user', - //'result_size', ], }, raw: true, // so we can extract headers diff --git a/modules/st2-action-reporter/action-reporter.component.js b/modules/st2-action-reporter/action-reporter.component.js index bd4b7daf8..446754386 100644 --- a/modules/st2-action-reporter/action-reporter.component.js +++ b/modules/st2-action-reporter/action-reporter.component.js @@ -42,12 +42,12 @@ const DEFAULT_MAX_RESULT_SIZE = 100 * 1024; // 100 KB */ function getBaseAPIUrl(api) { if (!api.server) { - console.log("config.js is not correctlu configured - it's missing API server URL entry") + console.log("config.js is not correctly configured - it's missing API server URL entry") return null; } if (!api.server.api) { - console.log("config.js is not correctlu configured - it's missing API server URL entry") + console.log("config.js is not correctly configured - it's missing API server URL entry") return null; } @@ -65,8 +65,8 @@ function getBaseAPIUrl(api) { } /** - * Return value for the ?max_result_size query parameter aka the maximum number - * for the result size (in bytes) we will still try to render and display. + * Return value for the ?max_result_size query parameter aka the maximum number for the result size + * (in bytes) we will still try to render and display. * * We specify a default value which can be overriden inside the config. */ From 717cfc280b5007b63ec2f9c92281dd3ddf8a03ef Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 18:45:28 +0200 Subject: [PATCH 11/26] Fix tests so they also work if DST is active. --- modules/st2-time/tests/test-time.js | 30 +++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/modules/st2-time/tests/test-time.js b/modules/st2-time/tests/test-time.js index 46a6b6309..b74581976 100644 --- a/modules/st2-time/tests/test-time.js +++ b/modules/st2-time/tests/test-time.js @@ -19,6 +19,12 @@ import { ReactTester } from '@stackstorm/module-test-utils'; import Time from '..'; +function isDST(d) { + let jan = new Date(d.getFullYear(), 0, 1).getTimezoneOffset(); + let jul = new Date(d.getFullYear(), 6, 1).getTimezoneOffset(); + return Math.max(jan, jul) != d.getTimezoneOffset(); +} + describe(`${Time.name} Component`, () => { describe('common functionality', () => { it('proxies className', () => { @@ -52,8 +58,18 @@ describe(`${Time.name} Component`, () => { ); // note: this will only work in places with whole hour offsets - const hour = (24 - new Date().getTimezoneOffset() / 60); + // note: it seems like this react time component doesn't correctly take DST + // into account so this is a temporary hack to get tests to pass on systems + // without UTC timezone :/ + const now = new Date(); + const isNowDst = isDST(now); + let hour = (24 - new Date().getTimezoneOffset() / 60); + if (hour >= 24) { + if (isNowDst) { + hour = hour - 1; + } + expect(instance.text).to.equal( `Thu, 01 Jan 1970 ${(hour - 24).toFixed(0).padStart(2, '0')}:00:00` ); @@ -83,8 +99,18 @@ describe(`${Time.name} Component`, () => { ); // note: this will only work in places with whole hour offsets - const hour = (24 - new Date().getTimezoneOffset() / 60); + // note: it seems like this react time component doesn't correctly take DST + // into account so this is a temporary hack to get tests to pass on systems + // without UTC timezone :/ + const now = new Date(); + const isNowDst = isDST(now); + let hour = (24 - new Date().getTimezoneOffset() / 60); + if (hour >= 24) { + if (isNowDst) { + hour = hour - 1; + } + expect(instance.text).to.equal( `January 1 1970 ${(hour - 24).toFixed(0).padStart(2, '0')}:00 AM` ); From 4d8af52ec2a278cb59a91a3910f39e55fb8827e2 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 18:46:35 +0200 Subject: [PATCH 12/26] Update sample config. --- config.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config.js b/config.js index e958e4829..2c77b5159 100644 --- a/config.js +++ b/config.js @@ -18,6 +18,12 @@ angular.module('main') .constant('st2Config', { + // In case you want to override default value for the result sizes we still render in the + // history details widget. Keep in mind that anything above 200-500 KB will take a long time to + // render and likely freeze the browser window for deeply nested JSON object results. + // Value is in bytes. + // max_execution_result_size_for_render: 200 * 1024; + // hosts: [ // { // name: 'Dev Env', From 5c28cdd7ae345a0c117534af45c4bb48563e294a Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 19:01:42 +0200 Subject: [PATCH 13/26] Try setting ST2_IMAGE_TAG env variable for end to end tests. --- .circleci/config.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index a8cd87582..6abe36ccd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -99,6 +99,8 @@ jobs: command: npm run test-functional - run: name: Reset test containers + environment: + ST2_IMAGE_TAG: "3.5dev" command: | docker-compose -f ~/st2-docker/docker-compose.yml down docker-compose -f ~/st2-docker/docker-compose.yml up -d @@ -107,6 +109,8 @@ jobs: docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2ctl restart - run: name: Recheck test containers + environment: + ST2_IMAGE_TAG: "3.5dev" command: | docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2 run core.noop docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2 execution list From cf355b653ebca7fec2ec186ca4cd8c5ffdf8dbc5 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 20:10:35 +0200 Subject: [PATCH 14/26] Test another change. --- .circleci/config.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6abe36ccd..0dc6c36b2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -68,7 +68,7 @@ jobs: name: Update Docker Compose command: | set -x - sudo sh -c "curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose" + sudo sh -c "curl -L https://github.com/docker/compose/releases/download/1.28.6/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose" sudo chmod +x /usr/local/bin/docker-compose - run: name: Clone test containers @@ -85,7 +85,10 @@ jobs: cat ~/st2-docker/conf/stackstorm.env - run: name: Start test containers + environment: + ST2_IMAGE_TAG: "3.5dev" command: | + echo "ST2_IMAGE_TAG=3.5dev" > .env docker-compose -f ~/st2-docker/docker-compose.yml up -d sleep 60 docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm crudini --set /etc/st2/st2.conf api allow_origin "*" @@ -99,9 +102,8 @@ jobs: command: npm run test-functional - run: name: Reset test containers - environment: - ST2_IMAGE_TAG: "3.5dev" command: | + echo "ST2_IMAGE_TAG=3.5dev" > .env docker-compose -f ~/st2-docker/docker-compose.yml down docker-compose -f ~/st2-docker/docker-compose.yml up -d sleep 60 @@ -112,6 +114,7 @@ jobs: environment: ST2_IMAGE_TAG: "3.5dev" command: | + echo "ST2_IMAGE_TAG=3.5dev" > .env docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2 run core.noop docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2 execution list - run: From 26f5b573b955a58678ed3382c52ef3d3a666dd2d Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 20:18:47 +0200 Subject: [PATCH 15/26] Revert changes. This won't work since it uses out of date stackstorm/stackstorm image. --- .circleci/config.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0dc6c36b2..40714480b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -86,9 +86,8 @@ jobs: - run: name: Start test containers environment: - ST2_IMAGE_TAG: "3.5dev" + ST2_IMAGE_TAG: "latest" command: | - echo "ST2_IMAGE_TAG=3.5dev" > .env docker-compose -f ~/st2-docker/docker-compose.yml up -d sleep 60 docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm crudini --set /etc/st2/st2.conf api allow_origin "*" @@ -102,8 +101,9 @@ jobs: command: npm run test-functional - run: name: Reset test containers + environment: + ST2_IMAGE_TAG: "latest" command: | - echo "ST2_IMAGE_TAG=3.5dev" > .env docker-compose -f ~/st2-docker/docker-compose.yml down docker-compose -f ~/st2-docker/docker-compose.yml up -d sleep 60 @@ -112,9 +112,8 @@ jobs: - run: name: Recheck test containers environment: - ST2_IMAGE_TAG: "3.5dev" + ST2_IMAGE_TAG: "latest" command: | - echo "ST2_IMAGE_TAG=3.5dev" > .env docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2 run core.noop docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2 execution list - run: From 26e65ee1ef28342f3aea395f7e9fe875cbc9b107 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 21:15:32 +0200 Subject: [PATCH 16/26] WIP attemp to use st2-docker master branch. --- .circleci/config.yml | 36 +++++++++++++----------------------- README.md | 4 ++-- tests/util.js | 12 ++++++------ 3 files changed, 21 insertions(+), 31 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 40714480b..6520efc4a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,9 +12,11 @@ jobs: DEPLOY_PACKAGES: 1 DEB: xenial bionic RPM: el7 el8 + ST2_VERSION: "3.5dev" ST2_HOST: localhost - ST2_USERNAME: admin - ST2_PASSWORD: 123 + ST2_PROTOCOL: http + ST2_USERNAME: st2admin + ST2_PASSWORD: Ch@ngeMe ST2_TEST_ENVIRONMENT: https://github.com/StackStorm/st2-docker steps: - checkout @@ -75,46 +77,34 @@ jobs: command: | # Use DEPRECATED/all-in-one for now, we'll have to circle back around # and fix this to use the master branch - echo "Cloning ${ST2_DOCKER_BRANCH:-DEPRECATED/all-in-one} branch of st2-docker" - git clone --branch ${ST2_DOCKER_BRANCH:-DEPRECATED/all-in-one} --depth 1 ${ST2_TEST_ENVIRONMENT} ~/st2-docker - - run: - name: Update env variables for test containers - command: | - make -C ~/st2-docker env - echo -e "ST2_USER=${ST2_USERNAME}\nST2_PASSWORD=${ST2_PASSWORD}" > ~/st2-docker/conf/stackstorm.env - cat ~/st2-docker/conf/stackstorm.env + echo "Cloning ${ST2_DOCKER_BRANCH:-master} branch of st2-docker" + git clone --branch ${ST2_DOCKER_BRANCH:-master} --depth 1 ${ST2_TEST_ENVIRONMENT} ~/st2-docker - run: name: Start test containers - environment: - ST2_IMAGE_TAG: "latest" command: | + echo "[api]" > ~/st2-docker/files/st2.user.conf + echo "allow_origin = *" >> ~/st2-docker/files/st2.user.conf + docker-compose -f ~/st2-docker/docker-compose.yml up -d sleep 60 - docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm crudini --set /etc/st2/st2.conf api allow_origin "*" - docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2ctl restart - run: name: Check test containers command: | - docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2 run core.noop + docker-compose -f ~/st2-docker/docker-compose.yml exec st2client st2 run core.noop - run: name: Run functional tests command: npm run test-functional - run: name: Reset test containers - environment: - ST2_IMAGE_TAG: "latest" command: | - docker-compose -f ~/st2-docker/docker-compose.yml down + docker-compose -f ~/st2-docker/docker-compose.yml down -v --rmi docker-compose -f ~/st2-docker/docker-compose.yml up -d sleep 60 - docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm crudini --set /etc/st2/st2.conf api allow_origin "*" - docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2ctl restart - run: name: Recheck test containers - environment: - ST2_IMAGE_TAG: "latest" command: | - docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2 run core.noop + docker-compose -f ~/st2-docker/docker-compose.yml exec st2client st2 run core.noop + docker-compose -f ~/st2-docker/docker-compose.yml exec st2client st2 execution list docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2 execution list - run: name: Run tests on production version diff --git a/README.md b/README.md index 6e7b3f189..a7fa51389 100644 --- a/README.md +++ b/README.md @@ -123,9 +123,9 @@ We're using [zombie](https://github.com/assaf/zombie) as our headless browser fo First of all, you need to make sure you have a running copy of st2 to run tests against. We're using [official docker images](https://github.com/stackstorm/st2-docker) for our automated tests, but the [AIO](https://docs.stackstorm.com/install/index.html) deployment will work just as good (though will take more time to deploy). -To let test runner know the details of your st2 installation, you need to set ST2_HOST, ST2_USERNAME and ST2_PASSWORD env variables, then call `gulp test`. +To let test runner know the details of your st2 installation, you need to set ST2_PROTOCOL, ST2_HOST, ST2_USERNAME and ST2_PASSWORD env variables, then call `gulp test`. - $ ST2_HOST=localhost ST2_USERNAME=admin ST2_PASSWORD=123 gulp test + $ ST2_PROTOCOL=http ST2_HOST=localhost ST2_USERNAME=admin ST2_PASSWORD=123 gulp test Copyright, License, and Contributors Agreement ---------------------------------------------- diff --git a/tests/util.js b/tests/util.js index fbc52e93f..8e3e76c6c 100644 --- a/tests/util.js +++ b/tests/util.js @@ -59,10 +59,10 @@ module.exports = function (browser) { return new zombie.Response(`angular.module('main').constant('st2Config', { hosts: [{ name: 'Test', - url: 'https://${process.env.ST2_HOST}/api', - auth: 'https://${process.env.ST2_HOST}/auth', + url: '${process.env.ST2_PROTOCOL}://${process.env.ST2_HOST}/api', + auth: '${process.env.ST2_PROTOCOL}://${process.env.ST2_HOST}/auth', }], - });`); + });`); } if (url.path().indexOf('/reamaze.js') >= 0) { @@ -103,11 +103,11 @@ module.exports = function (browser) { const api = new API(); client = api.connect({ - url: `https://${process.env.ST2_HOST}/api`, - auth: `https://${process.env.ST2_HOST}/auth`, + url: `${process.env.ST2_PROTOCOL}://${process.env.ST2_HOST}/api`, + auth: `${process.env.ST2_PROTOCOL}://${process.env.ST2_HOST}/auth`, }, process.env.ST2_USERNAME, process.env.ST2_PASSWORD) .then(() => api); - } + } return client; }, From e39cacb038b4d31459c7a9777ce76bf1e40c89f4 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 21:43:50 +0200 Subject: [PATCH 17/26] Update affected test. --- tests/test-history.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-history.js b/tests/test-history.js index 748a8441f..2351d8168 100644 --- a/tests/test-history.js +++ b/tests/test-history.js @@ -80,7 +80,7 @@ describe('User visits history page', function () { let resource; before(() => { - resource = browser.resources.filter((e) => new RegExp('^https://example.com/api/v1/executions/\\w+$').test(e.url)); + resource = browser.resources.filter((e) => new RegExp('^https://example.com/api/v1/executions/\\w+\\?max_result_size=102400$').test(e.url)); }); it('should make a call to execution endpoint once', () => { From 06d49b3e706d93ea74ab2b2aea1ff38d726a3ac9 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 21:44:04 +0200 Subject: [PATCH 18/26] Add a hack since all the tests assert on https. --- tests/util.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/util.js b/tests/util.js index 8e3e76c6c..bc5645a1d 100644 --- a/tests/util.js +++ b/tests/util.js @@ -70,7 +70,9 @@ module.exports = function (browser) { } if (url.host() === process.env.ST2_HOST) { - response._url = url.host('example.com').toString(); + // All the tests expect https:// so we just hack that and replace http with https in case + // https is not used + response._url = url.host('example.com').toString().replace("http://", "https://"); request.url = response.url; } From e094f73e75692c115f0073929442522f5d1a96f5 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 21:44:13 +0200 Subject: [PATCH 19/26] Update circle ci config. --- .circleci/config.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6520efc4a..fd82ad433 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -75,16 +75,17 @@ jobs: - run: name: Clone test containers command: | - # Use DEPRECATED/all-in-one for now, we'll have to circle back around - # and fix this to use the master branch echo "Cloning ${ST2_DOCKER_BRANCH:-master} branch of st2-docker" git clone --branch ${ST2_DOCKER_BRANCH:-master} --depth 1 ${ST2_TEST_ENVIRONMENT} ~/st2-docker - run: - name: Start test containers + name: Configufe docker compsoe config command: | + # Configure allow origin in the user config echo "[api]" > ~/st2-docker/files/st2.user.conf echo "allow_origin = *" >> ~/st2-docker/files/st2.user.conf - + - run: + name: Start test containers + command: | docker-compose -f ~/st2-docker/docker-compose.yml up -d sleep 60 - run: From 595322c02e2db8449ba5da3b6f85625c232a98f0 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 21:57:49 +0200 Subject: [PATCH 20/26] Remove old command. --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fd82ad433..48c33efc4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -106,7 +106,6 @@ jobs: command: | docker-compose -f ~/st2-docker/docker-compose.yml exec st2client st2 run core.noop docker-compose -f ~/st2-docker/docker-compose.yml exec st2client st2 execution list - docker-compose -f ~/st2-docker/docker-compose.yml exec stackstorm st2 execution list - run: name: Run tests on production version command: npm run test-production From 1cfbee0a9c41a959a9461bd66ac47677da104018 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 22:01:06 +0200 Subject: [PATCH 21/26] Fix typo. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 48c33efc4..b7a376103 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -78,7 +78,7 @@ jobs: echo "Cloning ${ST2_DOCKER_BRANCH:-master} branch of st2-docker" git clone --branch ${ST2_DOCKER_BRANCH:-master} --depth 1 ${ST2_TEST_ENVIRONMENT} ~/st2-docker - run: - name: Configufe docker compsoe config + name: Configufe docker compose config command: | # Configure allow origin in the user config echo "[api]" > ~/st2-docker/files/st2.user.conf From 34d70478a231509ed2f0093706bda21c4dd2c444 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 22:07:16 +0200 Subject: [PATCH 22/26] use longer sleep. --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b7a376103..ffe886555 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -87,7 +87,7 @@ jobs: name: Start test containers command: | docker-compose -f ~/st2-docker/docker-compose.yml up -d - sleep 60 + sleep 100 - run: name: Check test containers command: | @@ -100,7 +100,7 @@ jobs: command: | docker-compose -f ~/st2-docker/docker-compose.yml down -v --rmi docker-compose -f ~/st2-docker/docker-compose.yml up -d - sleep 60 + sleep 100 - run: name: Recheck test containers command: | From 752b0c38398444e2813d3c79dd1d599398ac048c Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Fri, 2 Apr 2021 22:16:13 +0200 Subject: [PATCH 23/26] Remove unncessary flag. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ffe886555..381da9c87 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -98,7 +98,7 @@ jobs: - run: name: Reset test containers command: | - docker-compose -f ~/st2-docker/docker-compose.yml down -v --rmi + docker-compose -f ~/st2-docker/docker-compose.yml down --rmi docker-compose -f ~/st2-docker/docker-compose.yml up -d sleep 100 - run: From 1da5c9e50e877959b5356858daa0acbc8dd6cbb7 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Sun, 4 Apr 2021 20:16:35 +0200 Subject: [PATCH 24/26] Add support for displaying component versions in the headers. It defaults to false and it can be enabled via config option. --- config.js | 5 ++++- index.html | 14 +++++++++++--- modules/st2-menu/menu.component.js | 7 +++++-- tasks/production/package-metadata.js | 12 ++++++++---- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/config.js b/config.js index 2c77b5159..233bcb2c8 100644 --- a/config.js +++ b/config.js @@ -22,7 +22,10 @@ angular.module('main') // history details widget. Keep in mind that anything above 200-500 KB will take a long time to // render and likely freeze the browser window for deeply nested JSON object results. // Value is in bytes. - // max_execution_result_size_for_render: 200 * 1024; + // max_execution_result_size_for_render: 200 * 1024, + // + // Set to true to display StackStorm and st2web version in the header + //show_version_in_header: false; // hosts: [ // { diff --git a/index.html b/index.html index d7df4ff73..bc0bfcc61 100644 --- a/index.html +++ b/index.html @@ -19,12 +19,18 @@ throw new Error('The st2web angular-config-polyfill only supports the "main" module.'); } - if (constant !== 'st2Config') { - throw new Error('The st2web angular-config-polyfill only supports the "st2Config" constant.'); + if (constant !== 'st2Config' && constant !== 'st2PackageMeta') { + throw new Error('The st2web angular-config-polyfill only supports the "st2Config" and "st2PackageMeta" constant.'); } window.st2constants = window.st2constants || {}; - window.st2constants.st2Config = value; + + if (constant === 'st2Config') { + window.st2constants.st2Config = value; + } + else if (constant === 'st2PackageMeta') { + window.st2constants.st2PackageMeta = value; + } }, run: (fn) => { if (module !== 'main') { @@ -33,6 +39,7 @@ window.st2constants = window.st2constants || {}; window.st2constants.st2Config = window.st2constants.st2Config || {}; + window.st2constants.st2PackageMeta = window.st2constants.st2PackageMeta || {}; fn(window.st2constants.st2Config); }, @@ -44,6 +51,7 @@
+ diff --git a/modules/st2-menu/menu.component.js b/modules/st2-menu/menu.component.js index 36a2ac607..52de8c4f3 100644 --- a/modules/st2-menu/menu.component.js +++ b/modules/st2-menu/menu.component.js @@ -73,7 +73,7 @@ export default class Menu extends React.Component { render() { const { className, location, routes: allRoutes, style, ...props } = this.props; - + const routes = _(allRoutes) .filter((e) => !!e.icon) .sortBy((e) => e.position) @@ -82,10 +82,13 @@ export default class Menu extends React.Component { const user = api.token && api.token.user; const server = api.server; + const showVersion = window.st2constants.st2Config.show_version_in_header || false; + const hasPackageMeta = (window.st2constants.st2PackageMeta !== undefined); + const st2webCommitsUrl = (showVersion && hasPackageMeta) ? "https://github.com/StackStorm/st2web/commit/" + window.st2constants.st2PackageMeta.git_sha : "" return (
- + { (showVersion && hasPackageMeta) ? st2: v{window.st2constants.st2PackageMeta.version}, st2web: {window.st2constants.st2PackageMeta.git_sha} : '' }
diff --git a/tasks/production/package-metadata.js b/tasks/production/package-metadata.js index a75d2b20c..64d8f3aff 100644 --- a/tasks/production/package-metadata.js +++ b/tasks/production/package-metadata.js @@ -25,13 +25,17 @@ gulp.task('production-package-metadata', (done) => { const result = child_process.spawnSync('git', [ 'rev-parse', '--short', 'HEAD' ]); const git_sha = result.stdout.toString().trim(); - const pkg_version = require(path.resolve('./package.json')).st2_version; - const data = `[st2web]\nversion = ${pkg_version}\ngit_sha = ${git_sha}\ncircle_build_url = ${circle_build_url}\n`; + // Write it to ini style file + const data_1 = `[st2web]\nversion = ${pkg_version}\ngit_sha = ${git_sha}\ncircle_build_url = ${circle_build_url}\n`; + const file_path_1 = path.join(path.resolve('./build'), 'package.meta'); + fs.writeFileSync(file_path_1, data_1); - const file_path = path.join(path.resolve('./build'), 'package.meta'); + // Write it to .js file + const data_2 = `angular.module('main').constant('st2PackageMeta', { version: "${pkg_version}", git_sha: "${git_sha}"});\n` + const file_path_2 = path.join(path.resolve('./build'), 'package.meta.js'); + fs.writeFileSync(file_path_2, data_2); - fs.writeFileSync(file_path, data); done(); }); From 65a85b0820209a8225844435d76ec30cdf5970d1 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Sun, 4 Apr 2021 21:01:50 +0200 Subject: [PATCH 25/26] Make sure gulp lint exits with non-zero on errors. Before that it didn't exit with non-zero so the build didn't fail and tons of violations have accumulated in the code base. --- tasks/lint.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tasks/lint.js b/tasks/lint.js index 43aaa43d9..71ff083e4 100644 --- a/tasks/lint.js +++ b/tasks/lint.js @@ -19,8 +19,11 @@ const gulp = require('gulp'); const settings = require('./settings.json'); const plugins = require('gulp-load-plugins')(settings.plugins); -gulp.task('lint', () => gulp.src(settings.lint, { cwd: settings.dev }) +gulp.task('lint', (done) => gulp.src(settings.lint, { cwd: settings.dev }) .pipe(plugins.plumber()) .pipe(plugins.eslint()) .pipe(plugins.eslint.format()) + .pipe(plugins.eslint.failAfterError()) + .on('end', () => done()) + .on('error', (err) => done(err)) ); From f53595b251c7df04dd494e957bc8848f42c1bde5 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Sun, 4 Apr 2021 21:14:09 +0200 Subject: [PATCH 26/26] Fix all the various lint violations detected by eslint. --- .eslintignore | 1 + apps/st2-actions/actions-details.component.js | 10 ++++--- apps/st2-history/history-details.component.js | 4 +-- apps/st2-workflows/workflows.component.js | 4 +-- .../action-reporter.component.js | 19 +++++++------- .../tests/test-action-reporter.js | 26 +++++++++---------- modules/st2-api/api.js | 25 +++++++++--------- modules/st2-menu/menu.component.js | 4 +-- modules/st2-pack-icon/pack-icon.component.js | 2 ++ modules/st2-time/tests/test-time.js | 6 ++--- modules/st2flow-canvas/index.js | 5 ++-- .../st2flow-details/orquesta-properties.js | 18 +++++++------ modules/st2flow-header/index.js | 4 +-- modules/st2flow-model/base-class.js | 5 +--- modules/st2flow-notifications/index.js | 6 ++--- modules/st2flow-palette/pack.js | 3 +-- tasks/production/package-metadata.js | 2 +- 17 files changed, 75 insertions(+), 69 deletions(-) diff --git a/.eslintignore b/.eslintignore index 79c529ab3..98ccae491 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,3 +3,4 @@ modules/*/node_modules tasks/*/node_modules node_modules js +package.meta.js diff --git a/apps/st2-actions/actions-details.component.js b/apps/st2-actions/actions-details.component.js index b0d189d89..96d2111d0 100644 --- a/apps/st2-actions/actions-details.component.js +++ b/apps/st2-actions/actions-details.component.js @@ -213,9 +213,11 @@ export default class ActionsDetails extends React.Component { }, }); } -setWindowName(e){ - window.name="parent" -} + + setWindowName(e) { + window.name = 'parent'; + } + handleRun(e, ...args) { e.preventDefault(); @@ -259,7 +261,7 @@ setWindowName(e){ target="_blank" to={`/action/${action.ref}`} className="st2-forms__button st2-details__toolbar-button" - onClick ={e => this.setWindowName(e)} + onClick={e => this.setWindowName(e)} > Edit diff --git a/apps/st2-history/history-details.component.js b/apps/st2-history/history-details.component.js index 566213612..3e2283a4a 100644 --- a/apps/st2-history/history-details.component.js +++ b/apps/st2-history/history-details.component.js @@ -56,7 +56,7 @@ export default class HistoryDetails extends React.Component { id: PropTypes.string, section: PropTypes.string, - execution: PropTypes.object, + execution: PropTypes.object, // eslint-disable-line react/no-unused-prop-types displayUTC: PropTypes.bool.isRequired, handleToggleUTC: PropTypes.func, } @@ -74,7 +74,7 @@ export default class HistoryDetails extends React.Component { } componentDidUpdate(prevProps) { - const { id, execution } = this.props; + const { id } = this.props; if (id && id !== prevProps.id) { this.fetchExecution(id); diff --git a/apps/st2-workflows/workflows.component.js b/apps/st2-workflows/workflows.component.js index 697a728d9..b682e22d4 100644 --- a/apps/st2-workflows/workflows.component.js +++ b/apps/st2-workflows/workflows.component.js @@ -73,7 +73,7 @@ export default class Workflows extends Component { pack: PropTypes.string, meta: PropTypes.object, metaSource: PropTypes.string, - setMeta: PropTypes.func, + setMeta: PropTypes.func, // eslint-disable-line react/no-unused-prop-types input: PropTypes.array, workflowSource: PropTypes.string, dirty: PropTypes.bool, @@ -243,7 +243,7 @@ export default class Workflows extends Component { } save() { - const { pack, meta, actions, workflowSource, metaSource, setMeta } = this.props; + const { pack, meta, actions, workflowSource, metaSource } = this.props; const existingAction = actions.find(e => e.name === meta.name && e.pack === pack); if (!meta.name) { diff --git a/modules/st2-action-reporter/action-reporter.component.js b/modules/st2-action-reporter/action-reporter.component.js index 446754386..e74432cd1 100644 --- a/modules/st2-action-reporter/action-reporter.component.js +++ b/modules/st2-action-reporter/action-reporter.component.js @@ -42,19 +42,19 @@ const DEFAULT_MAX_RESULT_SIZE = 100 * 1024; // 100 KB */ function getBaseAPIUrl(api) { if (!api.server) { - console.log("config.js is not correctly configured - it's missing API server URL entry") + console.log('config.js is not correctly configured - it\'s missing API server URL entry'); return null; } if (!api.server.api) { - console.log("config.js is not correctly configured - it's missing API server URL entry") + console.log('config.js is not correctly configured - it\'s missing API server URL entry'); return null; } - var url = api.server.api; - var baseUrl; + const url = api.server.api; + let baseUrl; - if (!url.startsWith("http://") && !(url.startsWith("https://"))) { + if (!url.startsWith('http://') && !(url.startsWith('https://'))) { baseUrl = `${window.location.protocol}${url}`; } else { @@ -71,7 +71,7 @@ function getBaseAPIUrl(api) { * We specify a default value which can be overriden inside the config. */ function getMaxExecutionResultSizeForRender() { - var maxResultSizeForRender; + let maxResultSizeForRender; try { maxResultSizeForRender = window.st2constants.st2Config.max_execution_result_size_for_render || DEFAULT_MAX_RESULT_SIZE; @@ -88,6 +88,7 @@ export default class ActionReporter extends React.Component { className: PropTypes.string, runner: PropTypes.string.isRequired, execution: PropTypes.object.isRequired, + api: PropTypes.object.isRequired, } static utils = { @@ -119,12 +120,12 @@ export default class ActionReporter extends React.Component { return (
-
Output
+
Output

- Action output is too large to be displayed here ({`${resultSizeMB}`} MB).

You can view raw execution output by clicking here or you can download the output by clicking here (uncompressed) or here (compressed). + Action output is too large to be displayed here ({`${resultSizeMB}`} MB).

You can view raw execution output by clicking here or you can download the output by clicking here (uncompressed) or here (compressed).

- ); + ); } return ( diff --git a/modules/st2-action-reporter/tests/test-action-reporter.js b/modules/st2-action-reporter/tests/test-action-reporter.js index f08a566d9..34f2ab37c 100644 --- a/modules/st2-action-reporter/tests/test-action-reporter.js +++ b/modules/st2-action-reporter/tests/test-action-reporter.js @@ -25,10 +25,10 @@ describe(`${ActionReporter.name} Component`, () => { it('proxies className', () => { const instance = ReactTester.create( ); @@ -38,10 +38,10 @@ describe(`${ActionReporter.name} Component`, () => { it('proxies extra props', () => { const instance = ReactTester.create( ); @@ -51,16 +51,16 @@ describe(`${ActionReporter.name} Component`, () => { it('returns correct message on large result', () => { const instance = ReactTester.create( ); - const pElem = instance.toJSON()["children"][1].children.join(""); - expect(pElem).to.contain("Action output is too large to be displayed here") - expect(pElem).to.contain("You can view raw") + const pElem = instance.toJSON().children[1].children.join(''); + expect(pElem).to.contain('Action output is too large to be displayed here'); + expect(pElem).to.contain('You can view raw'); }); }); }); diff --git a/modules/st2-api/api.js b/modules/st2-api/api.js index b186c89cf..35017f8ec 100644 --- a/modules/st2-api/api.js +++ b/modules/st2-api/api.js @@ -175,28 +175,29 @@ export class API { const headers = { 'content-type': 'application/json', - - }; if (this.token && this.token.token) { headers['x-auth-token'] = this.token.token; } - + const config = { method, url: this.route(opts), params: query, headers, - transformResponse: [function transformResponse(data, headers) { - if (typeof data === 'string' && headers["content-type"] === "application/json") { - try { - data = JSON.parse(data); - } catch (e) { /* Ignore */ } - } - return data; - } - ], + transformResponse: [ function transformResponse(data, headers) { + if (typeof data === 'string' && headers['content-type'] === 'application/json') { + try { + data = JSON.parse(data); + } + catch (e) { + /* Ignore */ + } + } + + return data; + } ], data, withCredentials: true, paramsSerializer: params => { diff --git a/modules/st2-menu/menu.component.js b/modules/st2-menu/menu.component.js index 52de8c4f3..68bedb2b1 100644 --- a/modules/st2-menu/menu.component.js +++ b/modules/st2-menu/menu.component.js @@ -84,11 +84,11 @@ export default class Menu extends React.Component { const server = api.server; const showVersion = window.st2constants.st2Config.show_version_in_header || false; const hasPackageMeta = (window.st2constants.st2PackageMeta !== undefined); - const st2webCommitsUrl = (showVersion && hasPackageMeta) ? "https://github.com/StackStorm/st2web/commit/" + window.st2constants.st2PackageMeta.git_sha : "" + const st2webCommitsUrl = (showVersion && hasPackageMeta) ? `https://github.com/StackStorm/st2web/commit/${window.st2constants.st2PackageMeta.git_sha}` : ''; return (
- { (showVersion && hasPackageMeta) ? st2: v{window.st2constants.st2PackageMeta.version}, st2web: {window.st2constants.st2PackageMeta.git_sha} : '' } + { (showVersion && hasPackageMeta) ? st2: v{window.st2constants.st2PackageMeta.version}, st2web: {window.st2constants.st2PackageMeta.git_sha} : '' }
diff --git a/modules/st2-pack-icon/pack-icon.component.js b/modules/st2-pack-icon/pack-icon.component.js index baac4d99a..61b70ce1d 100644 --- a/modules/st2-pack-icon/pack-icon.component.js +++ b/modules/st2-pack-icon/pack-icon.component.js @@ -82,9 +82,11 @@ export default class PackIcon extends React.Component { ); } + /* Unreachable code, commented out :shrug: return ( ); + */ // ^^ WAT? } diff --git a/modules/st2-time/tests/test-time.js b/modules/st2-time/tests/test-time.js index b74581976..c5df04909 100644 --- a/modules/st2-time/tests/test-time.js +++ b/modules/st2-time/tests/test-time.js @@ -20,9 +20,9 @@ import { ReactTester } from '@stackstorm/module-test-utils'; import Time from '..'; function isDST(d) { - let jan = new Date(d.getFullYear(), 0, 1).getTimezoneOffset(); - let jul = new Date(d.getFullYear(), 6, 1).getTimezoneOffset(); - return Math.max(jan, jul) != d.getTimezoneOffset(); + const jan = new Date(d.getFullYear(), 0, 1).getTimezoneOffset(); + const jul = new Date(d.getFullYear(), 6, 1).getTimezoneOffset(); + return Math.max(jan, jul) !== d.getTimezoneOffset(); } describe(`${Time.name} Component`, () => { diff --git a/modules/st2flow-canvas/index.js b/modules/st2flow-canvas/index.js index 19e459cbc..040c2a836 100644 --- a/modules/st2flow-canvas/index.js +++ b/modules/st2flow-canvas/index.js @@ -22,7 +22,6 @@ import { TransitionInterface, } from '@stackstorm/st2flow-model/interfaces'; import { NotificationInterface } from '@stackstorm/st2flow-notifications'; -import { Node } from 'react'; import React, { Component } from 'react'; import { connect } from 'react-redux'; @@ -48,7 +47,6 @@ import PoissonRectangleSampler from './poisson-rect'; import { origin } from './const'; import style from './style.css'; -import store from '../../apps/st2-workflows/store'; type DOMMatrix = { m11: number, m22: number @@ -228,6 +226,9 @@ export default class Canvas extends Component { nextTask: PropTypes.string, isCollapsed: PropTypes.object, toggleCollapse: PropTypes.func, + dirtyflag: PropTypes.bool, + fetchActionscalled: PropTypes.func, + saveData: PropTypes.func, } state = { diff --git a/modules/st2flow-details/orquesta-properties.js b/modules/st2flow-details/orquesta-properties.js index 8913df4da..b0d6bbf80 100644 --- a/modules/st2flow-details/orquesta-properties.js +++ b/modules/st2flow-details/orquesta-properties.js @@ -46,7 +46,6 @@ type TransitionProps = { }) ) export default class OrquestaTransition extends Component { - static propTypes = { task: PropTypes.object.isRequired, issueModelCommand: PropTypes.func, @@ -64,7 +63,10 @@ export default class OrquestaTransition extends Component { } getValue(value) { - if(!isNaN(value) && value!== '') value = parseInt(value,10); + if (!isNaN(value) && value !== '') { + value = parseInt(value,10); + } + return value; } @@ -119,8 +121,8 @@ export default class OrquestaTransition extends Component { this.handleTaskProperty('delay', value ? '10' : false)}> { task.delay != null && ( -
-