From 28526182a58b7ab1ef230f01de8d21ca93ac839d Mon Sep 17 00:00:00 2001 From: Dominik Broj Date: Fri, 27 Sep 2024 08:19:46 +0200 Subject: [PATCH 1/5] docs: update notifications wording (#5030) # What this PR does update notifications wording ## Which issue(s) this PR closes Related to https://github.com/grafana/oncall/issues/3104 ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --- docs/sources/manage/notify/_index.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/sources/manage/notify/_index.md b/docs/sources/manage/notify/_index.md index e6af64a30a..f796f2823a 100644 --- a/docs/sources/manage/notify/_index.md +++ b/docs/sources/manage/notify/_index.md @@ -34,21 +34,21 @@ To configure supported messaging apps, refer to the following topics: {{< section >}} -## Configure user notification policies +## Configure user notification rules -Notification policies are a configurable set of notification steps that determine how you're notified of alert in OnCall. Users with the Admin or Editor role are +Notification rules are a configurable set of notification steps that determine how you're notified of alert in OnCall. Users with the Admin or Editor role are able to receive notifications. Users can verify phone numbers and email addresses in the **Users** tab of Grafana OnCall. -- **Default Notifications** dictate how a user is notified for most escalation thresholds. +- **Default notification rules** dictate how a user is notified for most escalation thresholds. -- **Important Notifications** are labeled in escalation chains. If an escalation event is marked as an important notification, -it will bypass **Default Notification** settings and notify the user by the method specified. +- **Important notification rules** are labeled in escalation chains. If an escalation event is marked as an important notification, +it will bypass **Default notification rules** settings and notify the user by the method specified. > **NOTE**: You cannot add users or manage permissions in Grafana OnCall. User settings are found on the > organizational level of your Grafana instance in **Configuration > Users**. -To configure a users notification policy: +To configure a users notification rules: 1. Navigate to the **Users** tab of Grafana OnCall and search for or select a user. From 671a537dbce4537c94861341279f92bdc8272de6 Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Mon, 30 Sep 2024 17:22:04 +0100 Subject: [PATCH 2/5] Chore: Remove `topnav` references (#5092) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # What this PR does - removes references to `topnav` - `topnav` was default enabled in grafana v9.5 - we intend to remove the toggle soon™️ ## Which issue(s) this PR closes Related to [issue link here] ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --- dev/helm-local.yml | 2 +- grafana-plugin/jest.setup.ts | 4 +- grafana-plugin/src/PluginPage.tsx | 7 +- .../src/containers/Alerts/Alerts.tsx | 11 +-- .../DefaultPageLayout/DefaultPageLayout.tsx | 44 ++--------- .../MobileAppConnection.test.tsx | 4 - .../RotationForm/RotationForm.helpers.ts | 27 +++---- grafana-plugin/src/navbar/Header/Header.tsx | 3 +- .../src/navbar/LegacyNavHeading.tsx | 4 +- grafana-plugin/src/pages/pages.tsx | 9 +-- .../src/pages/settings/SettingsPage.tsx | 79 +++++++++---------- .../tabs/MainSettings/MainSettings.tsx | 10 --- .../plugin/GrafanaPluginRootPage.helpers.tsx | 5 -- .../src/plugin/GrafanaPluginRootPage.tsx | 14 +--- 14 files changed, 64 insertions(+), 159 deletions(-) diff --git a/dev/helm-local.yml b/dev/helm-local.yml index b5fd80492d..33a28790c6 100644 --- a/dev/helm-local.yml +++ b/dev/helm-local.yml @@ -70,7 +70,7 @@ grafana: - name: DATABASE_PASSWORD value: oncallpassword env: - GF_FEATURE_TOGGLES_ENABLE: topnav,externalServiceAccounts + GF_FEATURE_TOGGLES_ENABLE: externalServiceAccounts GF_SECURITY_ADMIN_PASSWORD: oncall GF_SECURITY_ADMIN_USER: oncall GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: grafana-oncall-app diff --git a/grafana-plugin/jest.setup.ts b/grafana-plugin/jest.setup.ts index 0ef64969ed..da0cee32ae 100644 --- a/grafana-plugin/jest.setup.ts +++ b/grafana-plugin/jest.setup.ts @@ -11,9 +11,7 @@ import { TextEncoder, TextDecoder } from 'util'; jest.mock('@grafana/runtime', () => ({ __esModule: true, config: { - featureToggles: { - topNav: false, - }, + featureToggles: {}, bootData: { user: { timezone: 'UTC', diff --git a/grafana-plugin/src/PluginPage.tsx b/grafana-plugin/src/PluginPage.tsx index 70020c93f7..eff870c796 100644 --- a/grafana-plugin/src/PluginPage.tsx +++ b/grafana-plugin/src/PluginPage.tsx @@ -6,13 +6,12 @@ import { Header } from 'navbar/Header/Header'; import { RenderConditionally } from 'components/RenderConditionally/RenderConditionally'; import { pages } from 'pages/pages'; -import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers'; interface AppPluginPageProps extends PluginPageProps { page?: string; } -export const PluginPage = (isTopNavbar() ? RealPlugin : PluginPageFallback) as React.ComponentType; +export const PluginPage = RealPlugin as React.ComponentType; function RealPlugin(props: AppPluginPageProps): React.ReactNode { const { page } = props; @@ -33,7 +32,3 @@ function RealPlugin(props: AppPluginPageProps): React.ReactNode { ); } - -export function PluginPageFallback(props: PluginPageProps): React.ReactNode { - return props.children; -} diff --git a/grafana-plugin/src/containers/Alerts/Alerts.tsx b/grafana-plugin/src/containers/Alerts/Alerts.tsx index d08b1df348..e22bf04a60 100644 --- a/grafana-plugin/src/containers/Alerts/Alerts.tsx +++ b/grafana-plugin/src/containers/Alerts/Alerts.tsx @@ -15,7 +15,6 @@ import { getSlackMessage } from 'containers/DefaultPageLayout/DefaultPageLayout. import { SlackError } from 'containers/DefaultPageLayout/DefaultPageLayout.types'; import { getIfChatOpsConnected } from 'containers/DefaultPageLayout/helper'; import { UserHelper } from 'models/user/user.helpers'; -import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers'; import { AppFeature } from 'state/features'; import { useStore } from 'state/useStore'; @@ -72,7 +71,7 @@ export const Alerts = observer(() => { return null; } return ( -
+
{showSlackInstallAlert && ( { instructionsLink: css` color: ${theme.colors.primary.text}; `, - - alertsContainerLegacy: css` - paddingtop: '10px'; - - @media (max-width: 768px) { - padding-top: 50px; - } - `, }; }; diff --git a/grafana-plugin/src/containers/DefaultPageLayout/DefaultPageLayout.tsx b/grafana-plugin/src/containers/DefaultPageLayout/DefaultPageLayout.tsx index aa1b1f7a70..98c9146926 100644 --- a/grafana-plugin/src/containers/DefaultPageLayout/DefaultPageLayout.tsx +++ b/grafana-plugin/src/containers/DefaultPageLayout/DefaultPageLayout.tsx @@ -1,13 +1,11 @@ -import React, { FC, ReactElement } from 'react'; +import React, { FC } from 'react'; -import { css, cx } from '@emotion/css'; +import { css } from '@emotion/css'; import { AppRootProps, NavModelItem } from '@grafana/data'; import { useStyles2 } from '@grafana/ui'; import { PluginPage } from 'PluginPage'; import { observer } from 'mobx-react'; -import { Alerts } from 'containers/Alerts/Alerts'; -import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers'; interface DefaultPageLayoutProps extends AppRootProps { children?: any; @@ -19,39 +17,11 @@ export const DefaultPageLayout: FC = observer((props) => const { children, page, pageNav } = props; const styles = useStyles2(getStyles); - if (isTopNavbar()) { - return renderTopNavbar(); - } - - return renderLegacyNavbar(); - - function renderTopNavbar(): ReactElement { - return ( - -
{children}
-
- ); - } - - function renderLegacyNavbar(): ReactElement { - return ( - -
-
- - {children} -
-
-
- ); - } + return ( + +
{children}
+
+ ); }); const getStyles = () => { diff --git a/grafana-plugin/src/containers/MobileAppConnection/MobileAppConnection.test.tsx b/grafana-plugin/src/containers/MobileAppConnection/MobileAppConnection.test.tsx index 124fde2a7e..d6136ce535 100644 --- a/grafana-plugin/src/containers/MobileAppConnection/MobileAppConnection.test.tsx +++ b/grafana-plugin/src/containers/MobileAppConnection/MobileAppConnection.test.tsx @@ -9,10 +9,6 @@ import { rootStore } from 'state/rootStore'; import { MobileAppConnection } from './MobileAppConnection'; -jest.mock('plugin/GrafanaPluginRootPage.helpers', () => ({ - isTopNavbar: () => false, -})); - jest.mock('helpers/authorization/authorization', () => ({ ...jest.requireActual('helpers/authorization/authorization'), isUserActionAllowed: jest.fn().mockReturnValue(true), diff --git a/grafana-plugin/src/containers/RotationForm/RotationForm.helpers.ts b/grafana-plugin/src/containers/RotationForm/RotationForm.helpers.ts index 7043f614bd..68066574bd 100644 --- a/grafana-plugin/src/containers/RotationForm/RotationForm.helpers.ts +++ b/grafana-plugin/src/containers/RotationForm/RotationForm.helpers.ts @@ -1,9 +1,7 @@ import { Dayjs, ManipulateType } from 'dayjs'; -import { GRAFANA_HEADER_HEIGHT, GRAFANA_LEGACY_SIDEBAR_WIDTH } from 'helpers/consts'; +import { GRAFANA_HEADER_HEIGHT } from 'helpers/consts'; import { DraggableData } from 'react-draggable'; -import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers'; - import { RepeatEveryPeriod } from './RotationForm.types'; export const getRepeatShiftsEveryOptions = (repeatEveryPeriod: number) => { @@ -195,20 +193,13 @@ export function getDraggableModalCoordinatesOnInit( const baseReferenceElRect = body.getBoundingClientRect(); const { innerHeight } = window; - const { right, bottom } = baseReferenceElRect; + const { right } = baseReferenceElRect; - return isTopNavbar() - ? { - // values are adjusted by any padding/margin differences - left: -data.node.offsetLeft + 12, - right: right - (data.node.offsetLeft + data.node.offsetWidth) - 12, - top: -offsetTop + GRAFANA_HEADER_HEIGHT + 12, - bottom: innerHeight - data.node.offsetHeight - offsetTop - 12, - } - : { - left: -data.node.offsetLeft + 12 + GRAFANA_LEGACY_SIDEBAR_WIDTH, - right: right - (data.node.offsetLeft + data.node.offsetWidth) - 12, - top: -offsetTop + 12, - bottom: bottom - data.node.offsetHeight - offsetTop - 12, - }; + return { + // values are adjusted by any padding/margin differences + left: -data.node.offsetLeft + 12, + right: right - (data.node.offsetLeft + data.node.offsetWidth) - 12, + top: -offsetTop + GRAFANA_HEADER_HEIGHT + 12, + bottom: innerHeight - data.node.offsetHeight - offsetTop - 12, + }; } diff --git a/grafana-plugin/src/navbar/Header/Header.tsx b/grafana-plugin/src/navbar/Header/Header.tsx index c5485d9d04..e1c99af03a 100644 --- a/grafana-plugin/src/navbar/Header/Header.tsx +++ b/grafana-plugin/src/navbar/Header/Header.tsx @@ -8,7 +8,6 @@ import { observer } from 'mobx-react'; import gitHubStarSVG from 'assets/img/github_star.svg'; import logo from 'assets/img/logo.svg'; import { Alerts } from 'containers/Alerts/Alerts'; -import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers'; import { getHeaderStyles } from './Header.styles'; @@ -18,7 +17,7 @@ export const Header = observer(() => { return ( <>
-
+
Grafana OnCall diff --git a/grafana-plugin/src/navbar/LegacyNavHeading.tsx b/grafana-plugin/src/navbar/LegacyNavHeading.tsx index 184e453a78..b125bc99a8 100644 --- a/grafana-plugin/src/navbar/LegacyNavHeading.tsx +++ b/grafana-plugin/src/navbar/LegacyNavHeading.tsx @@ -1,11 +1,9 @@ -import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers'; - interface LegacyNavHeadingProps { children: JSX.Element; show?: boolean; } export const LegacyNavHeading = function (props: LegacyNavHeadingProps): JSX.Element { - const { show = !isTopNavbar(), children } = props; + const { show = false, children } = props; return show ? children : null; }; diff --git a/grafana-plugin/src/pages/pages.tsx b/grafana-plugin/src/pages/pages.tsx index 8379ba9b5d..eea14bdf29 100644 --- a/grafana-plugin/src/pages/pages.tsx +++ b/grafana-plugin/src/pages/pages.tsx @@ -3,7 +3,6 @@ import { UserActions, UserAction, isUserActionAllowed } from 'helpers/authorizat import { PLUGIN_ROOT } from 'helpers/consts'; import { matchPath } from 'react-router-dom-v5-compat'; -import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers'; import { AppFeature } from 'state/features'; import { RootBaseStore } from 'state/rootBaseStore/RootBaseStore'; @@ -109,7 +108,7 @@ export const pages: { [id: string]: PageDefinition } = [ text: 'ChatOps', path: getPath('chat-ops'), hideFromBreadcrumbs: true, - hideFromTabs: isTopNavbar(), + hideFromTabs: true, action: UserActions.ChatOpsRead, }, { @@ -126,7 +125,7 @@ export const pages: { [id: string]: PageDefinition } = [ text: 'Env Variables', hideFromTabsFn: (store: RootBaseStore) => { const hasLiveSettings = store.hasFeature(AppFeature.LiveSettings); - return isTopNavbar() || !hasLiveSettings; + return !hasLiveSettings; }, path: getPath('live-settings'), action: UserActions.OtherSettingsRead, @@ -137,7 +136,7 @@ export const pages: { [id: string]: PageDefinition } = [ text: 'Cloud', hideFromTabsFn: (store: RootBaseStore) => { const hasCloudFeature = store.hasFeature(AppFeature.CloudConnection); - return isTopNavbar() || !hasCloudFeature; + return !hasCloudFeature; }, path: getPath('cloud'), action: UserActions.OtherSettingsWrite, @@ -161,7 +160,7 @@ export const pages: { [id: string]: PageDefinition } = [ ...current, getPageNav: (pageTitle: string) => ({ - text: isTopNavbar() ? '' : current.text, + text: '', parentItem: current.getParentItem ? current.getParentItem(pageTitle) : undefined, hideFromBreadcrumbs: current.hideFromBreadcrumbs, hideFromTabs: current.hideFromTabs, diff --git a/grafana-plugin/src/pages/settings/SettingsPage.tsx b/grafana-plugin/src/pages/settings/SettingsPage.tsx index f9fed76812..3f52bb786c 100644 --- a/grafana-plugin/src/pages/settings/SettingsPage.tsx +++ b/grafana-plugin/src/pages/settings/SettingsPage.tsx @@ -9,7 +9,6 @@ import { observer } from 'mobx-react'; import { ChatOpsPage } from 'pages/settings/tabs/ChatOps/ChatOps'; import { MainSettings } from 'pages/settings/tabs/MainSettings/MainSettings'; -import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers'; import { AppFeature } from 'state/features'; import { WithStoreProps } from 'state/types'; import { withMobXProviderContext } from 'state/withStore'; @@ -54,52 +53,48 @@ class Settings extends React.Component { const showCloudPage = hasCloudPage && isUserActionAllowed(UserActions.OtherSettingsWrite); const showLiveSettings = hasLiveSettings && isUserActionAllowed(UserActions.OtherSettingsRead); - if (isTopNavbar()) { - return ( - <> - + return ( + <> + + onTabChange(SettingsPageTab.MainSettings.key)} + active={activeTab === SettingsPageTab.MainSettings.key} + label={SettingsPageTab.MainSettings.value} + /> + onTabChange(SettingsPageTab.ChatOps.key)} + active={activeTab === SettingsPageTab.ChatOps.key} + label={SettingsPageTab.ChatOps.value} + /> + onTabChange(SettingsPageTab.TeamsSettings.key)} + active={activeTab === SettingsPageTab.TeamsSettings.key} + label={SettingsPageTab.TeamsSettings.value} + /> + {showLiveSettings && ( onTabChange(SettingsPageTab.MainSettings.key)} - active={activeTab === SettingsPageTab.MainSettings.key} - label={SettingsPageTab.MainSettings.value} + key={SettingsPageTab.EnvVariables.key} + onChangeTab={() => onTabChange(SettingsPageTab.EnvVariables.key)} + active={activeTab === SettingsPageTab.EnvVariables.key} + label={SettingsPageTab.EnvVariables.value} /> + )} + {showCloudPage && ( onTabChange(SettingsPageTab.ChatOps.key)} - active={activeTab === SettingsPageTab.ChatOps.key} - label={SettingsPageTab.ChatOps.value} + key={SettingsPageTab.Cloud.key} + onChangeTab={() => onTabChange(SettingsPageTab.Cloud.key)} + active={activeTab === SettingsPageTab.Cloud.key} + label={SettingsPageTab.Cloud.value} /> - onTabChange(SettingsPageTab.TeamsSettings.key)} - active={activeTab === SettingsPageTab.TeamsSettings.key} - label={SettingsPageTab.TeamsSettings.value} - /> - {showLiveSettings && ( - onTabChange(SettingsPageTab.EnvVariables.key)} - active={activeTab === SettingsPageTab.EnvVariables.key} - label={SettingsPageTab.EnvVariables.value} - /> - )} - {showCloudPage && ( - onTabChange(SettingsPageTab.Cloud.key)} - active={activeTab === SettingsPageTab.Cloud.key} - label={SettingsPageTab.Cloud.value} - /> - )} - - - - - ); - } + )} + - return ; + + + ); } getMatchingPageNav() { diff --git a/grafana-plugin/src/pages/settings/tabs/MainSettings/MainSettings.tsx b/grafana-plugin/src/pages/settings/tabs/MainSettings/MainSettings.tsx index 278d3600fe..66793e631c 100644 --- a/grafana-plugin/src/pages/settings/tabs/MainSettings/MainSettings.tsx +++ b/grafana-plugin/src/pages/settings/tabs/MainSettings/MainSettings.tsx @@ -9,8 +9,6 @@ import { LegacyNavHeading } from 'navbar/LegacyNavHeading'; import { Text } from 'components/Text/Text'; import { ApiTokenSettings } from 'containers/ApiTokenSettings/ApiTokenSettings'; import { WithPermissionControlTooltip } from 'containers/WithPermissionControl/WithPermissionControlTooltip'; -import { TeamsSettings } from 'pages/settings/tabs/TeamsSettings/TeamsSettings'; -import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers'; import { useStore } from 'state/useStore'; export const MainSettings = observer(() => { @@ -50,14 +48,6 @@ export const MainSettings = observer(() => {
- {!isTopNavbar() && ( -
- - Teams and Access Settings - - -
- )} API URL diff --git a/grafana-plugin/src/plugin/GrafanaPluginRootPage.helpers.tsx b/grafana-plugin/src/plugin/GrafanaPluginRootPage.helpers.tsx index 63b461beb8..478523c31c 100644 --- a/grafana-plugin/src/plugin/GrafanaPluginRootPage.helpers.tsx +++ b/grafana-plugin/src/plugin/GrafanaPluginRootPage.helpers.tsx @@ -1,8 +1,3 @@ -import { config } from '@grafana/runtime'; - -export function isTopNavbar(): boolean { - return !!config.featureToggles.topnav; -} export function getQueryParams(): any { const searchParams = new URLSearchParams(window.location.search); diff --git a/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx b/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx index a0040f8321..921b8095cb 100644 --- a/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx +++ b/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx @@ -8,8 +8,6 @@ import { DEFAULT_PAGE, getOnCallApiUrl } from 'helpers/consts'; import { FaroHelper } from 'helpers/faro'; import { useOnMount } from 'helpers/hooks'; import { observer, Provider } from 'mobx-react'; -import { Header } from 'navbar/Header/Header'; -import { LegacyNavTabsBar } from 'navbar/LegacyNavTabsBar'; import { Navigate, Route, Routes, useLocation } from 'react-router-dom-v5-compat'; import { RenderConditionally } from 'components/RenderConditionally/RenderConditionally'; @@ -36,7 +34,7 @@ import { rootStore } from 'state/rootStore'; import { useStore } from 'state/useStore'; import 'assets/style/global.css'; -import { getQueryParams, isTopNavbar } from './GrafanaPluginRootPage.helpers'; +import { getQueryParams } from './GrafanaPluginRootPage.helpers'; import grafanaGlobalStyle from '!raw-loader!assets/style/grafanaGlobalStyles.css'; @@ -112,22 +110,12 @@ export const Root = observer((props: AppRootProps) => { return ( - {!isTopNavbar() && ( - <> -
- - - )}
Date: Tue, 1 Oct 2024 14:59:24 +0200 Subject: [PATCH 3/5] Back merge irm (#5098) # What this PR does ## Which issue(s) this PR closes Related to [issue link here] ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --- .markdownlintignore | 2 + grafana-plugin/CHANGELOG.md | 39 +++++ .../e2e-tests/utils/integrations.ts | 6 +- grafana-plugin/e2e-tests/utils/schedule.ts | 2 +- grafana-plugin/go.mod | 63 ++++---- grafana-plugin/go.sum | 145 +++++++++--------- grafana-plugin/package.json | 6 +- grafana-plugin/pnpm-lock.yaml | 40 ++--- .../ExtensionLinkMenu/ExtensionLinkMenu.tsx | 25 ++- .../IntegrationForm/IntegrationForm.tsx | 2 +- .../OutgoingWebhookForm.tsx | 11 +- grafana-plugin/src/helpers/consts.ts | 5 +- .../alert_receive_channel.ts | 1 - grafana-plugin/src/module.ts | 5 +- .../src/pages/incident/Incident.styles.ts | 2 + .../outgoing_webhooks/OutgoingWebhooks.tsx | 31 ++-- .../src/plugin/GrafanaPluginRootPage.tsx | 3 +- grafana-plugin/src/version.ts | 2 +- 18 files changed, 233 insertions(+), 157 deletions(-) create mode 100644 grafana-plugin/CHANGELOG.md diff --git a/.markdownlintignore b/.markdownlintignore index 0e47d8afb4..a38ec9e11f 100644 --- a/.markdownlintignore +++ b/.markdownlintignore @@ -6,3 +6,5 @@ venv .idea .DS_Store .env + +CHANGELOG.md diff --git a/grafana-plugin/CHANGELOG.md b/grafana-plugin/CHANGELOG.md new file mode 100644 index 0000000000..f66f1b73de --- /dev/null +++ b/grafana-plugin/CHANGELOG.md @@ -0,0 +1,39 @@ +# Changelog + +## [1.9.27](https://github.com/grafana/irm/compare/grafana-oncall-app-v1.9.26...grafana-oncall-app-v1.9.27) (2024-09-26) + + +### Bug Fixes + +* address RBAC Admin issue ([#183](https://github.com/grafana/irm/issues/183)) ([508857b](https://github.com/grafana/irm/commit/508857b719641ce405910bb1b110dec62f1a7af5)) +* Bring webhooks to IRM ([#144](https://github.com/grafana/irm/issues/144)) ([1a883e1](https://github.com/grafana/irm/commit/1a883e1e44fe154ec0a7d36fa8183444fb90c773)) +* run go mod tidy ([#174](https://github.com/grafana/irm/issues/174)) ([df2cf75](https://github.com/grafana/irm/commit/df2cf75ac5d4f57661af722f4785ef4996644bbc)) +* style links in incident message ([#143](https://github.com/grafana/irm/issues/143)) ([2e55b07](https://github.com/grafana/irm/commit/2e55b07c1069cebfb30ba944b1c0b6f7dbfb1bad)) + + +### Dependencies + +* bump `github.com/grafana/grafana-plugin-sdk-go` to `v0.250.2` to address CVE-2024-8986 ([#173](https://github.com/grafana/irm/issues/173)) ([2385dc3](https://github.com/grafana/irm/commit/2385dc39e0108ca8ee4047046a34a735d1598ec8)) +* bump micromatch version from 4.0.6 to 4.0.8 ([#181](https://github.com/grafana/irm/issues/181)) ([b1123fd](https://github.com/grafana/irm/commit/b1123fd8d54db080eb90c9959494a3bd00a89540)) + + +### Miscellaneous Chores + +* release main ([#157](https://github.com/grafana/irm/issues/157)) ([1b2901c](https://github.com/grafana/irm/commit/1b2901c952cc8e82f94becfa44db146fc0abe076)) +* release main ([#187](https://github.com/grafana/irm/issues/187)) ([3221340](https://github.com/grafana/irm/commit/3221340148ac972ed32cd16194a5eaf3cc29db3d)) +* release main ([#190](https://github.com/grafana/irm/issues/190)) ([e2489d0](https://github.com/grafana/irm/commit/e2489d0a31c4ac80dc72dca57c42eb3068fa4661)) + +## [1.9.26](https://github.com/grafana/irm/compare/grafana-oncall-app-v1.9.25...grafana-oncall-app-v1.9.26) (2024-09-23) + + +### Bug Fixes + +* fix template editor layout ([#142](https://github.com/grafana/irm/issues/142)) ([c8ac3b0](https://github.com/grafana/irm/commit/c8ac3b0f60cb5472fb93b59255ca30bc8ba64653)) +* make sure GMT elem is selected from the dropdown options is sele… ([#141](https://github.com/grafana/irm/issues/141)) ([cc86f17](https://github.com/grafana/irm/commit/cc86f1751f7378d981d6e60a20cef746f090f1df)) +* rename OnCall notification titles ([#126](https://github.com/grafana/irm/issues/126)) ([7df0120](https://github.com/grafana/irm/commit/7df01208271b29640939730375d035b5d5a13f98)) +* update how config page is rendered in cloud ([#137](https://github.com/grafana/irm/issues/137)) ([3cf9bc2](https://github.com/grafana/irm/commit/3cf9bc23bee92dd8dde77fe225efebaeaf38a233)) + + +### Miscellaneous Chores + +* improve (again) ui pod readiness probe ([#120](https://github.com/grafana/irm/issues/120)) ([c4ee02b](https://github.com/grafana/irm/commit/c4ee02b5253a7cfaf983518c6475f6207a66e253)) diff --git a/grafana-plugin/e2e-tests/utils/integrations.ts b/grafana-plugin/e2e-tests/utils/integrations.ts index 1a3e7a203c..d9b7a0cc7e 100644 --- a/grafana-plugin/e2e-tests/utils/integrations.ts +++ b/grafana-plugin/e2e-tests/utils/integrations.ts @@ -77,10 +77,12 @@ export const sendDemoAlert = async (page: Page): Promise => { export const createIntegrationAndSendDemoAlert = async ( page: Page, integrationName: string, - escalationChainName: string + escalationChainName?: string ): Promise => { await createIntegration({ page, integrationName }); - await assignEscalationChainToIntegration(page, escalationChainName); + if (escalationChainName) { + await assignEscalationChainToIntegration(page, escalationChainName); + } await sendDemoAlert(page); }; diff --git a/grafana-plugin/e2e-tests/utils/schedule.ts b/grafana-plugin/e2e-tests/utils/schedule.ts index c08172f199..3a7f51567a 100644 --- a/grafana-plugin/e2e-tests/utils/schedule.ts +++ b/grafana-plugin/e2e-tests/utils/schedule.ts @@ -15,7 +15,7 @@ export const createOnCallSchedule = async ( // create an oncall-rotation schedule await clickButton({ page, buttonText: 'New Schedule' }); - (await page.waitForSelector('button >> text=Create >> nth=0')).click(); + await page.getByRole('button', { name: 'Create' }).first().click(); // fill in the name input await page.getByTestId('schedule-form').locator('input[name="name"]').fill(scheduleName); diff --git a/grafana-plugin/go.mod b/grafana-plugin/go.mod index aecbb33233..662f5034b1 100644 --- a/grafana-plugin/go.mod +++ b/grafana-plugin/go.mod @@ -2,7 +2,7 @@ module github.com/grafana/grafana-oncall-app go 1.21.5 -require github.com/grafana/grafana-plugin-sdk-go v0.228.0 +require github.com/grafana/grafana-plugin-sdk-go v0.250.0 require ( github.com/BurntSushi/toml v1.3.2 // indirect @@ -16,7 +16,7 @@ require ( github.com/elazarl/goproxy v0.0.0-20230731152917-f99041a5c027 // indirect github.com/fatih/color v1.15.0 // indirect github.com/getkin/kin-openapi v0.124.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.20.2 // indirect github.com/go-openapi/swag v0.22.8 // indirect @@ -27,16 +27,18 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.1 // indirect + github.com/grafana/otel-profiling-go v0.5.1 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect - github.com/hashicorp/go-plugin v1.6.0 // indirect + github.com/hashicorp/go-plugin v1.6.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/invopop/yaml v0.2.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/magefile/mage v1.15.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -48,45 +50,44 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/run v1.1.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/pierrec/lz4/v4 v4.1.18 // indirect - github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_golang v1.20.3 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.53.0 // indirect - github.com/prometheus/procfs v0.14.0 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sergi/go-diff v1.3.1 // indirect github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8 // indirect github.com/unknwon/com v1.0.1 // indirect github.com/unknwon/log v0.0.0-20150304194804-e617c87089d3 // indirect github.com/urfave/cli v1.22.15 // indirect - github.com/yudai/gojsondiff v1.0.0 // indirect - github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.51.0 // indirect - go.opentelemetry.io/contrib/propagators/jaeger v1.26.0 // indirect - go.opentelemetry.io/contrib/samplers/jaegerremote v0.20.0 // indirect - go.opentelemetry.io/otel v1.26.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 // indirect - go.opentelemetry.io/otel/metric v1.26.0 // indirect - go.opentelemetry.io/otel/sdk v1.26.0 // indirect - go.opentelemetry.io/otel/trace v1.26.0 // indirect - go.opentelemetry.io/proto/otlp v1.2.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.53.0 // indirect + go.opentelemetry.io/contrib/propagators/jaeger v1.29.0 // indirect + go.opentelemetry.io/contrib/samplers/jaegerremote v0.23.0 // indirect + go.opentelemetry.io/otel v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect + go.opentelemetry.io/otel/sdk v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/mod v0.13.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.14.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240415180920-8c6c420018be // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect - google.golang.org/grpc v1.63.2 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/grpc v1.66.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/grafana-plugin/go.sum b/grafana-plugin/go.sum index 760d8efeba..352713810b 100644 --- a/grafana-plugin/go.sum +++ b/grafana-plugin/go.sum @@ -37,8 +37,9 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M= github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= @@ -64,18 +65,22 @@ github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1 github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/grafana/grafana-plugin-sdk-go v0.228.0 h1:LlPqyB+RZTtDy8RVYD7iQVJW5A0gMoGSI/+Ykz8HebQ= -github.com/grafana/grafana-plugin-sdk-go v0.228.0/go.mod h1:u4K9vVN6eU86loO68977eTXGypC4brUCnk4sfDzutZU= +github.com/grafana/grafana-plugin-sdk-go v0.250.0 h1:9EBucp9jLqMx2b8NTlOXH+4OuQWUh6L85c6EJUN8Jdo= +github.com/grafana/grafana-plugin-sdk-go v0.250.0/go.mod h1:gCGN9kHY3KeX4qyni3+Kead38Q+85pYOrsDcxZp6AIk= +github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= +github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= -github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= +github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= +github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY= @@ -90,17 +95,16 @@ github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpR github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -129,6 +133,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= @@ -139,22 +145,20 @@ github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= +github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= -github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= -github.com/prometheus/procfs v0.14.0 h1:Lw4VdGGoKEZilJsayHf0B+9YgLGREba2C6xr+Fdfq6s= -github.com/prometheus/procfs v0.14.0/go.mod h1:XL+Iwz8k8ZabyZfMFHPiilCniixqQarAy5Mu67pHlNQ= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY= github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -165,7 +169,6 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -183,40 +186,40 @@ github.com/unknwon/log v0.0.0-20150304194804-e617c87089d3/go.mod h1:1xEUf2abjfP9 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.15 h1:nuqt+pdC/KqswQKhETJjo7pvn/k4xMUxgW6liI7XpnM= github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0= -github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= -github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 h1:A3SayB3rNyt+1S6qpI9mHPkeHTZbD7XILEqWnYZb2l0= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0/go.mod h1:27iA5uvhuRNmalO+iEUdVn5ZMj2qy10Mm+XRIpRmyuU= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.51.0 h1:974XTyIwHI4nHa1+uSLxHtUnlJ2DiVtAJjk7fd07p/8= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.51.0/go.mod h1:ZvX/taFlN6TGaOOM6D42wrNwPKUV1nGO2FuUXkityBU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc= -go.opentelemetry.io/contrib/propagators/jaeger v1.26.0 h1:RH76Cl2pfOLLoCtxAPax9c7oYzuL1tiI7/ZPJEmEmOw= -go.opentelemetry.io/contrib/propagators/jaeger v1.26.0/go.mod h1:W/cylm0ZtJK1uxsuTqoYGYPnqpZ8CeVGgW7TwfXPsGw= -go.opentelemetry.io/contrib/samplers/jaegerremote v0.20.0 h1:ja+d7Aea/9PgGxB63+E0jtRFpma717wubS0KFkZpmYw= -go.opentelemetry.io/contrib/samplers/jaegerremote v0.20.0/go.mod h1:Yc1eg51SJy7xZdOTyg1xyFcwE+ghcWh3/0hKeLo6Wlo= -go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= -go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 h1:Waw9Wfpo/IXzOI8bCB7DIk+0JZcqqsyn1JFnAc+iam8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0/go.mod h1:wnJIG4fOqyynOnnQF/eQb4/16VlX2EJAHhHgqIqWfAo= -go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= -go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= -go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= -go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= -go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= -go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= -go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= -go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.53.0 h1:IVtyPth4Rs5P8wIf0mP2KVKFNTJ4paX9qQ4Hkh5gFdc= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.53.0/go.mod h1:ImRBLMJv177/pwiLZ7tU7HDGNdBv7rS0HQ99eN/zBl8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/contrib/propagators/jaeger v1.29.0 h1:+YPiqF5rR6PqHBlmEFLPumbSP0gY0WmCGFayXRcCLvs= +go.opentelemetry.io/contrib/propagators/jaeger v1.29.0/go.mod h1:6PD7q7qquWSp3Z4HeM3e/2ipRubaY1rXZO8NIHVDZjs= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.23.0 h1:qKi9ntCcronqWqfuKxqrxZlZd82jXJEgGiAWH1+phxo= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.23.0/go.mod h1:1kbAgQa5lgYC3rC6cE3jSxQ/Q13l33wv/WI8U+htwag= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= +go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -226,19 +229,19 @@ golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191020152052-9984515f0562/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -251,18 +254,19 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -271,16 +275,15 @@ golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3j golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gonum.org/v1/gonum v0.12.0 h1:xKuo6hzt+gMav00meVPUlXwSdoEJP46BR+wdxQEFK2o= gonum.org/v1/gonum v0.12.0/go.mod h1:73TDxJfAAHeA8Mk9mf8NlIppyhQNo5GLTcYeqgo2lvY= -google.golang.org/genproto/googleapis/api v0.0.0-20240415180920-8c6c420018be h1:Zz7rLWqp0ApfsR/l7+zSHhY3PMiH2xqgxlfYfAfNpoU= -google.golang.org/genproto/googleapis/api v0.0.0-20240415180920-8c6c420018be/go.mod h1:dvdCTIoAGbkWbcIKBniID56/7XHTt6WfxXNMxuziJ+w= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be h1:LG9vZxsWGOmUKieR8wPAUR3u3MpnYFQZROPIMaXh7/A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= +google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify/fsnotify.v1 v1.4.7 h1:XNNYLJHt73EyYiCZi6+xjupS9CpvmiDgjPTAjrBlQbo= diff --git a/grafana-plugin/package.json b/grafana-plugin/package.json index 5fef73c9fe..c4a9b55d26 100644 --- a/grafana-plugin/package.json +++ b/grafana-plugin/package.json @@ -1,6 +1,6 @@ { "name": "grafana-oncall-app", - "version": "1.9.23", + "version": "1.9.27", "description": "Grafana OnCall Plugin", "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx --max-warnings=20 ./src ./e2e-tests", @@ -138,7 +138,7 @@ "@grafana/data": "^11.1.3", "@grafana/faro-web-sdk": "^1.4.2", "@grafana/faro-web-tracing": "^1.4.2", - "@grafana/labels": "^1.6.5", + "@grafana/labels": "^1.6.6", "@grafana/runtime": "^11.1.3", "@grafana/scenes": "^1.28.0", "@grafana/schema": "^11.1.3", @@ -183,6 +183,6 @@ }, "resolutions": { "braces": "3.0.3", - "micromatch": "4.0.6" + "micromatch": "4.0.8" } } diff --git a/grafana-plugin/pnpm-lock.yaml b/grafana-plugin/pnpm-lock.yaml index 9f796a7573..f6fa012539 100644 --- a/grafana-plugin/pnpm-lock.yaml +++ b/grafana-plugin/pnpm-lock.yaml @@ -6,7 +6,7 @@ settings: overrides: braces: 3.0.3 - micromatch: 4.0.6 + micromatch: 4.0.8 importers: @@ -37,8 +37,8 @@ importers: specifier: ^1.4.2 version: 1.9.1 '@grafana/labels': - specifier: ^1.6.5 - version: 1.6.5(@grafana/ui@11.2.0(@types/react-dom@18.2.0)(@types/react@18.2.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^1.6.6 + version: 1.6.6(@grafana/ui@11.2.0(@types/react-dom@18.2.0)(@types/react@18.2.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@grafana/runtime': specifier: ^11.1.3 version: 11.2.0(@types/react-dom@18.2.0)(@types/react@18.2.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -746,8 +746,8 @@ packages: '@grafana/faro-web-tracing@1.9.1': resolution: {integrity: sha512-BuXMxUX6N8kDwOJO2wfCFOWfyEwfduEdJGT9HhgA3VPGmpgzpvZD6FOt1vsBMOZWsKsI20EcNM21moUy08dWAA==} - '@grafana/labels@1.6.5': - resolution: {integrity: sha512-Z0Ho69My9evZkTYtgmYEIWuPGRfsHeM77pbExdPLvA8ZOB8LqoEEdRWJW7tyY3xPr1lGj//aSA2j697JoiXVrg==} + '@grafana/labels@1.6.6': + resolution: {integrity: sha512-jDmiCNpv9wXEQyB16Ptj2msQjykUecUtRicNpNowOG6eQ6GPktLiDSvbj+z5Ce8ieJ0pRuDcF7n3w1mf8ias6w==} peerDependencies: '@grafana/ui': ^11.0.0 react: ^17.0.0 || ^18.0.0 @@ -4286,8 +4286,8 @@ packages: micro-memoize@4.1.2: resolution: {integrity: sha512-+HzcV2H+rbSJzApgkj0NdTakkC+bnyeiUxgT6/m7mjcz1CmM22KYFKp+EVj1sWe4UYcnriJr5uqHQD/gMHLD+g==} - micromatch@4.0.6: - resolution: {integrity: sha512-Y4Ypn3oujJYxJcMacVgcs92wofTHxp9FzfDpQON4msDefoC0lb3ETvQLOdLcbhSwU1bz8HrL/1sygfBIHudrkQ==} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} mime-db@1.33.0: @@ -6991,7 +6991,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@grafana/labels@1.6.5(@grafana/ui@11.2.0(@types/react-dom@18.2.0)(@types/react@18.2.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@grafana/labels@1.6.6(@grafana/ui@11.2.0(@types/react-dom@18.2.0)(@types/react@18.2.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@emotion/css': 11.13.0 '@grafana/ui': 11.2.0(@types/react-dom@18.2.0)(@types/react@18.2.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -7219,7 +7219,7 @@ snapshots: jest-util: 29.7.0 jest-validate: 29.7.0 jest-watcher: 29.7.0 - micromatch: 4.0.6 + micromatch: 4.0.8 pretty-format: 29.7.0 slash: 3.0.0 strip-ansi: 6.0.1 @@ -7356,7 +7356,7 @@ snapshots: jest-haste-map: 29.7.0 jest-regex-util: 29.6.3 jest-util: 29.7.0 - micromatch: 4.0.6 + micromatch: 4.0.8 pirates: 4.0.6 slash: 3.0.0 write-file-atomic: 4.0.2 @@ -9873,7 +9873,7 @@ snapshots: '@types/eslint': 8.56.12 eslint: 8.57.0 jest-worker: 29.7.0 - micromatch: 4.0.6 + micromatch: 4.0.8 normalize-path: 3.0.0 schema-utils: 4.2.0 webpack: 5.94.0(@swc/core@1.7.22(@swc/helpers@0.5.12))(webpack-cli@5.1.4) @@ -10084,7 +10084,7 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.6 + micromatch: 4.0.8 fast-json-stable-stringify@2.1.0: {} @@ -10839,7 +10839,7 @@ snapshots: jest-runner: 29.7.0 jest-util: 29.7.0 jest-validate: 29.7.0 - micromatch: 4.0.6 + micromatch: 4.0.8 parse-json: 5.2.0 pretty-format: 29.7.0 slash: 3.0.0 @@ -10916,7 +10916,7 @@ snapshots: jest-regex-util: 29.6.3 jest-util: 29.7.0 jest-worker: 29.7.0 - micromatch: 4.0.6 + micromatch: 4.0.8 walker: 1.0.8 optionalDependencies: fsevents: 2.3.3 @@ -10952,7 +10952,7 @@ snapshots: '@types/stack-utils': 2.0.3 chalk: 4.1.2 graceful-fs: 4.2.11 - micromatch: 4.0.6 + micromatch: 4.0.8 pretty-format: 27.5.1 slash: 3.0.0 stack-utils: 2.0.6 @@ -10964,7 +10964,7 @@ snapshots: '@types/stack-utils': 2.0.3 chalk: 4.1.2 graceful-fs: 4.2.11 - micromatch: 4.0.6 + micromatch: 4.0.8 pretty-format: 29.7.0 slash: 3.0.0 stack-utils: 2.0.6 @@ -11298,7 +11298,7 @@ snapshots: execa: 4.1.0 listr2: 3.14.0(enquirer@2.4.1) log-symbols: 4.1.0 - micromatch: 4.0.6 + micromatch: 4.0.8 normalize-path: 3.0.0 please-upgrade-node: 3.2.0 string-argv: 0.3.1 @@ -11471,10 +11471,10 @@ snapshots: micro-memoize@4.1.2: {} - micromatch@4.0.6: + micromatch@4.0.8: dependencies: braces: 3.0.3 - picomatch: 4.0.2 + picomatch: 2.3.1 mime-db@1.33.0: {} @@ -13197,7 +13197,7 @@ snapshots: known-css-properties: 0.26.0 mathml-tag-names: 2.1.3 meow: 9.0.0 - micromatch: 4.0.6 + micromatch: 4.0.8 normalize-path: 3.0.0 picocolors: 1.0.1 postcss: 8.4.43 diff --git a/grafana-plugin/src/components/ExtensionLinkMenu/ExtensionLinkMenu.tsx b/grafana-plugin/src/components/ExtensionLinkMenu/ExtensionLinkMenu.tsx index ecc3ebe9a8..c797698cfa 100644 --- a/grafana-plugin/src/components/ExtensionLinkMenu/ExtensionLinkMenu.tsx +++ b/grafana-plugin/src/components/ExtensionLinkMenu/ExtensionLinkMenu.tsx @@ -2,7 +2,7 @@ import React, { ReactElement, useMemo } from 'react'; import { locationUtil, PluginExtensionLink, PluginExtensionTypes } from '@grafana/data'; import { IconName, Menu } from '@grafana/ui'; -import { getPluginId } from 'helpers/consts'; +import { getPluginId, PLUGIN_ROOT } from 'helpers/consts'; import { truncateTitle } from 'helpers/string'; import { PluginBridge, SupportedPlugin } from 'components/PluginBridge/PluginBridge'; @@ -58,14 +58,23 @@ const IRMActionSection: React.FC = ({ webhookModal, extensions, declareIn return ( - - {extensions.length > 0 && ( - + } + > + - )} + ); }; diff --git a/grafana-plugin/src/containers/IntegrationForm/IntegrationForm.tsx b/grafana-plugin/src/containers/IntegrationForm/IntegrationForm.tsx index c30f538f0f..0f526c8bb3 100644 --- a/grafana-plugin/src/containers/IntegrationForm/IntegrationForm.tsx +++ b/grafana-plugin/src/containers/IntegrationForm/IntegrationForm.tsx @@ -456,7 +456,7 @@ export const IntegrationForm = observer( onHide(); async function createNewIntegration(): Promise { - const response = await alertReceiveChannelStore.create({ data, skipErrorHandling: true }); + const response = await alertReceiveChannelStore.create({ data }); const pushHistory = (id: ApiSchemas['AlertReceiveChannel']['id']) => navigate(`${PLUGIN_ROOT}/integrations/${id}`); diff --git a/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookForm.tsx b/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookForm.tsx index ea38f830e4..29277358ba 100644 --- a/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookForm.tsx +++ b/grafana-plugin/src/containers/OutgoingWebhookForm/OutgoingWebhookForm.tsx @@ -100,7 +100,11 @@ export const OutgoingWebhookForm = observer((props: OutgoingWebhookFormProps) => defaultValues: data, }); - const { setValue, reset, setError } = formMethods; + const { + setValue, + reset, + setError, + } = formMethods; const onSubmit = useCallback( async (rawData: Partial) => { @@ -115,8 +119,11 @@ export const OutgoingWebhookForm = observer((props: OutgoingWebhookFormProps) => onHide(); onUpdate(); } catch (error) { + const values = formMethods.getValues(); Object.keys(error.response.data).forEach((key) => { - setError(key as WebhookFormFieldName, { message: error.response.data[key][0] }); + if (key in values) { + setError(key as WebhookFormFieldName, { message: error.response.data[key][0] }); + } }); } }, diff --git a/grafana-plugin/src/helpers/consts.ts b/grafana-plugin/src/helpers/consts.ts index 5d8f034911..0bfa08c0ac 100644 --- a/grafana-plugin/src/helpers/consts.ts +++ b/grafana-plugin/src/helpers/consts.ts @@ -1,3 +1,4 @@ +import { GrafanaBootConfig } from '@grafana/runtime'; import { OnCallAppPluginMeta } from 'app-types'; //@ts-ignore @@ -9,8 +10,10 @@ export const PluginId = { } as const; export type PluginId = (typeof PluginId)[keyof typeof PluginId]; +export const getIsIrmPluginPresent = () => PluginId.Irm in (window.grafanaBootData?.settings as GrafanaBootConfig).apps; + // Determine current environment: cloud, oss or local -const CLOUD_VERSION_REGEX = /^(v\d+\.\d+\.\d+|github-actions-[a-zA-Z0-9-]+)$/ +const CLOUD_VERSION_REGEX = /^(v\d+\.\d+\.\d+|github-actions-[a-zA-Z0-9-]+)$/; const determineCurrentEnv = (): 'oss' | 'cloud' | 'local' => { if (CLOUD_VERSION_REGEX.test(plugin?.version)) { return 'cloud'; diff --git a/grafana-plugin/src/models/alert_receive_channel/alert_receive_channel.ts b/grafana-plugin/src/models/alert_receive_channel/alert_receive_channel.ts index bf17bfb8b0..7107bf7703 100644 --- a/grafana-plugin/src/models/alert_receive_channel/alert_receive_channel.ts +++ b/grafana-plugin/src/models/alert_receive_channel/alert_receive_channel.ts @@ -44,7 +44,6 @@ export class AlertReceiveChannelStore { this.rootStore = rootStore; } - @WithGlobalNotification({ failure: 'There was an issue creating Integration. Please try again.' }) async create({ data, skipErrorHandling, diff --git a/grafana-plugin/src/module.ts b/grafana-plugin/src/module.ts index f73db2ac20..a11fc863f7 100644 --- a/grafana-plugin/src/module.ts +++ b/grafana-plugin/src/module.ts @@ -1,7 +1,7 @@ import { ComponentClass } from 'react'; import { AppPlugin, PluginExtensionPoints } from '@grafana/data'; -import { IRM_TAB } from 'helpers/consts'; +import { getIsIrmPluginPresent, IRM_TAB } from 'helpers/consts'; import { isCurrentGrafanaVersionEqualOrGreaterThan } from 'helpers/helpers'; import { MobileAppConnectionWrapper } from 'containers/MobileAppConnection/MobileAppConnection'; @@ -45,7 +45,8 @@ function isUseProfileExtensionPointEnabled(): boolean { isCurrentGrafanaVersionEqualOrGreaterThan({ minMajor: 10, minMinor: 3 }) && 'configureExtensionComponent' in plugin && PluginExtensionPoints != null && - 'UserProfileTab' in PluginExtensionPoints + 'UserProfileTab' in PluginExtensionPoints && + !getIsIrmPluginPresent() ); } diff --git a/grafana-plugin/src/pages/incident/Incident.styles.ts b/grafana-plugin/src/pages/incident/Incident.styles.ts index 7afaeb24f9..6dc1229718 100644 --- a/grafana-plugin/src/pages/incident/Incident.styles.ts +++ b/grafana-plugin/src/pages/incident/Incident.styles.ts @@ -51,6 +51,8 @@ export const getIncidentStyles = (theme: GrafanaTheme2) => { a { word-break: break-all; + color: ${theme.colors.text.link}; + text-decoration: underline; } ul { diff --git a/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.tsx b/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.tsx index 3c051d7969..b2613a8a2a 100644 --- a/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.tsx +++ b/grafana-plugin/src/pages/outgoing_webhooks/OutgoingWebhooks.tsx @@ -196,17 +196,19 @@ class OutgoingWebhooks extends React.Component )} -
- - - - - +
+
+ + + + + +
@@ -464,10 +466,15 @@ const getStyles = () => { align-items: baseline; `, + relative: css` + position: relative; + padding-top: 16px; + `, + newWebhookButton: css` position: absolute; right: 0; - top: -48px; + top: -40px; `, }; }; diff --git a/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx b/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx index 921b8095cb..01594c750c 100644 --- a/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx +++ b/grafana-plugin/src/plugin/GrafanaPluginRootPage.tsx @@ -32,10 +32,10 @@ import { LiveSettings } from 'pages/settings/tabs/LiveSettings/LiveSettingsPage' import { UsersPage } from 'pages/users/Users'; import { rootStore } from 'state/rootStore'; import { useStore } from 'state/useStore'; -import 'assets/style/global.css'; import { getQueryParams } from './GrafanaPluginRootPage.helpers'; +import globalStyles from '!raw-loader!assets/style/global.css'; import grafanaGlobalStyle from '!raw-loader!assets/style/grafanaGlobalStyles.css'; export const GrafanaPluginRootPage = observer((props: AppRootProps) => { @@ -84,6 +84,7 @@ export const Root = observer((props: AppRootProps) => { const styleEl = document.createElement('style'); const head = document.head || document.getElementsByTagName('head')[0]; styleEl.appendChild(document.createTextNode(grafanaGlobalStyle)); + styleEl.appendChild(document.createTextNode(globalStyles)); // append grafana overriding styles to head head.appendChild(styleEl); diff --git a/grafana-plugin/src/version.ts b/grafana-plugin/src/version.ts index b2a27fbc5c..cfc0671c8a 100644 --- a/grafana-plugin/src/version.ts +++ b/grafana-plugin/src/version.ts @@ -2,4 +2,4 @@ export const GIT_COMMIT = 'dev'; // Declare a constant that will be updated by release-please action -export const CURRENT_VERSION = '1.9.23' as string; // x-release-please-version +export const CURRENT_VERSION = '1.9.27' as string; // x-release-please-version From 8754f60530ee17664274445ea35327b419b34d3e Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Tue, 1 Oct 2024 10:37:28 -0300 Subject: [PATCH 4/5] Update schedule related users to use cached final representation (#5101) Related to https://github.com/grafana/oncall/issues/4936 Cached final schedule keeps a (now - 15d, now + 6m) window representation of a schedule (this representation always use users' username; it will un-relate users that are not anymore associated to a schedule). --- engine/apps/alerts/tests/test_paging.py | 1 + engine/apps/api/tests/test_schedules.py | 4 ++ .../tasks/test_new_shift_swap_request.py | 1 + .../apps/schedules/models/on_call_schedule.py | 22 ++-------- .../schedules/tests/test_on_call_schedule.py | 41 ++++++++++++++++++- .../test_manage_responders.py | 2 + .../tests/test_scenario_steps/test_paging.py | 2 + 7 files changed, 52 insertions(+), 21 deletions(-) diff --git a/engine/apps/alerts/tests/test_paging.py b/engine/apps/alerts/tests/test_paging.py index de67237072..0528782d0e 100644 --- a/engine/apps/alerts/tests/test_paging.py +++ b/engine/apps/alerts/tests/test_paging.py @@ -48,6 +48,7 @@ def test_user_is_oncall(make_organization, make_user_for_organization, make_sche ) on_call_shift.add_rolling_users([[oncall_user]]) schedule.refresh_ical_file() + schedule.refresh_ical_final_schedule() assert user_is_oncall(not_oncall_user) is False assert user_is_oncall(oncall_user) is True diff --git a/engine/apps/api/tests/test_schedules.py b/engine/apps/api/tests/test_schedules.py index 65dcd58899..3a80ac1095 100644 --- a/engine/apps/api/tests/test_schedules.py +++ b/engine/apps/api/tests/test_schedules.py @@ -435,6 +435,7 @@ def test_get_list_schedules_by_mine( ) override.add_rolling_users([[user]]) web_schedule.refresh_ical_file() + web_schedule.refresh_ical_final_schedule() url = reverse("api-internal:schedule-list") + query_param response = client.get(url, format="json", **make_user_auth_headers(user, token)) @@ -1497,6 +1498,7 @@ def test_next_shifts_per_user( override.add_rolling_users([[user_c]]) # final schedule: 7-12: B, 15-16: A, 16-17: B, 17-18: C (override), 18-20: C + schedule.refresh_ical_final_schedule() url = reverse("api-internal:schedule-next-shifts-per-user", kwargs={"pk": schedule.public_primary_key}) response = client.get(url, format="json", **make_user_auth_headers(admin, token)) @@ -1569,6 +1571,7 @@ def test_next_shifts_per_user_ical_schedule_using_emails( schedule_class=OnCallScheduleICal, cached_ical_file_primary=cached_ical_primary_schedule, ) + schedule.refresh_ical_final_schedule() url = reverse("api-internal:schedule-next-shifts-per-user", kwargs={"pk": schedule.public_primary_key}) response = client.get(url, format="json", **make_user_auth_headers(admin, token)) @@ -1628,6 +1631,7 @@ def test_related_users( ) override.add_rolling_users([[user_c]]) schedule.refresh_ical_file() + schedule.refresh_ical_final_schedule() url = reverse("api-internal:schedule-related-users", kwargs={"pk": schedule.public_primary_key}) response = client.get(url, format="json", **make_user_auth_headers(admin, token)) diff --git a/engine/apps/mobile_app/tests/tasks/test_new_shift_swap_request.py b/engine/apps/mobile_app/tests/tasks/test_new_shift_swap_request.py index 3ef7599244..452b98952f 100644 --- a/engine/apps/mobile_app/tests/tasks/test_new_shift_swap_request.py +++ b/engine/apps/mobile_app/tests/tasks/test_new_shift_swap_request.py @@ -229,6 +229,7 @@ def test_notify_shift_swap_request_success( on_call_shift.add_rolling_users([[user]]) schedule.refresh_ical_file() + schedule.refresh_ical_final_schedule() schedule.refresh_from_db() swap_start = now + timezone.timedelta(days=100) diff --git a/engine/apps/schedules/models/on_call_schedule.py b/engine/apps/schedules/models/on_call_schedule.py index 126b62048e..e053a6a51f 100644 --- a/engine/apps/schedules/models/on_call_schedule.py +++ b/engine/apps/schedules/models/on_call_schedule.py @@ -11,7 +11,6 @@ from django.conf import settings from django.core.validators import MinLengthValidator from django.db import models -from django.db.models import Q from django.db.utils import DatabaseError from django.utils import timezone from django.utils.functional import cached_property @@ -158,10 +157,7 @@ def get_oncall_users(self, events_datetime=None): def related_to_user(self, user): username_regex = RE_ICAL_SEARCH_USERNAME.format(user.username) return self.filter( - Q(cached_ical_file_primary__regex=username_regex) - | Q(cached_ical_file_primary__contains=user.email) - | Q(cached_ical_file_overrides__regex=username_regex) - | Q(cached_ical_file_overrides__contains=user.email), + cached_ical_final_schedule__regex=username_regex, organization=user.organization, ) @@ -344,10 +340,8 @@ def _drop_overrides_ical_file(self): def related_users(self): """Return users referenced in the schedule.""" usernames = [] - if self.cached_ical_file_primary: - usernames += RE_ICAL_FETCH_USERNAME.findall(self.cached_ical_file_primary) - if self.cached_ical_file_overrides: - usernames += RE_ICAL_FETCH_USERNAME.findall(self.cached_ical_file_overrides) + if self.cached_ical_final_schedule: + usernames += RE_ICAL_FETCH_USERNAME.findall(self.cached_ical_final_schedule) return self.organization.users.filter(username__in=usernames) def filter_events( @@ -1128,16 +1122,6 @@ def _refresh_overrides_ical_file(self): ) self.save(update_fields=["cached_ical_file_overrides", "prev_ical_file_overrides", "ical_file_error_overrides"]) - def related_users(self): - """Return users referenced in the schedule.""" - # combine users based on usernames and users via email (allowed in iCal based schedules) - usernames = [] - if self.cached_ical_file_primary: - usernames += RE_ICAL_FETCH_USERNAME.findall(self.cached_ical_file_primary) - if self.cached_ical_file_overrides: - usernames += RE_ICAL_FETCH_USERNAME.findall(self.cached_ical_file_overrides) - return self.organization.users.filter(Q(username__in=usernames) | Q(email__in=usernames)) - # Insight logs @property def insight_logs_serialized(self): diff --git a/engine/apps/schedules/tests/test_on_call_schedule.py b/engine/apps/schedules/tests/test_on_call_schedule.py index 77308544a1..e63c96b2f8 100644 --- a/engine/apps/schedules/tests/test_on_call_schedule.py +++ b/engine/apps/schedules/tests/test_on_call_schedule.py @@ -1206,7 +1206,7 @@ def test_schedule_related_users(make_organization, make_user_for_organization, m now = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0) start_date = now - timezone.timedelta(days=7) - user_a, _, _, user_d, user_e = (make_user_for_organization(organization, username=i) for i in "ABCDE") + user_a, user_b, _, user_d, user_e = (make_user_for_organization(organization, username=i) for i in "ABCDE") shifts = ( # user, priority, start time (h), duration (hs) @@ -1239,7 +1239,20 @@ def test_schedule_related_users(make_organization, make_user_for_organization, m ) override.add_rolling_users([[user_e]]) + # override: 22-23, a month ago / B (won't be considered a related user) + override_data = { + "start": start_date - timezone.timedelta(hours=22, days=30), + "rotation_start": start_date - timezone.timedelta(hours=22, days=30), + "duration": timezone.timedelta(hours=1), + "schedule": schedule, + } + override = make_on_call_shift( + organization=organization, shift_type=CustomOnCallShift.TYPE_OVERRIDE, **override_data + ) + override.add_rolling_users([[user_b]]) + schedule.refresh_ical_file() + schedule.refresh_ical_final_schedule() schedule.refresh_from_db() users = schedule.related_users() @@ -1282,6 +1295,7 @@ def test_schedule_related_users_usernames( on_call_shift.add_rolling_users([[user]]) schedule.refresh_ical_file() + schedule.refresh_ical_final_schedule() schedule.refresh_from_db() assert set(schedule.related_users()) == set(users) @@ -1304,7 +1318,7 @@ def test_schedule_related_users_emails(make_organization, make_user_for_organiza DTSTAMP:20230127T151619Z UID:something SUMMARY:testing@testing.com - RRULE:FREQ=WEEKLY;UNTIL=20221231T010101 + RRULE:FREQ=WEEKLY DTSTART;TZID=Europe/Madrid:20220309T130000 DTEND;TZID=Europe/Madrid:20220309T133000 SEQUENCE:4 @@ -1317,6 +1331,8 @@ def test_schedule_related_users_emails(make_organization, make_user_for_organiza schedule_class=OnCallScheduleICal, cached_ical_file_primary=cached_ical_primary_schedule, ) + schedule.refresh_ical_final_schedule() + schedule.refresh_from_db() assert set(schedule.related_users()) == {user} @@ -1604,6 +1620,7 @@ def test_user_related_schedules( ) on_call_shift.add_rolling_users([[user]]) schedule1.refresh_ical_file() + schedule1.refresh_ical_final_schedule() schedule2 = make_schedule(organization, schedule_class=OnCallScheduleWeb) override_data = { @@ -1617,10 +1634,27 @@ def test_user_related_schedules( ) override.add_rolling_users([[admin]]) schedule2.refresh_ical_file() + schedule2.refresh_ical_final_schedule() # schedule3 make_schedule(organization, schedule_class=OnCallScheduleWeb) + # schedule4 + schedule4 = make_schedule(organization, schedule_class=OnCallScheduleWeb) + # user was part of the schedule some time ago (outside of the final schedule window) + override_data = { + "start": today - timezone.timedelta(days=21), + "rotation_start": today - timezone.timedelta(days=21), + "duration": timezone.timedelta(hours=1), + "schedule": schedule4, + } + override = make_on_call_shift( + organization=organization, shift_type=CustomOnCallShift.TYPE_OVERRIDE, **override_data + ) + override.add_rolling_users([[admin]]) + schedule4.refresh_ical_file() + schedule4.refresh_ical_final_schedule() + schedules = OnCallSchedule.objects.related_to_user(admin) assert set(schedules) == {schedule1, schedule2} @@ -1658,6 +1692,7 @@ def test_user_related_schedules_only_username( ) on_call_shift.add_rolling_users([[user]]) schedule1.refresh_ical_file() + schedule1.refresh_ical_final_schedule() schedule2 = make_schedule(organization, schedule_class=OnCallScheduleWeb) override_data = { @@ -1671,6 +1706,7 @@ def test_user_related_schedules_only_username( ) override.add_rolling_users([[user]]) schedule2.refresh_ical_file() + schedule2.refresh_ical_final_schedule() # schedule3 schedule3 = make_schedule(organization, schedule_class=OnCallScheduleWeb) @@ -1685,6 +1721,7 @@ def test_user_related_schedules_only_username( ) override.add_rolling_users([[other_user]]) schedule3.refresh_ical_file() + schedule3.refresh_ical_final_schedule() schedules = OnCallSchedule.objects.related_to_user(user) assert set(schedules) == {schedule1, schedule2} diff --git a/engine/apps/slack/tests/test_scenario_steps/test_manage_responders.py b/engine/apps/slack/tests/test_scenario_steps/test_manage_responders.py index 5238aea6d2..9802e6c6f8 100644 --- a/engine/apps/slack/tests/test_scenario_steps/test_manage_responders.py +++ b/engine/apps/slack/tests/test_scenario_steps/test_manage_responders.py @@ -114,6 +114,7 @@ def test_add_user_no_warning(manage_responders_setup, make_schedule, make_on_cal ) on_call_shift.add_rolling_users([[user]]) schedule.refresh_ical_file() + schedule.refresh_ical_final_schedule() # setup notification policy make_user_notification_policy( user=user, @@ -199,6 +200,7 @@ def test_get_users_select(make_organization, make_user, make_schedule, make_on_c ) on_call_shift.add_rolling_users([[oncall_user]]) schedule.refresh_ical_file() + schedule.refresh_ical_final_schedule() select_input = _get_users_select( organization=organization, input_id_prefix="test", action_id="test", max_options_per_group=2 diff --git a/engine/apps/slack/tests/test_scenario_steps/test_paging.py b/engine/apps/slack/tests/test_scenario_steps/test_paging.py index 0e80ac322b..9c62d8e5a0 100644 --- a/engine/apps/slack/tests/test_scenario_steps/test_paging.py +++ b/engine/apps/slack/tests/test_scenario_steps/test_paging.py @@ -186,6 +186,7 @@ def test_add_user_no_warning(make_organization_and_user_with_slack_identities, m ) on_call_shift.add_rolling_users([[user]]) schedule.refresh_ical_file() + schedule.refresh_ical_final_schedule() payload = make_paging_view_slack_payload(selected_org=organization, user=user) @@ -221,6 +222,7 @@ def test_add_user_maximum_exceeded(make_organization_and_user_with_slack_identit ) on_call_shift.add_rolling_users([[user]]) schedule.refresh_ical_file() + schedule.refresh_ical_final_schedule() payload = make_paging_view_slack_payload(selected_org=organization, user=user) From e9d94ebc1ebc36d82a33f5ef7a5890474de6640b Mon Sep 17 00:00:00 2001 From: Vadim Stepanov Date: Tue, 1 Oct 2024 15:01:38 +0100 Subject: [PATCH 5/5] fix alert group page bug (#5105) # What this PR does fixes a bug where it's not possible to view an alert group older than 30 days Screenshot 2024-10-01 at 14 36 00 ## Which issue(s) this PR closes the bug was introduced in https://github.com/grafana/oncall/pull/5067 ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --- engine/apps/api/tests/test_alert_group.py | 38 +++++++++++++++++++++++ engine/apps/api/views/alert_group.py | 3 +- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/engine/apps/api/tests/test_alert_group.py b/engine/apps/api/tests/test_alert_group.py index 42808e85fe..a015fccc3e 100644 --- a/engine/apps/api/tests/test_alert_group.py +++ b/engine/apps/api/tests/test_alert_group.py @@ -2344,3 +2344,41 @@ def test_alert_group_external_urls( "url": "https://some-url", } assert response.json()["external_urls"] == [expected] + + +@pytest.mark.django_db +def test_filter_default_started_at( + make_organization_and_user_with_plugin_token, + make_alert_receive_channel, + make_channel_filter, + make_alert_group, + make_alert, + make_user_auth_headers, +): + organization, user, token = make_organization_and_user_with_plugin_token() + alert_receive_channel = make_alert_receive_channel(organization) + channel_filter = make_channel_filter(alert_receive_channel, is_default=True) + + old_alert_group = make_alert_group(alert_receive_channel, channel_filter=channel_filter) + old_alert_group.started_at = timezone.now() - timezone.timedelta(days=31) + old_alert_group.save(update_fields=["started_at"]) + make_alert(alert_group=old_alert_group, raw_request_data=alert_raw_request_data) + + new_alert_group = make_alert_group(alert_receive_channel, channel_filter=channel_filter) + make_alert(alert_group=new_alert_group, raw_request_data=alert_raw_request_data) + + client = APIClient() + + # by default, no alert groups older than 30 days should be listed + response = client.get(reverse("api-internal:alertgroup-list"), **make_user_auth_headers(user, token)) + assert response.status_code == status.HTTP_200_OK + assert len(response.json()["results"]) == 1 + assert response.json()["results"][0]["pk"] == new_alert_group.public_primary_key + + # but it should still be possible to retrieve an old alert group by its ID + response = client.get( + reverse("api-internal:alertgroup-detail", kwargs={"pk": old_alert_group.public_primary_key}), + **make_user_auth_headers(user, token), + ) + assert response.status_code == status.HTTP_200_OK + assert response.json()["pk"] == old_alert_group.public_primary_key diff --git a/engine/apps/api/views/alert_group.py b/engine/apps/api/views/alert_group.py index 8e9cf00516..35ef836a68 100644 --- a/engine/apps/api/views/alert_group.py +++ b/engine/apps/api/views/alert_group.py @@ -332,8 +332,7 @@ def get_queryset(self, ignore_filtering_by_available_teams=False): alert_receive_channels_ids = list(alert_receive_channels_qs.values_list("id", flat=True)) queryset = AlertGroup.objects.filter(channel__in=alert_receive_channels_ids) - # This is a quick fix to speed up requests from mobile app by adding default `started_at` filter value - if not self.request.query_params.get("started_at"): + if self.action in ("list", "stats") and not self.request.query_params.get("started_at"): queryset = queryset.filter(started_at__gte=timezone.now() - timezone.timedelta(days=30)) if self.action in ("list", "stats") and settings.ALERT_GROUPS_DISABLE_PREFER_ORDERING_INDEX: