Skip to content

Commit

Permalink
Merge branch 'main' into scout/add-unit-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dmlemeshko authored Dec 17, 2024
2 parents 73a73e0 + 0b74f62 commit 91f53ff
Show file tree
Hide file tree
Showing 175 changed files with 4,137 additions and 2,609 deletions.
20 changes: 20 additions & 0 deletions .buildkite/pipelines/pull_request/renovate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
steps:
- command: .buildkite/scripts/lifecycle/pre_build.sh
label: Pre-Build
timeout_in_minutes: 10
agents:
machineType: n2-standard-2

- wait

- command: .buildkite/scripts/steps/renovate.sh
label: 'Renovate validation'
agents:
machineType: n2-highcpu-8
preemptible: true
key: renovate_validation
timeout_in_minutes: 60
retry:
automatic:
- exit_status: '-1'
limit: 3
8 changes: 8 additions & 0 deletions .buildkite/scripts/pipelines/pull_request/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ const getPipeline = (filename: string, removeSteps = true) => {
return;
}

const onlyRunQuickChecks = await areChangesSkippable([/^renovate\.json$/], REQUIRED_PATHS);
if (onlyRunQuickChecks) {
pipeline.push(getPipeline('.buildkite/pipelines/pull_request/renovate.yml', false));
pipeline.push(getPipeline('.buildkite/pipelines/pull_request/post_build.yml'));
console.log('Isolated changes to renovate.json. Skipping main PR pipeline.');
return;
}

pipeline.push(getAgentImageConfig({ returnYaml: true }));
pipeline.push(getPipeline('.buildkite/pipelines/pull_request/base.yml', false));

Expand Down
6 changes: 6 additions & 0 deletions .buildkite/scripts/steps/renovate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env bash

set -euo pipefail

echo '--- Renovate: validation'
.buildkite/scripts/steps/checks/renovate.sh
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -1832,7 +1832,7 @@ packages/kbn-monaco/src/esql @elastic/kibana-esql
#CC# /x-pack/plugins/global_search_providers/ @elastic/kibana-core

# AppEx AI Infra
/x-pack/plugins/inference @elastic/appex-ai-infra @elastic/obs-ai-assistant @elastic/security-generative-ai
/x-pack/platform/plugins/shared/inference @elastic/appex-ai-infra @elastic/obs-ai-assistant @elastic/security-generative-ai
/x-pack/test/functional_gen_ai/inference @elastic/appex-ai-infra

# AppEx Platform Services Security
Expand Down
2 changes: 2 additions & 0 deletions packages/kbn-relocate/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ export const EXTENSIONS = [
'mdz',
'asciidoc',
'sh',
'snap',
'ts',
'jsonc',
'xml',
'yaml',
'yml',
];
Expand Down
4 changes: 3 additions & 1 deletion packages/kbn-relocate/relocate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ export const findAndRelocateModules = async (params: RelocateModulesParams, log:
log.info(`Access the PR at: https://github.com/elastic/kibana/pull/${prNumber}`);
} else {
log.info('TIP: Run the following command to quickly create a PR:');
log.info(`$ gh pr create -d -t "<title>" -F ${DESCRIPTION} -R elastic/kibana`);
log.info(
`$ gh pr create -d -B "${baseBranch}" -t "<title>" -F ${DESCRIPTION} -R elastic/kibana`
);
}
};
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -770,10 +770,9 @@ export const runActionTestSuite = ({
});
});

// Reindex doesn't return any errors on it's own, so we have to test
// Reindex doesn't return any errors on its own, so we have to test
// together with waitForReindexTask
// Failing: See https://github.com/elastic/kibana/issues/166190
describe.skip('reindex & waitForReindexTask', () => {
describe('reindex & waitForReindexTask', () => {
it('resolves right when reindex succeeds without reindex script', async () => {
const res = (await reindex({
client,
Expand Down Expand Up @@ -1444,8 +1443,7 @@ export const runActionTestSuite = ({
});
});

// FLAKY: https://github.com/elastic/kibana/issues/166199
describe.skip('waitForPickupUpdatedMappingsTask', () => {
describe('waitForPickupUpdatedMappingsTask', () => {
it('rejects if there are failures', async () => {
const res = (await pickupUpdatedMappings(
client,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@ async function updateRoutingAllocations(
});
}

// Failing ES promotion: https://github.com/elastic/kibana/issues/158318
describe.skip('incompatible_cluster_routing_allocation', () => {
describe('incompatible_cluster_routing_allocation', () => {
let client: ElasticsearchClient;
let root: Root;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ function createRoot({ logFileName, hosts }: RootConfig) {
});
}

// Failing ES promotion: https://github.com/elastic/kibana/issues/167676
describe.skip('migration v2', () => {
describe('migration v2', () => {
let esServer: TestElasticsearchUtils;
let root: Root;
const migratedIndexAlias = `.kibana_${pkg.version}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ import { getFips } from 'crypto';

const logFilePath = join(__dirname, 'read_batch_size.log');

// Failing ES promotion: https://github.com/elastic/kibana/issues/163254
// Failing ES promotion: https://github.com/elastic/kibana/issues/163255
describe.skip('migration v2 - read batch size', () => {
describe('migration v2 - read batch size', () => {
let esServer: TestElasticsearchUtils;
let root: Root;
let logs: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
'data_visualizer.resultLinks.fileBeat.enabled (boolean)',
'dev_tools.deeplinks.navLinkStatus (string?)',
'discover.experimental.enabledProfiles (array?)',
'enterpriseSearch.canDeployEntSearch (boolean?)',
'enterpriseSearch.host (string?)',
'enterpriseSearch.ui.enabled (boolean?)',
'home.disableWelcomeScreen (boolean?)',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,14 @@ export {
type InferenceTaskErrorEvent,
type InferenceTaskInternalError,
type InferenceTaskRequestError,
type InferenceTaskAbortedError,
createInferenceInternalError,
createInferenceRequestError,
createInferenceRequestAbortedError,
isInferenceError,
isInferenceInternalError,
isInferenceRequestError,
isInferenceRequestAbortedError,
} from './src/errors';

export { truncateList } from './src/truncate_list';
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ export type ChatCompleteOptions<
* Function calling mode, defaults to "native".
*/
functionCalling?: FunctionCallingMode;
/**
* Optional signal that can be used to forcefully abort the request.
*/
abortSignal?: AbortSignal;
} & TToolOptions;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { InferenceTaskEventBase, InferenceTaskEventType } from './inference_task
export enum InferenceTaskErrorCode {
internalError = 'internalError',
requestError = 'requestError',
abortedError = 'requestAborted',
}

/**
Expand Down Expand Up @@ -46,16 +47,37 @@ export type InferenceTaskErrorEvent = InferenceTaskEventBase<InferenceTaskEventT
};
};

/**
* Inference error thrown when an unexpected internal error occurs while handling the request.
*/
export type InferenceTaskInternalError = InferenceTaskError<
InferenceTaskErrorCode.internalError,
Record<string, any>
>;

/**
* Inference error thrown when the request was considered invalid.
*
* Some example of reasons for invalid requests would be:
* - no connector matching the provided connectorId
* - invalid connector type for the provided connectorId
*/
export type InferenceTaskRequestError = InferenceTaskError<
InferenceTaskErrorCode.requestError,
{ status: number }
>;

/**
* Inference error thrown when the request was aborted.
*
* Request abortion occurs when providing an abort signal and firing it
* before the call to the LLM completes.
*/
export type InferenceTaskAbortedError = InferenceTaskError<
InferenceTaskErrorCode.abortedError,
{ status: number }
>;

export function createInferenceInternalError(
message = 'An internal error occurred',
meta?: Record<string, any>
Expand All @@ -72,16 +94,38 @@ export function createInferenceRequestError(
});
}

export function createInferenceRequestAbortedError(): InferenceTaskAbortedError {
return new InferenceTaskError(InferenceTaskErrorCode.abortedError, 'Request was aborted', {
status: 499,
});
}

/**
* Check if the given error is an {@link InferenceTaskError}
*/
export function isInferenceError(
error: unknown
): error is InferenceTaskError<string, Record<string, any> | undefined> {
return error instanceof InferenceTaskError;
}

/**
* Check if the given error is an {@link InferenceTaskInternalError}
*/
export function isInferenceInternalError(error: unknown): error is InferenceTaskInternalError {
return isInferenceError(error) && error.code === InferenceTaskErrorCode.internalError;
}

/**
* Check if the given error is an {@link InferenceTaskRequestError}
*/
export function isInferenceRequestError(error: unknown): error is InferenceTaskRequestError {
return isInferenceError(error) && error.code === InferenceTaskErrorCode.requestError;
}

/**
* Check if the given error is an {@link InferenceTaskAbortedError}
*/
export function isInferenceRequestAbortedError(error: unknown): error is InferenceTaskAbortedError {
return isInferenceError(error) && error.code === InferenceTaskErrorCode.abortedError;
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ export interface OutputOptions<
* Defaults to false.
*/
stream?: TStream;

/**
* Optional signal that can be used to forcefully abort the request.
*/
abortSignal?: AbortSignal;
/**
* Optional configuration for retrying the call if an error occurs.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import type { TransformSelectorControlProps } from './transform_selector_control';
import { TransformSelectorControl } from './transform_selector_control';

describe('TransformSelectorControl', () => {
const defaultProps: TransformSelectorControlProps = {
label: 'Select Transforms',
errors: [],
onChange: jest.fn(),
selectedOptions: [],
options: ['transform1', 'transform2'],
allowSelectAll: true,
};

it('renders without crashing', () => {
const { getByLabelText } = render(<TransformSelectorControl {...defaultProps} />);
expect(getByLabelText('Select Transforms')).toBeInTheDocument();
});

it('displays options correctly', () => {
const { getByText } = render(<TransformSelectorControl {...defaultProps} />);
fireEvent.click(getByText('Select Transforms'));
expect(getByText('transform1')).toBeInTheDocument();
expect(getByText('transform2')).toBeInTheDocument();
expect(getByText('*')).toBeInTheDocument();
});

it('calls onChange with selected options', () => {
const { getByText } = render(<TransformSelectorControl {...defaultProps} />);
fireEvent.click(getByText('Select Transforms'));
fireEvent.click(getByText('transform1'));
expect(defaultProps.onChange).toHaveBeenCalledWith(['transform1']);
});

it('only allows wildcards as custom options', () => {
const { getByText, getByTestId } = render(<TransformSelectorControl {...defaultProps} />);
fireEvent.click(getByText('Select Transforms'));
const input = getByTestId('comboBoxSearchInput');

fireEvent.change(input, { target: { value: 'custom' } });
fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
expect(defaultProps.onChange).not.toHaveBeenCalledWith(['custom']);

fireEvent.change(input, { target: { value: 'custom*' } });
fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
expect(defaultProps.onChange).toHaveBeenCalledWith(['custom*']);
});

it('displays errors correctly', () => {
const errorProps = { ...defaultProps, errors: ['Error message'] };
const { getByText } = render(<TransformSelectorControl {...errorProps} />);
expect(getByText('Error message')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
* 2.0.
*/

import type { EuiComboBoxProps } from '@elastic/eui';
import type { EuiComboBoxOptionsListProps, EuiComboBoxProps } from '@elastic/eui';
import { EuiComboBox, EuiFormRow } from '@elastic/eui';
import type { FC } from 'react';
import React, { useMemo } from 'react';
import React, { useMemo, useState } from 'react';
import { isDefined } from '@kbn/ml-is-defined';
import { i18n } from '@kbn/i18n';
import { ALL_TRANSFORMS_SELECTION } from '../../../common/constants';

export interface TransformSelectorControlProps {
Expand All @@ -33,6 +34,8 @@ export const TransformSelectorControl: FC<TransformSelectorControlProps> = ({
options,
allowSelectAll = false,
}) => {
const [allowCustomOptions, setAllowCustomOptions] = useState(false);

const onSelectionChange: EuiComboBoxProps<string>['onChange'] = ((selectionUpdate) => {
if (!selectionUpdate?.length) {
onChange([]);
Expand All @@ -50,6 +53,12 @@ export const TransformSelectorControl: FC<TransformSelectorControlProps> = ({
);
}) as Exclude<EuiComboBoxProps<string>['onChange'], undefined>;

const onCreateOption = allowCustomOptions
? (((searchValue) => {
onChange([...selectedOptions, searchValue]);
}) as EuiComboBoxOptionsListProps<string>['onCreateOption'])
: undefined;

const selectedOptionsEui = useMemo(() => convertToEuiOptions(selectedOptions), [selectedOptions]);
const optionsEui = useMemo(() => {
return convertToEuiOptions(allowSelectAll ? [ALL_TRANSFORMS_SELECTION, ...options] : options);
Expand All @@ -58,6 +67,17 @@ export const TransformSelectorControl: FC<TransformSelectorControlProps> = ({
return (
<EuiFormRow fullWidth label={label} isInvalid={!!errors?.length} error={errors}>
<EuiComboBox<string>
onSearchChange={(searchValue, hasMatchingOption) => {
setAllowCustomOptions(!hasMatchingOption && searchValue.includes('*'));
}}
onCreateOption={onCreateOption}
customOptionText={i18n.translate(
'xpack.transform.alertTypes.transformHealth.customOptionText',
{
defaultMessage: 'Include {searchValuePlaceholder} wildcard',
values: { searchValuePlaceholder: '{searchValue}' },
}
)}
singleSelection={false}
selectedOptions={selectedOptionsEui}
options={optionsEui}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ interface Props {
}

export const ExpandedRowJsonPane: FC<Props> = ({ json }) => {
// exclude alerting rules from the JSON
if ('alerting_rules' in json) {
const { alerting_rules: alertingRules, ...rest } = json;
json = rest;
}

return (
<div data-test-subj="transformJsonTabContent">
<EuiFlexGroup>
Expand Down
Loading

0 comments on commit 91f53ff

Please sign in to comment.