Skip to content

Commit

Permalink
Merge branch 'master' into fix/errorsavedobjects
Browse files Browse the repository at this point in the history
  • Loading branch information
ppisljar committed May 14, 2020
2 parents 4d59a6c + b560705 commit 71e30b0
Show file tree
Hide file tree
Showing 319 changed files with 38,982 additions and 4,824 deletions.
95 changes: 16 additions & 79 deletions .ci/Jenkinsfile_coverage
Original file line number Diff line number Diff line change
Expand Up @@ -5,89 +5,26 @@ kibanaLibrary.load() // load from the Jenkins instance

kibanaPipeline(timeoutMinutes: 240) {
catchErrors {
def timestamp = new Date(currentBuild.startTimeInMillis).format("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("UTC"))
withEnv([
'CODE_COVERAGE=1', // Needed for multiple ci scripts, such as remote.ts, test/scripts/*.sh, schema.js, etc.
"TIME_STAMP=${timestamp}",
'CODE_COVERAGE=1', // Enables coverage. Needed for multiple ci scripts, such as remote.ts, test/scripts/*.sh, schema.js, etc.
]) {
parallel([
'kibana-intake-agent': workers.intake('kibana-intake', './test/scripts/jenkins_unit.sh'),
'x-pack-intake-agent': {
withEnv([
'NODE_ENV=test' // Needed for jest tests only
]) {
workers.intake('x-pack-intake', './test/scripts/jenkins_xpack.sh')()
}
},
'kibana-oss-agent': workers.functional('kibana-oss-tests', { kibanaPipeline.buildOss() }, [
'oss-ciGroup1': kibanaPipeline.ossCiGroupProcess(1),
'oss-ciGroup2': kibanaPipeline.ossCiGroupProcess(2),
'oss-ciGroup3': kibanaPipeline.ossCiGroupProcess(3),
'oss-ciGroup4': kibanaPipeline.ossCiGroupProcess(4),
'oss-ciGroup5': kibanaPipeline.ossCiGroupProcess(5),
'oss-ciGroup6': kibanaPipeline.ossCiGroupProcess(6),
'oss-ciGroup7': kibanaPipeline.ossCiGroupProcess(7),
'oss-ciGroup8': kibanaPipeline.ossCiGroupProcess(8),
'oss-ciGroup9': kibanaPipeline.ossCiGroupProcess(9),
'oss-ciGroup10': kibanaPipeline.ossCiGroupProcess(10),
'oss-ciGroup11': kibanaPipeline.ossCiGroupProcess(11),
'oss-ciGroup12': kibanaPipeline.ossCiGroupProcess(12),
]),
'kibana-xpack-agent': workers.functional('kibana-xpack-tests', { kibanaPipeline.buildXpack() }, [
'xpack-ciGroup1': kibanaPipeline.xpackCiGroupProcess(1),
'xpack-ciGroup2': kibanaPipeline.xpackCiGroupProcess(2),
'xpack-ciGroup3': kibanaPipeline.xpackCiGroupProcess(3),
'xpack-ciGroup4': kibanaPipeline.xpackCiGroupProcess(4),
'xpack-ciGroup5': kibanaPipeline.xpackCiGroupProcess(5),
'xpack-ciGroup6': kibanaPipeline.xpackCiGroupProcess(6),
'xpack-ciGroup7': kibanaPipeline.xpackCiGroupProcess(7),
'xpack-ciGroup8': kibanaPipeline.xpackCiGroupProcess(8),
'xpack-ciGroup9': kibanaPipeline.xpackCiGroupProcess(9),
'xpack-ciGroup10': kibanaPipeline.xpackCiGroupProcess(10),
]),
])
workers.base(name: 'coverage-worker', size: 'l', ramDisk: false, bootstrapped: false) {
kibanaPipeline.downloadCoverageArtifacts()
kibanaPipeline.bash(
'''
# bootstrap from x-pack folder
source src/dev/ci_setup/setup_env.sh
cd x-pack
yarn kbn bootstrap --prefer-offline
cd ..
# extract archives
mkdir -p /tmp/extracted_coverage
echo extracting intakes
tar -xzf /tmp/downloaded_coverage/coverage/kibana-intake/kibana-coverage.tar.gz -C /tmp/extracted_coverage
tar -xzf /tmp/downloaded_coverage/coverage/x-pack-intake/kibana-coverage.tar.gz -C /tmp/extracted_coverage
echo extracting kibana-oss-tests
tar -xzf /tmp/downloaded_coverage/coverage/kibana-oss-tests/kibana-coverage.tar.gz -C /tmp/extracted_coverage
echo extracting kibana-xpack-tests
tar -xzf /tmp/downloaded_coverage/coverage/kibana-xpack-tests/kibana-coverage.tar.gz -C /tmp/extracted_coverage
# replace path in json files to have valid html report
pwd=$(pwd)
du -sh /tmp/extracted_coverage/target/kibana-coverage/
echo replacing path in json files
for i in {1..9}; do
sed -i "s|/dev/shm/workspace/kibana|$pwd|g" /tmp/extracted_coverage/target/kibana-coverage/functional/${i}*.json &
done
wait
# merge oss & x-pack reports
echo merging coverage reports
yarn nyc report --temp-dir /tmp/extracted_coverage/target/kibana-coverage/jest --report-dir target/kibana-coverage/jest-combined --reporter=html --reporter=json-summary
yarn nyc report --temp-dir /tmp/extracted_coverage/target/kibana-coverage/functional --report-dir target/kibana-coverage/functional-combined --reporter=html --reporter=json-summary
echo copy mocha reports
mkdir -p target/kibana-coverage/mocha-combined
cp -r /tmp/extracted_coverage/target/kibana-coverage/mocha target/kibana-coverage/mocha-combined
''',
"run `yarn kbn bootstrap && merge coverage`"
)
sh 'tar -czf kibana-jest-coverage.tar.gz target/kibana-coverage/jest-combined/*'
kibanaPipeline.uploadCoverageArtifacts("coverage/jest-combined", 'kibana-jest-coverage.tar.gz')
sh 'tar -czf kibana-functional-coverage.tar.gz target/kibana-coverage/functional-combined/*'
kibanaPipeline.uploadCoverageArtifacts("coverage/functional-combined", 'kibana-functional-coverage.tar.gz')
sh 'tar -czf kibana-mocha-coverage.tar.gz target/kibana-coverage/mocha-combined/*'
kibanaPipeline.uploadCoverageArtifacts("coverage/mocha-combined", 'kibana-mocha-coverage.tar.gz')
kibanaCoverage.runTests()
handleIngestion(TIME_STAMP)
}
}
kibanaPipeline.sendMail()
}
kibanaPipeline.sendMail()
}

def handleIngestion(timestamp) {
kibanaPipeline.downloadCoverageArtifacts()
kibanaCoverage.prokLinks("### Process HTML Links")
kibanaCoverage.collectVcsInfo("### Collect VCS Info")
kibanaCoverage.ingest(timestamp, '### Injest && Upload')
kibanaCoverage.uploadCoverageStaticSite(timestamp)
}


32 changes: 17 additions & 15 deletions .ci/Jenkinsfile_visual_baseline
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@ library 'kibana-pipeline-library'
kibanaLibrary.load()

kibanaPipeline(timeoutMinutes: 120) {
catchError {
parallel([
'oss-visualRegression': {
workers.ci(name: 'oss-visualRegression', size: 's', ramDisk: false) {
kibanaPipeline.functionalTestProcess('oss-visualRegression', './test/scripts/jenkins_visual_regression.sh')(1)
}
},
'xpack-visualRegression': {
workers.ci(name: 'xpack-visualRegression', size: 's', ramDisk: false) {
kibanaPipeline.functionalTestProcess('xpack-visualRegression', './test/scripts/jenkins_xpack_visual_regression.sh')(1)
}
},
])
}
ciStats.trackBuild {
catchError {
parallel([
'oss-visualRegression': {
workers.ci(name: 'oss-visualRegression', size: 's', ramDisk: false) {
kibanaPipeline.functionalTestProcess('oss-visualRegression', './test/scripts/jenkins_visual_regression.sh')(1)
}
},
'xpack-visualRegression': {
workers.ci(name: 'xpack-visualRegression', size: 's', ramDisk: false) {
kibanaPipeline.functionalTestProcess('xpack-visualRegression', './test/scripts/jenkins_xpack_visual_regression.sh')(1)
}
},
])
}

kibanaPipeline.sendMail()
kibanaPipeline.sendMail()
}
}
5 changes: 4 additions & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@
/src/legacy/server/utils/ @elastic/kibana-operations
/src/legacy/server/warnings/ @elastic/kibana-operations

# Quality Assurance
/src/dev/code_coverage @elastic/kibana-qa

# Platform
/src/core/ @elastic/kibana-platform
/config/kibana.yml @elastic/kibana-platform
Expand Down Expand Up @@ -161,8 +164,8 @@

# Pulse
/packages/kbn-analytics/ @elastic/pulse
/src/legacy/core_plugins/ui_metric/ @elastic/pulse
/src/plugins/kibana_usage_collection/ @elastic/pulse
/src/plugins/newsfeed/ @elastic/pulse
/src/plugins/telemetry/ @elastic/pulse
/src/plugins/telemetry_collection_manager/ @elastic/pulse
/src/plugins/telemetry_management_section/ @elastic/pulse
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ npm-debug.log*
.tern-project
x-pack/plugins/apm/tsconfig.json
apm.tsconfig.json
/x-pack/legacy/plugins/apm/e2e/snapshots.js
/x-pack/plugins/apm/e2e/snapshots.js
.nyc_output
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@
"spec_to_console": "node scripts/spec_to_console",
"backport-skip-ci": "backport --prDescription \"[skip-ci]\"",
"storybook": "node scripts/storybook",
"cover:report": "nyc report --temp-dir target/kibana-coverage/functional --report-dir target/coverage/report --reporter=lcov && open ./target/coverage/report/lcov-report/index.html"
"cover:report": "nyc report --temp-dir target/kibana-coverage/functional --report-dir target/coverage/report --reporter=lcov && open ./target/coverage/report/lcov-report/index.html",
"cover:functional:merge": "nyc report --temp-dir target/kibana-coverage/functional --report-dir target/coverage/report/functional --reporter=json-summary"
},
"repository": {
"type": "git",
Expand Down
11 changes: 7 additions & 4 deletions packages/kbn-spec-to-console/lib/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,16 @@ module.exports = spec => {
Object.keys(spec).forEach(api => {
const source = spec[api];

if (source.url.paths.every(path => Boolean(path.deprecated))) {
return;
}

if (!source.url) {
return result;
}

if (source.url.path) {
if (source.url.paths.every(path => Boolean(path.deprecated))) {
return;
}
}

const convertedSpec = (result[api] = {});
if (source.params) {
const urlParams = convertParams(source.params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,5 @@
* under the License.
*/

export const NEWSFEED_FALLBACK_LANGUAGE = 'en';
export const NEWSFEED_LAST_FETCH_STORAGE_KEY = 'newsfeed.lastfetchtime';
export const NEWSFEED_HASH_SET_STORAGE_KEY = 'newsfeed.hashes';
require('../src/setup_node_env');
require('../src/dev/code_coverage/ingest_coverage').runCoverageIngestionCli();
30 changes: 30 additions & 0 deletions src/core/CONVENTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,36 @@ export class MyPlugin implements Plugin {
}
```

Prefer the pattern shown above, using `core.getStartServices()`, rather than store local references retrieved from `start`.

**Bad:**
```ts
export class MyPlugin implements Plugin {
// Anti pattern
private coreStart?: CoreStart;
private depsStart?: DepsStart;

public setup(core) {
core.application.register({
id: 'my-app',
async mount(params) {
const { renderApp } = await import('./application/my_app');
// Anti pattern - use `core.getStartServices()` instead!
return renderApp(this.coreStart, this.depsStart, params);
}
});
}

public start(core, deps) {
// Anti pattern
this.coreStart = core;
this.depsStart = deps;
}
}
```

The main reason to prefer the provided async accessor, is that it doesn't requires the developer to understand and reason about when that function can be called. Having an API that fails sometimes isn't a good API design, and it makes accurately testing this difficult.

#### Services

Service structure should mirror the plugin lifecycle to make reasoning about how the service is executed more clear.
Expand Down
2 changes: 2 additions & 0 deletions src/core/public/application/application_service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ export class ApplicationService {
appBasePath: basePath.prepend(app.appRoute!),
mount: wrapMount(plugin, app),
unmountBeforeMounting: false,
legacy: false,
});
},
registerLegacyApp: app => {
Expand Down Expand Up @@ -232,6 +233,7 @@ export class ApplicationService {
appBasePath,
mount,
unmountBeforeMounting: true,
legacy: true,
});
},
registerAppUpdater: (appUpdater$: Observable<AppUpdater>) =>
Expand Down
22 changes: 21 additions & 1 deletion src/core/public/application/integration_tests/router.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { createRenderer, createAppMounter, createLegacyAppMounter, getUnmounter
import { AppStatus } from '../types';
import { ScopedHistory } from '../scoped_history';

describe('AppContainer', () => {
describe('AppRouter', () => {
let mounters: MockedMounterMap<EitherApp>;
let globalHistory: History;
let appStatuses$: BehaviorSubject<Map<string, AppStatus>>;
Expand Down Expand Up @@ -78,6 +78,16 @@ describe('AppContainer', () => {
history.push('/subpath');
},
}),
createAppMounter({
appId: 'app5',
html: '<div>App 5</div>',
appRoute: '/app/my-app/app5',
}),
createAppMounter({
appId: 'app6',
html: '<div>App 6</div>',
appRoute: '/app/my-app/app6',
}),
] as Array<MockedMounterTuple<EitherApp>>);
globalHistory = createMemoryHistory();
appStatuses$ = mountersToAppStatus$();
Expand Down Expand Up @@ -282,6 +292,16 @@ describe('AppContainer', () => {
expect(unmount).not.toHaveBeenCalled();
});

it('allows multiple apps with the same `/app/appXXX` appRoute prefix', async () => {
await navigate('/app/my-app/app5/path');
expect(mounters.get('app5')!.mounter.mount).toHaveBeenCalledTimes(1);
expect(mounters.get('app6')!.mounter.mount).toHaveBeenCalledTimes(0);

await navigate('/app/my-app/app6/another-path');
expect(mounters.get('app5')!.mounter.mount).toHaveBeenCalledTimes(1);
expect(mounters.get('app6')!.mounter.mount).toHaveBeenCalledTimes(1);
});

it('should not remount when when changing pages within app using hash history', async () => {
globalHistory = createHashHistory();
update = createRenderer(
Expand Down
2 changes: 2 additions & 0 deletions src/core/public/application/integration_tests/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export const createAppMounter = ({
mounter: {
appRoute,
appBasePath: appRoute,
legacy: false,
mount: jest.fn(async (params: AppMountParameters) => {
const { appBasePath: basename, element } = params;
Object.assign(element, {
Expand Down Expand Up @@ -88,6 +89,7 @@ export const createLegacyAppMounter = (
appRoute: `/app/${appId.split(':')[0]}`,
appBasePath: `/app/${appId.split(':')[0]}`,
unmountBeforeMounting: true,
legacy: true,
mount: legacyMount,
},
unmount: jest.fn(),
Expand Down
1 change: 1 addition & 0 deletions src/core/public/application/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ export type Mounter<T = App | LegacyApp> = SelectivePartial<
appRoute: string;
appBasePath: string;
mount: T extends LegacyApp ? LegacyAppMounter : AppMounter;
legacy: boolean;
unmountBeforeMounting: T extends LegacyApp ? true : boolean;
},
T extends LegacyApp ? never : 'unmountBeforeMounting'
Expand Down
4 changes: 3 additions & 1 deletion src/core/public/application/ui/app_container.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ describe('AppContainer', () => {
appBasePath: '/base-path',
appRoute: '/some-route',
unmountBeforeMounting: false,
legacy: false,
mount: async ({ element }: AppMountParameters) => {
await promise;
const container = document.createElement('div');
Expand Down Expand Up @@ -138,9 +139,10 @@ describe('AppContainer', () => {
it('should call setIsMounting(false) if mounting throws', async () => {
const [waitPromise, resolvePromise] = createResolver();
const mounter = {
appBasePath: '/base-path',
appBasePath: '/base-path/some-route',
appRoute: '/some-route',
unmountBeforeMounting: false,
legacy: false,
mount: async ({ element }: AppMountParameters) => {
await waitPromise;
throw new Error(`Mounting failed!`);
Expand Down
39 changes: 19 additions & 20 deletions src/core/public/application/ui/app_router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,26 +55,25 @@ export const AppRouter: FunctionComponent<Props> = ({
return (
<Router history={history}>
<Switch>
{[...mounters].flatMap(([appId, mounter]) =>
// Remove /app paths from the routes as they will be handled by the
// "named" route parameter `:appId` below
mounter.appBasePath.startsWith('/app')
? []
: [
<Route
key={mounter.appRoute}
path={mounter.appRoute}
render={({ match: { url } }) => (
<AppContainer
appPath={url}
appStatus={appStatuses.get(appId) ?? AppStatus.inaccessible}
createScopedHistory={createScopedHistory}
{...{ appId, mounter, setAppLeaveHandler, setIsMounting }}
/>
)}
/>,
]
)}
{[...mounters]
// legacy apps can have multiple sub-apps registered with the same route
// which needs additional logic that is handled in the catch-all route below
.filter(([_, mounter]) => !mounter.legacy)
.map(([appId, mounter]) => (
<Route
key={mounter.appRoute}
path={mounter.appRoute}
render={({ match: { url } }) => (
<AppContainer
appPath={url}
appStatus={appStatuses.get(appId) ?? AppStatus.inaccessible}
createScopedHistory={createScopedHistory}
{...{ appId, mounter, setAppLeaveHandler, setIsMounting }}
/>
)}
/>
))}
{/* handler for legacy apps and used as a catch-all to display 404 page on not existing /app/appId apps*/}
<Route
path="/app/:appId"
render={({
Expand Down
Loading

0 comments on commit 71e30b0

Please sign in to comment.