Skip to content

Commit

Permalink
Merge branch 'main' into data-usage-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
neptunian authored Nov 21, 2024
2 parents 109d35b + cba99de commit e1d4dd8
Show file tree
Hide file tree
Showing 43 changed files with 595 additions and 232 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# yaml-language-server: $schema=https://gist.githubusercontent.com/elasticmachine/988b80dae436cafea07d9a4a460a011d/raw/rre.schema.json
apiVersion: backstage.io/v1alpha1
kind: Resource
metadata:
name: bk-kibana-console-definitions-sync
description: Opens a PR if anything changes in the console definitions in elasticsearch-definitions
links:
- url: 'https://buildkite.com/elastic/kibana-console-definitions-sync'
title: Pipeline link
spec:
type: buildkite-pipeline
owner: 'group:kibana-management'
system: buildkite
implementation:
apiVersion: buildkite.elastic.dev/v1
kind: Pipeline
metadata:
name: kibana / Console definitions sync
description: Opens a PR if anything changes in the console definitions in elasticsearch-definitions
spec:
env:
SLACK_NOTIFICATIONS_CHANNEL: '#kibana-management'
ELASTIC_SLACK_NOTIFICATIONS_ENABLED: 'true'
allow_rebuilds: false
branch_configuration: main
default_branch: main
repository: elastic/kibana
pipeline_file: .buildkite/pipelines/console_definitions_sync.yml
provider_settings:
build_branches: false
build_pull_requests: false
publish_commit_status: false
trigger_mode: none
build_tags: false
prefix_pull_request_fork_branch_names: false
skip_pull_request_builds_for_existing_commits: true
teams:
kibana-management:
access_level: MANAGE_BUILD_AND_READ
kibana-operations:
access_level: MANAGE_BUILD_AND_READ
appex-qa:
access_level: MANAGE_BUILD_AND_READ
kibana-tech-leads:
access_level: MANAGE_BUILD_AND_READ
everyone:
access_level: BUILD_AND_READ
schedules:
Weekly build:
cronline: 0 0 * * 1 America/New_York
message: Weekly build
branch: main
tags:
- kibana
10 changes: 10 additions & 0 deletions .buildkite/pipelines/console_definitions_sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
steps:
- command: .buildkite/scripts/steps/console_definitions_sync.sh
label: Console Definitions Sync
timeout_in_minutes: 10
agents:
image: family/kibana-ubuntu-2004
imageProject: elastic-images-prod
provider: gcp
machineType: n2-standard-2
preemptible: true
68 changes: 68 additions & 0 deletions .buildkite/scripts/steps/console_definitions_sync.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/env bash
set -euo pipefail

report_main_step () {
echo "--- $1"
}

main () {
cd "$PARENT_DIR"

report_main_step "Cloning repositories"

rm -rf elasticsearch-specification
if ! git clone https://github.com/elastic/elasticsearch-specification --depth 1; then
echo "Error: Failed to clone the elasticsearch-specification repository."
exit 1
fi

cd "$KIBANA_DIR"

report_main_step "Generating console definitions"
node scripts/generate_console_definitions.js --source "$PARENT_DIR/elasticsearch-specification" --emptyDest

# Check if there are any differences
set +e
git diff --exit-code --quiet "$destination_file"
if [ $? -eq 0 ]; then
echo "No differences found. Exiting.."
exit
fi
set -e

report_main_step "Differences found. Checking for an existing pull request."

KIBANA_MACHINE_USERNAME="kibanamachine"
git config --global user.name "$KIBANA_MACHINE_USERNAME"
git config --global user.email '[email protected]'

PR_TITLE='[Console] Update console definitions'
PR_BODY='This PR updates the console definitions to match the latest ones from the @elastic/elasticsearch-specification repo.'

# Check if a PR already exists
pr_search_result=$(gh pr list --search "$PR_TITLE" --state open --author "$KIBANA_MACHINE_USERNAME" --limit 1 --json title -q ".[].title")

if [ "$pr_search_result" == "$PR_TITLE" ]; then
echo "PR already exists. Exiting.."
exit
fi

echo "No existing PR found. Proceeding.."

# Commit diff
BRANCH_NAME="console_definitions_sync_$(date +%s)"

git checkout -b "$BRANCH_NAME"

git add src/plugins/console/server/lib/spec_definitions/json/generated/*
git commit -m "Update console definitions"

report_main_step "Changes committed. Creating pull request."

git push origin "$BRANCH_NAME"

# Create PR
gh pr create --title "$PR_TITLE" --body "$PR_BODY" --base main --head "${BRANCH_NAME}" --label 'release_note:skip' --label 'Feature:Console' --label 'Team:Kibana Management'
}

main
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
*/

import { firstValueFrom } from 'rxjs';
import { apm } from '@elastic/apm-rum';
import { Transaction, apm } from '@elastic/apm-rum';
import { type Client, OpenFeature, type Provider } from '@openfeature/web-sdk';
import { coreContextMock } from '@kbn/core-base-browser-mocks';
import type { FeatureFlagsStart } from '@kbn/core-feature-flags-browser';
import type { FeatureFlagsSetup, FeatureFlagsStart } from '@kbn/core-feature-flags-browser';
import { injectedMetadataServiceMock } from '@kbn/core-injected-metadata-browser-mocks';
import type { InternalInjectedMetadataSetup } from '@kbn/core-injected-metadata-browser-internal';
import { FeatureFlagsService } from '..';
Expand Down Expand Up @@ -63,7 +63,7 @@ describe('FeatureFlagsService Browser', () => {
test('awaits initialization in the start context', async () => {
const { setProvider } = featureFlagsService.setup({ injectedMetadata });
let externalResolve: Function = () => void 0;
const spy = jest.spyOn(OpenFeature, 'setProviderAndWait').mockImplementation(async () => {
const spy = jest.spyOn(OpenFeature, 'setProviderAndWait').mockImplementationOnce(async () => {
await new Promise((resolve) => {
externalResolve = resolve;
});
Expand All @@ -80,7 +80,7 @@ describe('FeatureFlagsService Browser', () => {

test('do not hold for too long during initialization', async () => {
const { setProvider } = featureFlagsService.setup({ injectedMetadata });
const spy = jest.spyOn(OpenFeature, 'setProviderAndWait').mockImplementation(async () => {
const spy = jest.spyOn(OpenFeature, 'setProviderAndWait').mockImplementationOnce(async () => {
await new Promise(() => {}); // never resolves
});
const apmCaptureErrorSpy = jest.spyOn(apm, 'captureError');
Expand All @@ -95,6 +95,60 @@ describe('FeatureFlagsService Browser', () => {
expect.stringContaining('The feature flags provider took too long to initialize.')
);
});

describe('APM instrumentation', () => {
const fakeProvider = { metadata: { name: 'fake provider' } } as Provider;

let setProvider: FeatureFlagsSetup['setProvider'];
let apmSpy: jest.SpyInstance<Transaction | undefined>;
let setProviderSpy: jest.SpyInstance<Promise<void>>;

beforeEach(() => {
const setup = featureFlagsService.setup({ injectedMetadata });
setProvider = setup.setProvider;
setProviderSpy = jest.spyOn(OpenFeature, 'setProviderAndWait');
apmSpy = jest.spyOn(apm, 'startTransaction');
});

test('starts an APM transaction to track the time it takes to set a provider', () => {
expect.assertions(1);
setProvider(fakeProvider);
expect(apmSpy).toHaveBeenCalledWith('set-provider', 'feature-flags');
});

test('APM transaction tracks success', async () => {
expect.assertions(4);

setProviderSpy.mockResolvedValueOnce();
setProvider(fakeProvider);

const transaction = apmSpy.mock.results[0].value;
const endTransactionSpy = jest.spyOn(transaction, 'end');
expect(transaction.outcome).toBeUndefined();
expect(endTransactionSpy).toHaveBeenCalledTimes(0);
await setProviderSpy.mock.results[0].value.catch(() => {});
expect(transaction.outcome).toBe('success');
expect(endTransactionSpy).toHaveBeenCalledTimes(1);
});

test('APM transaction tracks failures', async () => {
expect.assertions(5);

const apmCaptureErrorSpy = jest.spyOn(apm, 'captureError');
const error = new Error('Something went terribly wrong');
setProviderSpy.mockRejectedValueOnce(error);
setProvider(fakeProvider);

const transaction = apmSpy.mock.results[0].value;
const endTransactionSpy = jest.spyOn(transaction, 'end');
expect(transaction.outcome).toBeUndefined();
expect(endTransactionSpy).toHaveBeenCalledTimes(0);
await setProviderSpy.mock.results[0].value.catch(() => {});
expect(apmCaptureErrorSpy).toHaveBeenCalledWith(error);
expect(transaction.outcome).toBe('failure');
expect(endTransactionSpy).toHaveBeenCalledTimes(1);
});
});
});

describe('context handling', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,21 @@ export class FeatureFlagsService {
const transaction = apm.startTransaction('set-provider', 'feature-flags');
this.isProviderReadyPromise = OpenFeature.setProviderAndWait(provider);
this.isProviderReadyPromise
.then(() => transaction?.end())
.then(() => {
if (transaction) {
// @ts-expect-error RUM types are not correct
transaction.outcome = 'success';
transaction.end();
}
})
.catch((err) => {
this.logger.error(err);
apm.captureError(err);
transaction?.end();
if (transaction) {
// @ts-expect-error RUM types are not correct
transaction.outcome = 'failure';
transaction.end();
}
});
},
appendContext: (contextToAppend) => this.appendContext(contextToAppend),
Expand Down
2 changes: 1 addition & 1 deletion packages/shared-ux/modal/tabbed/src/context/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import React, { type ComponentProps, type ComponentType } from 'react';
import { renderHook, act } from '@testing-library/react-hooks';
import { renderHook, act } from '@testing-library/react';
import { useModalContext, ModalContextProvider } from '.';

type ModalContextProviderProps = ComponentProps<typeof ModalContextProvider>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import { CriteriaWithPagination } from '@elastic/eui';
import { renderHook, act } from '@testing-library/react-hooks';
import { renderHook, act } from '@testing-library/react';
import { useEuiTablePersist } from './use_table_persist';
import { createStorage } from './storage'; // Mock this if it's external

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import React, { FC, PropsWithChildren } from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { renderHook, waitFor } from '@testing-library/react';
import { ContentClientProvider } from './content_client_context';
import { ContentClient } from './content_client';
import { createCrudClientMock } from '../crud_client/crud_client.mock';
Expand Down Expand Up @@ -46,12 +46,10 @@ describe('useCreateContentMutation', () => {
const input: CreateIn = { contentTypeId: 'testType', data: { foo: 'bar' }, version: 2 };
const output = { test: 'test' };
crudClient.create.mockResolvedValueOnce(output);
const { result, waitFor } = renderHook(() => useCreateContentMutation(), { wrapper: Wrapper });
const { result } = renderHook(() => useCreateContentMutation(), { wrapper: Wrapper });
result.current.mutate(input);

await waitFor(() => result.current.isSuccess);

expect(result.current.data).toEqual(output);
await waitFor(() => expect(result.current.data).toEqual(output));
});
});

Expand All @@ -66,12 +64,10 @@ describe('useUpdateContentMutation', () => {
};
const output = { test: 'test' };
crudClient.update.mockResolvedValueOnce(output);
const { result, waitFor } = renderHook(() => useUpdateContentMutation(), { wrapper: Wrapper });
const { result } = renderHook(() => useUpdateContentMutation(), { wrapper: Wrapper });
result.current.mutate(input);

await waitFor(() => result.current.isSuccess);

expect(result.current.data).toEqual(output);
await waitFor(() => expect(result.current.data).toEqual(output));
});
});

Expand All @@ -81,11 +77,9 @@ describe('useDeleteContentMutation', () => {
const input: DeleteIn = { contentTypeId: 'testType', id: 'test', version: 2 };
const output = { test: 'test' };
crudClient.delete.mockResolvedValueOnce(output);
const { result, waitFor } = renderHook(() => useDeleteContentMutation(), { wrapper: Wrapper });
const { result } = renderHook(() => useDeleteContentMutation(), { wrapper: Wrapper });
result.current.mutate(input);

await waitFor(() => result.current.isSuccess);

expect(result.current.data).toEqual(output);
await waitFor(() => expect(result.current.data).toEqual(output));
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import React, { FC, PropsWithChildren } from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { renderHook, waitFor } from '@testing-library/react';
import { ContentClientProvider } from './content_client_context';
import { ContentClient } from './content_client';
import { createCrudClientMock } from '../crud_client/crud_client.mock';
Expand Down Expand Up @@ -42,9 +42,8 @@ describe('useGetContentQuery', () => {
const input: GetIn = { id: 'test', contentTypeId: 'testType', version: 2 };
const output = { test: 'test' };
crudClient.get.mockResolvedValueOnce(output);
const { result, waitFor } = renderHook(() => useGetContentQuery(input), { wrapper: Wrapper });
await waitFor(() => result.current.isSuccess);
expect(result.current.data).toEqual(output);
const { result } = renderHook(() => useGetContentQuery(input), { wrapper: Wrapper });
await waitFor(() => expect(result.current.data).toEqual(output));
});
});

Expand All @@ -54,10 +53,9 @@ describe('useSearchContentQuery', () => {
const input: SearchIn = { contentTypeId: 'testType', query: {}, version: 2 };
const output = { hits: [{ id: 'test' }] };
crudClient.search.mockResolvedValueOnce(output);
const { result, waitFor } = renderHook(() => useSearchContentQuery(input), {
const { result } = renderHook(() => useSearchContentQuery(input), {
wrapper: Wrapper,
});
await waitFor(() => result.current.isSuccess);
expect(result.current.data).toEqual(output);
await waitFor(() => expect(result.current.data).toEqual(output));
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { createAppMockRenderer } from '../../common/mock';

const showMoreClickMock = jest.fn();

describe('ShowMoreButton', () => {
// FLAKY: https://github.com/elastic/kibana/issues/192672
describe.skip('ShowMoreButton', () => {
let appMockRender: AppMockRenderer;

beforeEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import { setMockValues, setMockActions } from '../../../../../__mocks__/kea_logi

import React from 'react';

import { shallow, mount } from 'enzyme';
import { shallow } from 'enzyme';

import { EuiModal, EuiFieldText, EuiCodeBlock } from '@elastic/eui';
import { mountWithIntl } from '@kbn/test-jest-helpers';

const mockActions = { makeRequest: jest.fn(), setKeyName: jest.fn() };

Expand Down Expand Up @@ -47,7 +48,9 @@ describe('GenerateAnalyticsApiKeyModal', () => {
});

it('pre-set the key name with collection name', () => {
mount(<GenerateAnalyticsApiKeyModal collectionName="puggles" onClose={onCloseMock} />);
mountWithIntl(
<GenerateAnalyticsApiKeyModal collectionName="puggles" onClose={onCloseMock} />
);
expect(mockActions.setKeyName).toHaveBeenCalledWith('puggles API key');
});

Expand Down
Loading

0 comments on commit e1d4dd8

Please sign in to comment.