Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Reporting/New Platform] Provide async access to server-side dependencies #56824

Merged
merged 12 commits into from
Feb 14, 2020

Conversation

tsullivan
Copy link
Member

@tsullivan tsullivan commented Feb 5, 2020

Summary

Related #53898

Migrates the Reporting plugin server-side to access these dependences outside of the context of a request:

  • savedObjectsClient
  • uiSettingsService

Since these dependences are available in the start method of the new ReportingPlugin class, I have moved some setup code to start:

  • esqueue
  • enqueueJobFn

Previous init functionality is still run in the setup method, such as validating the configuration (and setting default encryption key) and setting the routes.

In this PR, the ReportingPlugin class provides async getters for all of these dependencies. The reporting object is now passed to route registration and is now part of the export type definitions. This is a new facade utilized by a large part of the Reporting server-side code, which amounts to a lot of lines of code change in this PR.

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-reporting-services (Team:Reporting Services)

@elasticmachine
Copy link
Contributor

💔 Build Failed


Test Failures

Kibana Pipeline / kibana-xpack-agent / Chrome X-Pack UI Functional Tests.x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security·ts.Advanced Settings security feature controls "before all" hook

Link to Jenkins

Standard Out

Failed Tests Reporter:
  - Test has not failed recently on tracked branches

[00:00:00]       │
[00:00:00]         └-: Advanced Settings
[00:00:00]           └-> "before all" hook
[00:00:00]           └-: security feature controls
[00:00:00]             └-> "before all" hook
[00:00:00]             └-> "before all" hook
[00:00:00]               │ info [empty_kibana] Loading "mappings.json"
[00:00:00]               │ info [empty_kibana] Loading "data.json.gz"
[00:00:00]               │ info [o.e.c.m.MetaDataDeleteIndexService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] [.kibana_1/VXVWVp4BSnq0GdnOaAX_YQ] deleting index
[00:00:00]               │ info [empty_kibana] Deleted existing index [".kibana_1"]
[00:00:00]               │ info [o.e.c.m.MetaDataCreateIndexService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] [.kibana] creating index, cause [api], templates [], shards [1]/[1], mappings [_doc]
[00:00:00]               │ info [empty_kibana] Created index ".kibana"
[00:00:00]               │ debg [empty_kibana] ".kibana" settings {"index":{"number_of_replicas":"1","number_of_shards":"1"}}
[00:00:00]               │ info [empty_kibana] Indexed 2 docs into ".kibana"
[00:00:40]               │ proc [kibana]   log   [11:44:29.670] [warning][reporting] Generating a random key for xpack.reporting.encryptionKey. To prevent pending reports from failing on restart, please set xpack.reporting.encryptionKey in kibana.yml
[00:00:40]               │ proc [kibana] internal/process/warning.js:153
[00:00:40]               │ proc [kibana]         throw warning;
[00:00:40]               │ proc [kibana]         ^
[00:00:40]               │ proc [kibana] 
[00:00:40]               │ proc [kibana] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
[00:00:40]               │ proc [kibana]     at emitDeprecationWarning (internal/process/promises.js:111:13)
[00:00:40]               │ proc [kibana]     at emitWarning (internal/process/promises.js:104:3)
[00:00:40]               │ proc [kibana]     at emitPromiseRejectionWarnings (internal/process/promises.js:143:7)
[00:00:40]               │ proc [kibana]     at process._tickCallback (internal/process/next_tick.js:69:34)
[00:00:40]               └- ✖ fail: "Advanced Settings security feature controls "before all" hook"
[00:00:40]               │

Stack Trace

{ DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    at emitDeprecationWarning (internal/process/promises.js:111:13)
    at emitWarning (internal/process/promises.js:104:3)
    at emitPromiseRejectionWarnings (internal/process/promises.js:143:7)
    at process._tickCallback (internal/process/next_tick.js:69:34) name: 'DeprecationWarning', code: 'DEP0018', uncaught: true }

Kibana Pipeline / kibana-xpack-agent / Chrome X-Pack UI Functional Tests.x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security·ts.Advanced Settings security feature controls "after all" hook in "security feature controls"

Link to Jenkins

Standard Out

Failed Tests Reporter:
  - Test has not failed recently on tracked branches

[00:00:00]       │
[00:00:00]         └-: Advanced Settings
[00:00:00]           └-> "before all" hook
[00:00:00]           └-: security feature controls
[00:00:00]             └-> "before all" hook
[00:00:00]             └-> "before all" hook
[00:00:00]               │ info [empty_kibana] Loading "mappings.json"
[00:00:00]               │ info [empty_kibana] Loading "data.json.gz"
[00:00:00]               │ info [o.e.c.m.MetaDataDeleteIndexService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] [.kibana_1/VXVWVp4BSnq0GdnOaAX_YQ] deleting index
[00:00:00]               │ info [empty_kibana] Deleted existing index [".kibana_1"]
[00:00:00]               │ info [o.e.c.m.MetaDataCreateIndexService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] [.kibana] creating index, cause [api], templates [], shards [1]/[1], mappings [_doc]
[00:00:00]               │ info [empty_kibana] Created index ".kibana"
[00:00:00]               │ debg [empty_kibana] ".kibana" settings {"index":{"number_of_replicas":"1","number_of_shards":"1"}}
[00:00:00]               │ info [empty_kibana] Indexed 2 docs into ".kibana"
[00:00:40]               │ proc [kibana]   log   [11:44:29.670] [warning][reporting] Generating a random key for xpack.reporting.encryptionKey. To prevent pending reports from failing on restart, please set xpack.reporting.encryptionKey in kibana.yml
[00:00:40]               │ proc [kibana] internal/process/warning.js:153
[00:00:40]               │ proc [kibana]         throw warning;
[00:00:40]               │ proc [kibana]         ^
[00:00:40]               │ proc [kibana] 
[00:00:40]               │ proc [kibana] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
[00:00:40]               │ proc [kibana]     at emitDeprecationWarning (internal/process/promises.js:111:13)
[00:00:40]               │ proc [kibana]     at emitWarning (internal/process/promises.js:104:3)
[00:00:40]               │ proc [kibana]     at emitPromiseRejectionWarnings (internal/process/promises.js:143:7)
[00:00:40]               │ proc [kibana]     at process._tickCallback (internal/process/next_tick.js:69:34)
[00:00:40]               └- ✖ fail: "Advanced Settings security feature controls "before all" hook"
[00:00:40]               │
[00:00:40]               └-> "after all" hook
[00:00:42]                 │ERROR [GET http://elastic:changeme@localhost:6131/api/status] request failed (attempt=1/5)
[00:00:43]                 │ info Creating index .kibana_2.
[00:00:43]                 │ info [o.e.c.m.MetaDataCreateIndexService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] [.kibana_2] creating index, cause [api], templates [], shards [1]/[1], mappings [_doc]
[00:00:43]                 │ info [o.e.c.r.a.AllocationService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] updating number_of_replicas to [0] for indices [.kibana_2]
[00:00:43]                 │ info Reindexing .kibana to .kibana_1
[00:00:43]                 │ info [o.e.c.m.MetaDataCreateIndexService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] [.kibana_1] creating index, cause [api], templates [], shards [1]/[1], mappings [_doc]
[00:00:43]                 │ info [o.e.c.r.a.AllocationService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] updating number_of_replicas to [0] for indices [.kibana_1]
[00:00:43]                 │ info [o.e.c.m.MetaDataCreateIndexService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] [.tasks] creating index, cause [auto(task api)], templates [], shards [1]/[1], mappings [_doc]
[00:00:43]                 │ info [o.e.c.r.a.AllocationService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] updating number_of_replicas to [0] for indices [.tasks]
[00:00:43]                 │ info [o.e.t.LoggingTaskListener] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] 574 finished with response BulkByScrollResponse[took=52.9ms,timed_out=false,sliceId=null,updated=0,created=2,deleted=0,batches=1,versionConflicts=0,noops=0,retries=0,throttledUntil=0s,bulk_failures=[],search_failures=[]]
[00:00:43]                 │ info [o.e.c.m.MetaDataDeleteIndexService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] [.kibana/veOPJoT1SUmKi8AvtxPHrQ] deleting index
[00:00:43]                 │ info Migrating .kibana_1 saved objects to .kibana_2
[00:00:43]                 │ debg Migrating saved objects config:6.0.0-alpha1, space:default
[00:00:43]                 │ info [o.e.c.m.MetaDataMappingService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] [.kibana_2/M_HfQSbeRwWelyMvddm2EA] update_mapping [_doc]
[00:00:43]                 │ERROR [GET http://elastic:changeme@localhost:6131/api/status] request failed (attempt=2/5)
[00:00:43]                 │ info [o.e.c.m.MetaDataMappingService] [kibana-ci-immutable-debian-tests-xl-1581074022536679471] [.kibana_2/M_HfQSbeRwWelyMvddm2EA] update_mapping [_doc]
[00:00:43]                 │ info Pointing alias .kibana to .kibana_2.
[00:00:43]                 │ info Finished in 793ms.
[00:00:43]                 │ debg applying update to kibana config: {"accessibility:disableAnimations":true,"dateFormat:tz":"UTC"}
[00:00:43]                 │ERROR [POST http://elastic:changeme@localhost:6131/api/kibana/settings] request failed (attempt=1/5)
[00:00:44]                 │ERROR [POST http://elastic:changeme@localhost:6131/api/kibana/settings] request failed (attempt=2/5)
[00:00:45]                 │ERROR [GET http://elastic:changeme@localhost:6131/api/status] request failed (attempt=3/5)
[00:00:46]                 │ERROR [POST http://elastic:changeme@localhost:6131/api/kibana/settings] request failed (attempt=3/5)
[00:00:48]                 │ERROR [GET http://elastic:changeme@localhost:6131/api/status] request failed (attempt=4/5)
[00:00:49]                 │ERROR [POST http://elastic:changeme@localhost:6131/api/kibana/settings] request failed (attempt=4/5)
[00:00:52]                 │ERROR [GET http://elastic:changeme@localhost:6131/api/status] request failed (attempt=5/5)
[00:00:52]                 │ info Taking screenshot "/dev/shm/workspace/kibana/x-pack/test/functional/screenshots/failure/Advanced Settings security feature controls _after all_ hook.png"
[00:00:53]                 │ info Current URL is: data:/,
[00:00:53]                 │ info Saving page source to: /dev/shm/workspace/kibana/x-pack/test/functional/failure_debug/html/Advanced Settings security feature controls _after all_ hook.html
[00:00:53]                 └- ✖ fail: "Advanced Settings security feature controls "after all" hook in "security feature controls""
[00:00:53]                 │

Stack Trace

Error: [GET http://elastic:changeme@localhost:6131/api/status] request failed (attempt=5/5) -- and ran out of retries
    at KbnClientRequester.request (/dev/shm/workspace/kibana/packages/kbn-dev-utils/target/kbn_client/kbn_client_requester.js:99:23)
    at process._tickCallback (internal/process/next_tick.js:68:7)

Kibana Pipeline / kibana-xpack-agent / Chrome X-Pack UI Functional Tests.x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode·js.dashboard mode Dashboard View Mode "before all" hook: initialize tests

Link to Jenkins

Standard Out

Failed Tests Reporter:
  - Test has not failed recently on tracked branches

[00:00:00]       │
[00:00:00]         └-: dashboard mode
[00:00:00]           └-> "before all" hook
[00:00:00]           └-: Dashboard View Mode
[00:00:00]             └-> "before all" hook
[00:00:00]             └-> "before all" hook: initialize tests
[00:00:00]               │ debg Dashboard View Mode:initTests
[00:00:00]               │ proc [kibana] internal/process/warning.js:153
[00:00:00]               │ proc [kibana]         throw warning;
[00:00:00]               │ proc [kibana]         ^
[00:00:00]               │ proc [kibana] 
[00:00:00]               │ proc [kibana] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
[00:00:00]               │ proc [kibana]     at emitDeprecationWarning (internal/process/promises.js:111:13)
[00:00:00]               │ proc [kibana]     at emitWarning (internal/process/promises.js:104:3)
[00:00:00]               │ proc [kibana]     at emitPromiseRejectionWarnings (internal/process/promises.js:143:7)
[00:00:00]               │ proc [kibana]     at process._tickCallback (internal/process/next_tick.js:69:34)
[00:00:00]               │ERROR [GET http://elastic:changeme@localhost:6181/api/status] request failed (attempt=1/5)
[00:00:00]               └- ✖ fail: "dashboard mode Dashboard View Mode "before all" hook: initialize tests"
[00:00:00]               │

Stack Trace

{ DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    at emitDeprecationWarning (internal/process/promises.js:111:13)
    at emitWarning (internal/process/promises.js:104:3)
    at emitPromiseRejectionWarnings (internal/process/promises.js:143:7)
    at process._tickCallback (internal/process/next_tick.js:69:34) name: 'DeprecationWarning', code: 'DEP0018', uncaught: true }

and 51 more failures, only showing the first 3.

History

  • 💔 Build #24513 failed fbc9163b48da5dcdda11ee92c7ee35d3fa82b1e3

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@elastic elastic deleted a comment from kibanamachine Feb 7, 2020
@tsullivan tsullivan force-pushed the reporting/np-server-uisettings branch 2 times, most recently from 5e89c52 to 073cbcf Compare February 11, 2020 21:48
@tsullivan tsullivan added Feature:NP Migration (Deprecated) Feature:Reporting Use Reporting:Screenshot, Reporting:CSV, or Reporting:Framework instead v7.7.0 v8.0.0 labels Feb 12, 2020
@tsullivan tsullivan marked this pull request as ready for review February 12, 2020 20:25
@tsullivan tsullivan changed the title [Reporting/New Platform] Async access for cross-plugin server-side dependencies [Reporting/New Platform] Provide async access to server-side dependencies Feb 12, 2020
@tsullivan tsullivan added the release_note:skip Skip the PR/issue when compiling release notes label Feb 12, 2020
@tsullivan tsullivan force-pushed the reporting/np-server-uisettings branch from 9d57ada to 807be16 Compare February 12, 2020 20:34
@tsullivan tsullivan force-pushed the reporting/np-server-uisettings branch from 807be16 to 1a9e839 Compare February 12, 2020 21:18
@tsullivan tsullivan force-pushed the reporting/np-server-uisettings branch from 1a9e839 to 25dc761 Compare February 12, 2020 21:20
@tsullivan tsullivan force-pushed the reporting/np-server-uisettings branch from c391413 to dd0fd40 Compare February 13, 2020 00:32
};

const savedObjects = server.savedObjects;
const savedObjectsClient = savedObjects.getScopedSavedObjectsClient(fakeRequest);
const uiSettings = server.uiSettingsServiceFactory({ savedObjectsClient });
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed legacy dependency here

);
const uiConfig = server.uiSettingsServiceFactory({
savedObjectsClient,
});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed legacy dependency here

@@ -22,8 +22,6 @@ const buildLegacyDependencies = (
xpack_main: server.plugins.xpack_main,
reporting: reportingPlugin,
},
savedObjects: server.savedObjects,
uiSettingsServiceFactory: server.uiSettingsServiceFactory,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed legacy dependencies here

server: ServerFacade,
elasticsearch: ElasticsearchServiceSetup,
logger: Logger,
searchPanel: SearchPanel,
jobParams: JobParamsDiscoverCsv
): Promise<CsvResultFromSearch> {
const { savedObjects, uiSettingsServiceFactory } = server;
const savedObjectsClient = savedObjects.getScopedSavedObjectsClient(
const savedObjectsClient = await reporting.getSavedObjectsClient(
Copy link
Member Author

@tsullivan tsullivan Feb 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed legacy dependency here and from line 76

) {
const browserDriverFactory = await reporting.getBrowserDriverFactory();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're also using other accessor methods to get internal dependencies that are available after setup, like this getBrowserDriverFactory and even getEsqueue

server: ServerFacade,
elasticsearch: ElasticsearchServiceSetup,
logger: Logger,
{ exportTypesRegistry, browserDriverFactory }: CreateQueueFactoryOpts
): Esqueue {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since more accessors exist on the reporting object, I have simplified signatures like this because the extra opts no longer need to be passed separately

Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach chosen to be able to pass dependencies only available during start to the route handlers that must be defined during setup definitely makes sense, and follows the suggested approach.

As explained in the comments:

  • I would still avoid passing the whole and concrete ReportingPlugin instance alongs the whole chain, and use a specialized type or at least interface for that
  • The plugin's start (and setup also it seems) method is currently returning an internal contract instead of a public (or empty) one. From what I see, these returns even seems unused as the calls in x-pack/legacy/plugins/reporting/server/legacy.ts are ignoring them, so I would remove that

Comment on lines +35 to 36
logger.error(err);
logger.warning(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: logging both an error and a warning?

xpackMainPlugin.info.feature(PLUGIN_ID).registerLicenseCheckResultsGenerator(checkLicense);
});
// Reporting routes
registerRoutes(this, __LEGACY, plugins, this.logger);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For isolation and testability sake, I would really avoid using the concrete ReportingPlugin type for the registerRoutes (and every nested calls) signature, and use a specialized interface instead. Actually passing the plugin instance as the implementation is fine I think, but I would create a real fascade interface containing only the internally used methods, to at least excludes start and setup from the contract, something like Pick<ReportingPlugin, 'getEsqueue' | ...>

Another slight inprovement (imho) from this initial proposal would be to extract this contract you put in the ReportingPlugin class to another class and use it instead

Something like

const internalContract = new ReportingInternals(this.pluginStartDeps, this.exportTypesRegistry, [probably others]);
registerRoutes(internalContract, __LEGACY, plugins, this.logger);


// Reporting routes
registerRoutes(__LEGACY, plugins, exportTypesRegistry, browserDriverFactory, logger);
return this.pluginStartDeps;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is supposed to be the plugin's public contract. You are currently returning an internal contract, which doesn't really make any sense of any plugins that may want to consume your API (even if I get that reporting is more of a 'end of chain' plugin, this still doesn't respect the core conventions)

this.pluginStartDeps = {
      savedObjects: core.savedObjects,
      uiSettings: core.uiSettings,
      esqueue,
      enqueueJob,
    };

My question is: I see you are using that internally (this.pluginStart$.next(this.pluginStartDeps);), but do you use anywhere this contract from the actual plugin's start return?

  • if no, I would stick to returning an empty contract ({})
  • If you do need to access this from outside of the shim for any reason, I would wrap it inside an __internal property to make it clear that this a temporary measure during migration

This follows my previous comment, I think your pluginStartDeps should be more named such as reportingInternalStartDeps or something like that, as it is supposed to be only consumed from inside your plugin.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes senses to use a new types for Internal* instead of hooking into the types that were conveniently there :). Since I chose to use a type conveniently in scope, that forced me to return it. I get the point that it should only public expose internals as-needed by outside consumers

if no, I would stick to returning an empty contract ({})

👍

Comment on lines 20 to 29
>> = function executeJobFactoryFn(
>> = async function executeJobFactoryFn(
reporting: ReportingPlugin,
server: ServerFacade,
elasticsearch: ElasticsearchServiceSetup,
parentLogger: Logger
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: now that you introduced this ReportingPlugin internal that currently contains SO accessors such as reporting.getSavedObjectsClient(fakeRequest), it would probably makes sense to move the elasticsearch accessors inside it too instead of passing it as an additional parameter, for consistency.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the thought occurred to me as well, so 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to take this on in a future PR. It would make sense to get this in before working on the migration of our "config" usage on the server. Config can also follow the pattern of using an accessor on the reporting object.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fine with me

Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM for platform changes

@tsullivan
Copy link
Member Author

@elasticmachine merge upstream

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@tsullivan tsullivan merged commit 34ae99b into elastic:master Feb 14, 2020
@tsullivan tsullivan deleted the reporting/np-server-uisettings branch February 14, 2020 19:36
tsullivan added a commit to tsullivan/kibana that referenced this pull request Feb 14, 2020
…cies (elastic#56824)

* [Reporting/New Platform] Provide async access to server-side

* consistent name for reportingPlugin

* Prettier changes

* simplify reporting usage collector setup

* add more tests

* extract internals access to separate core class

* fix tests

* fix imports for jest and build

Co-authored-by: Elastic Machine <[email protected]>
tsullivan added a commit that referenced this pull request Feb 18, 2020
…pendencies (#56824) (#57727)

* [Reporting/New Platform] Provide async access to server-side dependencies (#56824)

* [Reporting/New Platform] Provide async access to server-side

* consistent name for reportingPlugin

* Prettier changes

* simplify reporting usage collector setup

* add more tests

* extract internals access to separate core class

* fix tests

* fix imports for jest and build

Co-authored-by: Elastic Machine <[email protected]>

* fix lint

* fix ts import

Co-authored-by: Elastic Machine <[email protected]>
@tsullivan tsullivan mentioned this pull request Feb 24, 2020
19 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
(Deprecated) Feature:Reporting Use Reporting:Screenshot, Reporting:CSV, or Reporting:Framework instead Feature:NP Migration release_note:skip Skip the PR/issue when compiling release notes v7.7.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants