ci: update oss plugin release process (#5051)
# What this PR does Related to https://github.com/grafana/irm/pull/137 (**NOTE**: should only be merged after those changed are back-merged here into `grafana/oncall`) ## Which issue(s) this PR closes Also, fixes https://github.com/grafana/oncall/issues/5028 --------- Co-authored-by: Dominik <dominik.broj@grafana.com>
This commit is contained in:
parent
20d2d5a578
commit
e882e9782d
25 changed files with 130 additions and 178 deletions
|
|
@ -2,18 +2,10 @@ name: Build, sign, and package plugin
|
|||
description: Build, sign, and package plugin
|
||||
inputs:
|
||||
plugin_version_number:
|
||||
description: "The version number of the plugin"
|
||||
description: |
|
||||
The version number of the plugin. NOTE: this action will chop off the leading "v" to use
|
||||
it as the official plugin version.
|
||||
required: true
|
||||
grafana_access_policy_token:
|
||||
description: "The Grafana access policy token used to sign the plugin"
|
||||
required: true
|
||||
working_directory:
|
||||
description: "The working directory of the plugin"
|
||||
required: true
|
||||
is_enterprise:
|
||||
description: "Whether the plugin is an enterprise build or not"
|
||||
required: false
|
||||
default: "false"
|
||||
outputs:
|
||||
artifact_filename:
|
||||
description: "The filename of the plugin artifact"
|
||||
|
|
@ -21,12 +13,24 @@ outputs:
|
|||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
# This will fetch the secret keys from vault and set them as environment variables for subsequent steps
|
||||
- name: Get Vault secrets
|
||||
uses: grafana/shared-workflows/actions/get-vault-secrets@main
|
||||
with:
|
||||
repo_secrets: |
|
||||
GRAFANA_ACCESS_POLICY_TOKEN=github_actions:cloud-access-policy-token
|
||||
- name: Determine official plugin version
|
||||
id: plugin-version
|
||||
shell: bash
|
||||
run: |
|
||||
# VERY IMPORTANT: chop off the "v".. this tells the oncall plugin that this is an OSS build
|
||||
PLUGIN_VERSION="$(echo ${{ inputs.plugin_version_number }} | sed 's/^v//')"
|
||||
echo version="$PLUGIN_VERSION" >> $GITHUB_OUTPUT
|
||||
- name: Determine artifact filename
|
||||
shell: bash
|
||||
id: artifact-filename
|
||||
# yamllint disable rule:line-length
|
||||
run: |
|
||||
echo filename="grafana-oncall${{ inputs.is_enterprise == 'true' && '-ee' || '' }}-app-${{ inputs.plugin_version_number }}.zip" >> $GITHUB_OUTPUT
|
||||
echo filename="grafana-oncall-app-${{ steps.plugin-version.outputs.version }}.zip" >> $GITHUB_OUTPUT
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
|
|
@ -36,16 +40,18 @@ runs:
|
|||
run: go install github.com/magefile/mage@v1.15.0
|
||||
- name: Build, sign, and package plugin
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working_directory }}
|
||||
env:
|
||||
GRAFANA_ACCESS_POLICY_TOKEN: ${{ inputs.grafana_access_policy_token }}
|
||||
working-directory: grafana-plugin
|
||||
run: |
|
||||
jq --arg v "${{ inputs.plugin_version_number }}" '.version=$v' package.json > package.new && mv package.new package.json && jq '.version' package.json;
|
||||
jq --arg v "${{ steps.plugin-version.outputs.version }}" '.version=$v' package.json > package.new && \
|
||||
mv package.new package.json && \
|
||||
jq '.version' package.json;
|
||||
|
||||
pnpm build
|
||||
mage buildAll || true
|
||||
|
||||
pnpm sign
|
||||
|
||||
if [ ! -f dist/MANIFEST.txt ]; then echo "Sign failed, MANIFEST.txt not created, aborting." && exit 1; fi
|
||||
mv dist grafana-oncall-app
|
||||
zip -r grafana-oncall-app.zip ./grafana-oncall-app
|
||||
cp grafana-oncall-app.zip ${{ steps.artifact-filename.outputs.filename }}
|
||||
# yamllint enable rule:line-length
|
||||
|
|
|
|||
3
.github/workflows/on-release-published.yml
vendored
3
.github/workflows/on-release-published.yml
vendored
|
|
@ -36,15 +36,12 @@ jobs:
|
|||
uses: grafana/shared-workflows/actions/get-vault-secrets@main
|
||||
with:
|
||||
repo_secrets: |
|
||||
GRAFANA_ACCESS_POLICY_TOKEN=github_actions:cloud-access-policy-token
|
||||
GCS_PLUGIN_PUBLISHER_SERVICE_ACCOUNT_JSON=github_actions:gcs-plugin-publisher
|
||||
- name: Build, sign, and package plugin
|
||||
id: build-sign-and-package-plugin
|
||||
uses: ./.github/actions/build-sign-and-package-plugin
|
||||
with:
|
||||
plugin_version_number: ${{ github.ref_name }}
|
||||
grafana_access_policy_token: ${{ env.GRAFANA_ACCESS_POLICY_TOKEN }}
|
||||
working_directory: grafana-plugin
|
||||
- name: Authenticate with GCS
|
||||
uses: google-github-actions/auth@v2
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -64,20 +64,20 @@ repos:
|
|||
- "@grafana/eslint-config@^5.0.0"
|
||||
- eslint-plugin-promise@^6.1.1
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: "v2.7.1"
|
||||
hooks:
|
||||
- id: prettier
|
||||
name: prettier
|
||||
types_or: [css, javascript, jsx, ts, tsx]
|
||||
files: ^grafana-plugin/src
|
||||
additional_dependencies:
|
||||
- prettier@2.8.2
|
||||
- id: prettier
|
||||
name: prettier - json
|
||||
types_or: [json]
|
||||
additional_dependencies:
|
||||
- prettier@2.8.2
|
||||
# - repo: https://github.com/pre-commit/mirrors-prettier
|
||||
# rev: "v2.7.1"
|
||||
# hooks:
|
||||
# - id: prettier
|
||||
# name: prettier
|
||||
# types_or: [css, javascript, jsx, ts, tsx]
|
||||
# files: ^grafana-plugin/src
|
||||
# additional_dependencies:
|
||||
# - prettier@2.8.2
|
||||
# - id: prettier
|
||||
# name: prettier - json
|
||||
# types_or: [json]
|
||||
# additional_dependencies:
|
||||
# - prettier@2.8.2
|
||||
|
||||
- repo: https://github.com/thibaudcolas/pre-commit-stylelint
|
||||
rev: v13.13.1
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import dayjs from 'dayjs';
|
||||
|
||||
import { test, expect, Locator } from '../fixtures';
|
||||
import { MOSCOW_TIMEZONE } from '../utils/constants';
|
||||
import { isGrafanaVersionGreaterThan, MOSCOW_TIMEZONE } from '../utils/constants';
|
||||
import { clickButton, generateRandomValue } from '../utils/forms';
|
||||
import { setTimezoneInProfile } from '../utils/grafanaProfile';
|
||||
import { createOnCallSchedule, getOverrideFormDateInputs } from '../utils/schedule';
|
||||
|
|
@ -12,6 +12,12 @@ test('Default dates in override creation modal are set to today', async ({ admin
|
|||
const onCallScheduleName = generateRandomValue();
|
||||
await createOnCallSchedule(page, onCallScheduleName, userName);
|
||||
|
||||
await page.clock.setFixedTime(new Date().setHours(12, 0, 0, 0));
|
||||
await page.getByTestId('timezone-select').locator('svg').click();
|
||||
await (isGrafanaVersionGreaterThan('11.0.0') ? page.getByRole('option') : page.getByLabel('Select option'))
|
||||
.getByText(/^GMT$/)
|
||||
.click();
|
||||
|
||||
await clickButton({ page, buttonText: 'Add override' });
|
||||
|
||||
const overrideFormDateInputs = await getOverrideFormDateInputs(page);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ test.skip('dates in schedule are correct according to selected current timezone'
|
|||
* Always set a fixed time of today's date but at 12:00:00 (noon)
|
||||
*
|
||||
* This solves the issue here https://github.com/grafana/oncall/issues/4991
|
||||
* where we would occasionally see this test flake if it srtated and finished at a different hour
|
||||
* where we would occasionally see this test flake if it started and finished at a different hour
|
||||
*
|
||||
* See playwright docs for more details
|
||||
* https://playwright.dev/docs/clock
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export const configureUserNotificationSettings = async (page: Page, notifyBy: No
|
|||
// select our notification type, first check if we have any already defined, if so, click the
|
||||
// "Add Notification Step" button
|
||||
const defaultNotificationSettingsSection = getDefaultNotificationSettingsSectionByTestId(page);
|
||||
const addNotificationStepText = 'Add Notification Step';
|
||||
const addNotificationStepText = 'Add notification step';
|
||||
|
||||
if (!(await defaultNotificationSettingsSection.locator(`button >> text=${addNotificationStepText}`).isVisible())) {
|
||||
await clickButton({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "grafana-oncall-app",
|
||||
"version": "1.0.0",
|
||||
"version": "1.9.23",
|
||||
"description": "Grafana OnCall Plugin",
|
||||
"scripts": {
|
||||
"lint": "eslint --ext .js,.jsx,.ts,.tsx --max-warnings=20 ./src ./e2e-tests",
|
||||
|
|
@ -11,9 +11,8 @@
|
|||
"build:dev": "NODE_ENV=development webpack -c ./webpack.config.ts --env development",
|
||||
"labels:link": "pnpm --dir ../../gops-labels/frontend link && pnpm link \"@grafana/labels\" && pnpm --dir ../../gops-labels/frontend watch",
|
||||
"labels:unlink": "pnpm --dir ../../gops-labels/frontend unlink",
|
||||
"mage:build-dev": "go mod download && mage -v build:debug",
|
||||
"mage:watch": "go mod download && mage -v watch",
|
||||
"mod:download": "go mod download",
|
||||
"mage:build-dev": "mage -v build:debug",
|
||||
"mage:watch": "mage -v watch",
|
||||
"test-utc": "TZ=UTC jest --verbose --testNamePattern '^((?!@london-tz).)*$'",
|
||||
"test-london-tz": "TZ=Europe/London jest --verbose --testNamePattern '@london-tz'",
|
||||
"test": "PLUGIN_ID=grafana-oncall-app pnpm test-utc && pnpm test-london-tz",
|
||||
|
|
|
|||
|
|
@ -105,8 +105,8 @@ type OnCallSettingsCache struct {
|
|||
otherPluginSettingsExpiry time.Time
|
||||
}
|
||||
|
||||
const CLOUD_VERSION_PATTERN = `^(r\d+-v?\d+\.\d+\.\d+|^github-actions-\d+)$`
|
||||
const OSS_VERSION_PATTERN = `^(v?\d+\.\d+\.\d+|dev-oss)$`
|
||||
const CLOUD_VERSION_PATTERN = `^(v\d+\.\d+\.\d+|github-actions-[a-zA-Z0-9-]+)$`
|
||||
const OSS_VERSION_PATTERN = `^(\d+\.\d+\.\d+)$`
|
||||
const CLOUD_LICENSE_NAME = "Cloud"
|
||||
const OPEN_SOURCE_LICENSE_NAME = "OpenSource"
|
||||
const INCIDENT_PLUGIN_ID = "grafana-incident-app"
|
||||
|
|
|
|||
|
|
@ -24,12 +24,12 @@ export const NotificationPoliciesSelect: FC<Props> = ({ disabled = false, import
|
|||
{
|
||||
value: NotificationPolicyValue.Default,
|
||||
label: 'Default',
|
||||
description: 'Use "Default notifications" from users personal settings',
|
||||
description: 'Use "Default notification rules" from users personal settings',
|
||||
},
|
||||
{
|
||||
value: NotificationPolicyValue.Important,
|
||||
label: 'Important',
|
||||
description: 'Use "Important notifications" from users personal settings',
|
||||
description: 'Use "Important notification rules" from users personal settings',
|
||||
},
|
||||
]}
|
||||
onChange={onChange}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers';
|
|||
import { AppFeature } from 'state/features';
|
||||
import { useStore } from 'state/useStore';
|
||||
|
||||
import plugin from '../../../package.json'; // eslint-disable-line
|
||||
|
||||
enum AlertID {
|
||||
CONNECTIVITY_WARNING = 'Connectivity Warning',
|
||||
USER_GOOGLE_OAUTH2_TOKEN_MISSING_SCOPES = 'User Google OAuth2 token is missing scopes',
|
||||
|
|
@ -59,7 +57,6 @@ export const Alerts = observer(() => {
|
|||
organizationStore: { currentOrganization },
|
||||
} = store;
|
||||
|
||||
const versionMismatchLocalStorageId = `version_mismatch_${store.backendVersion}_${plugin?.version}`;
|
||||
const isChatOpsConnected = getIfChatOpsConnected(currentUser);
|
||||
const isPhoneVerified = currentUser?.cloud_connection_status === 3 || currentUser?.verified_phone_number;
|
||||
|
||||
|
|
@ -70,7 +67,6 @@ export const Alerts = observer(() => {
|
|||
!showSlackInstallAlert &&
|
||||
!showCurrentUserGoogleOAuth2TokenIsMissingScopes() &&
|
||||
!showBannerTeam() &&
|
||||
!showMismatchWarning() &&
|
||||
!showChannelWarnings()
|
||||
) {
|
||||
return null;
|
||||
|
|
@ -117,30 +113,6 @@ export const Alerts = observer(() => {
|
|||
/>
|
||||
</Alert>
|
||||
)}
|
||||
{showMismatchWarning() && (
|
||||
<Alert
|
||||
className={styles.alert}
|
||||
severity="warning"
|
||||
title={'Version mismatch!'}
|
||||
onRemove={getRemoveAlertHandler(versionMismatchLocalStorageId)}
|
||||
>
|
||||
Please make sure you have the same versions of the Grafana OnCall plugin and the Grafana OnCall engine,
|
||||
otherwise there could be issues with your Grafana OnCall installation!
|
||||
<br />
|
||||
{`Current plugin version: ${plugin.version}, current engine version: ${store.backendVersion}`}
|
||||
<br />
|
||||
Please see{' '}
|
||||
<a
|
||||
href={'https://grafana.com/docs/oncall/latest/open-source/#update-grafana-oncall-oss'}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={styles.instructionsLink}
|
||||
>
|
||||
the update instructions
|
||||
</a>
|
||||
.
|
||||
</Alert>
|
||||
)}
|
||||
{showChannelWarnings() && (
|
||||
<Alert
|
||||
onRemove={getRemoveAlertHandler(AlertID.CONNECTIVITY_WARNING)}
|
||||
|
|
@ -169,16 +141,6 @@ export const Alerts = observer(() => {
|
|||
return Boolean(currentOrganization?.banner?.title) && !getItem(currentOrganization?.banner?.title);
|
||||
}
|
||||
|
||||
function showMismatchWarning(): boolean {
|
||||
return (
|
||||
store.isOpenSource &&
|
||||
store.backendVersion &&
|
||||
plugin?.version &&
|
||||
store.backendVersion !== plugin?.version &&
|
||||
!getItem(versionMismatchLocalStorageId)
|
||||
);
|
||||
}
|
||||
|
||||
function showChannelWarnings(): boolean {
|
||||
return Boolean(
|
||||
currentOrganization &&
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ export const IntegrationTemplate = observer((props: IntegrationTemplateProps) =>
|
|||
return (
|
||||
<Drawer
|
||||
title={
|
||||
<div>
|
||||
<div className={styles.titleContainer}>
|
||||
<Stack justifyContent="space-between" alignItems="flex-start">
|
||||
<Stack direction="column">
|
||||
<Text.Title level={3}>Edit {template.displayName} template</Text.Title>
|
||||
|
|
@ -188,7 +188,8 @@ export const IntegrationTemplate = observer((props: IntegrationTemplateProps) =>
|
|||
closeOnMaskClick={false}
|
||||
width={'95%'}
|
||||
>
|
||||
<div>
|
||||
<div className={styles.containerWrapper}>
|
||||
<div className={styles.container}>
|
||||
<TemplatesAlertGroupsList
|
||||
templatePage={TemplatePage.Integrations}
|
||||
alertReceiveChannelId={id}
|
||||
|
|
@ -209,6 +210,7 @@ export const IntegrationTemplate = observer((props: IntegrationTemplateProps) =>
|
|||
onSaveAndFollowLink={onSaveAndFollowLink}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|||
import { css, cx } from '@emotion/css';
|
||||
import { Button, Icon, LoadingPlaceholder, Stack, useStyles2 } from '@grafana/ui';
|
||||
import { UserActions } from 'helpers/authorization/authorization';
|
||||
import { StackSize } from 'helpers/consts';
|
||||
import { IS_CURRENT_ENV_CLOUD, StackSize } from 'helpers/consts';
|
||||
import { isMobile, openNotification, openWarningNotification, openErrorNotification } from 'helpers/helpers';
|
||||
import { useInitializePlugin } from 'helpers/hooks';
|
||||
import { observer } from 'mobx-react';
|
||||
|
|
@ -140,7 +140,7 @@ export const MobileAppConnection = observer(({ userPk }: Props) => {
|
|||
|
||||
// Show link to cloud page for OSS instances with no cloud connection
|
||||
if (
|
||||
store.isOpenSource &&
|
||||
!IS_CURRENT_ENV_CLOUD &&
|
||||
store.hasFeature(AppFeature.CloudConnection) &&
|
||||
!cloudStore.cloudConnectionStatus.cloud_connection_status
|
||||
) {
|
||||
|
|
@ -191,7 +191,7 @@ export const MobileAppConnection = observer(({ userPk }: Props) => {
|
|||
<QRCode className={cx({ [styles.qrCode]: true, [styles.blurry]: isQRBlurry })} value={QRCodeValue} />
|
||||
{isQRBlurry && <QRLoading />}
|
||||
</div>
|
||||
{store.isOpenSource && QRCodeDataParsed && (
|
||||
{!IS_CURRENT_ENV_CLOUD && QRCodeDataParsed && (
|
||||
<Text type="secondary">
|
||||
Server URL embedded in this QR:
|
||||
<br />
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export const PersonalNotificationSettings = observer((props: PersonalNotificatio
|
|||
const title = (
|
||||
<Text.Title level={5}>
|
||||
<Stack>
|
||||
{isImportant ? 'Important Notifications' : 'Default Notifications'}
|
||||
{isImportant ? 'Important notification rules' : 'Default notification rules'}
|
||||
<Tooltip
|
||||
placement="top"
|
||||
content={
|
||||
|
|
@ -154,7 +154,7 @@ export const PersonalNotificationSettings = observer((props: PersonalNotificatio
|
|||
<div className={styles.step}>
|
||||
<WithPermissionControlTooltip userAction={userAction}>
|
||||
<Button icon="plus" variant="secondary" fill="text" onClick={getAddNotificationPolicyHandler()}>
|
||||
Add Notification Step
|
||||
Add notification step
|
||||
</Button>
|
||||
</WithPermissionControlTooltip>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,12 @@ import {
|
|||
DEFAULT_PAGE,
|
||||
DOCS_ONCALL_OSS_INSTALL,
|
||||
DOCS_SERVICE_ACCOUNTS,
|
||||
IS_CURRENT_ENV_CLOUD,
|
||||
PLUGIN_CONFIG,
|
||||
PLUGIN_ROOT,
|
||||
REQUEST_HELP_URL,
|
||||
} from 'helpers/consts';
|
||||
import { getIsExternalServiceAccountFeatureAvailable, getIsRunningOpenSourceVersion } from 'helpers/helpers';
|
||||
import { getIsExternalServiceAccountFeatureAvailable } from 'helpers/helpers';
|
||||
import { useOnMount } from 'helpers/hooks';
|
||||
import { validateURL } from 'helpers/string';
|
||||
import { observer } from 'mobx-react';
|
||||
|
|
@ -50,7 +51,7 @@ export const PluginConfigPage = observer((props: PluginConfigPageProps<PluginMet
|
|||
>
|
||||
Configure Grafana OnCall
|
||||
</Text.Title>
|
||||
{getIsRunningOpenSourceVersion() ? <OSSPluginConfigPage {...props} /> : <CloudPluginConfigPage {...props} />}
|
||||
{IS_CURRENT_ENV_CLOUD ? <CloudPluginConfigPage {...props} /> : <OSSPluginConfigPage {...props} />}
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import React, { FC } from 'react';
|
||||
|
||||
import { Button, Stack, LoadingPlaceholder } from '@grafana/ui';
|
||||
import { REQUEST_HELP_URL, PLUGIN_CONFIG } from 'helpers/consts';
|
||||
import { getIsRunningOpenSourceVersion } from 'helpers/helpers';
|
||||
import { REQUEST_HELP_URL, PLUGIN_CONFIG, IS_CURRENT_ENV_CLOUD } from 'helpers/consts';
|
||||
import { useInitializePlugin } from 'helpers/hooks';
|
||||
import { observer } from 'mobx-react';
|
||||
import { useNavigate } from 'react-router-dom-v5-compat';
|
||||
|
|
@ -34,12 +33,11 @@ export const PluginInitializer: FC<PluginInitializerProps> = observer(({ childre
|
|||
});
|
||||
|
||||
const PluginNotConnectedFullPageError = observer(() => {
|
||||
const isOpenSource = getIsRunningOpenSourceVersion();
|
||||
const isCurrentUserAdmin = window.grafanaBootData.user.orgRole === 'Admin';
|
||||
const navigate = useNavigate();
|
||||
|
||||
const getSubtitleExtension = () => {
|
||||
if (!isOpenSource) {
|
||||
if (IS_CURRENT_ENV_CLOUD) {
|
||||
return 'request help from our support team.';
|
||||
}
|
||||
return isCurrentUserAdmin
|
||||
|
|
@ -61,8 +59,8 @@ const PluginNotConnectedFullPageError = observer(() => {
|
|||
<Button variant="secondary" onClick={() => window.location.reload()}>
|
||||
Retry
|
||||
</Button>
|
||||
{!isOpenSource && <Button onClick={() => window.open(REQUEST_HELP_URL, '_blank')}>Request help</Button>}
|
||||
{isOpenSource && isCurrentUserAdmin && (
|
||||
{IS_CURRENT_ENV_CLOUD && <Button onClick={() => window.open(REQUEST_HELP_URL, '_blank')}>Request help</Button>}
|
||||
{!IS_CURRENT_ENV_CLOUD && isCurrentUserAdmin && (
|
||||
<Button onClick={() => navigate(PLUGIN_CONFIG)}>Open configuration</Button>
|
||||
)}
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -9,13 +9,22 @@ export const PluginId = {
|
|||
} as const;
|
||||
export type PluginId = (typeof PluginId)[keyof typeof PluginId];
|
||||
|
||||
export const getIsDevelopmentEnv = () => {
|
||||
// Determine current environment: cloud, oss or local
|
||||
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';
|
||||
}
|
||||
try {
|
||||
return process.env.NODE_ENV === 'development';
|
||||
return process.env.NODE_ENV === 'development' ? 'local' : 'oss';
|
||||
} catch (error) {
|
||||
return false;
|
||||
return 'cloud';
|
||||
}
|
||||
};
|
||||
const CURRENT_ENV = determineCurrentEnv();
|
||||
export const IS_CURRENT_ENV_CLOUD = CURRENT_ENV === 'cloud';
|
||||
export const IS_CURRENT_ENV_OSS = CURRENT_ENV === 'oss';
|
||||
export const IS_CURRENT_ENV_LOCAL = CURRENT_ENV === 'local';
|
||||
|
||||
export const getPluginId = (): PluginId => {
|
||||
try {
|
||||
|
|
@ -28,17 +37,6 @@ export const getPluginId = (): PluginId => {
|
|||
// Navbar
|
||||
export const APP_SUBTITLE = `Developer-friendly incident response (${plugin?.version})`;
|
||||
|
||||
export const APP_VERSION = `${plugin?.version}`;
|
||||
|
||||
export const CLOUD_VERSION_REGEX = new RegExp('^(r[\\d]+-v[\\d]+.[\\d]+.[\\d]+|github-actions-[\\d]+)$');
|
||||
|
||||
// License
|
||||
export const GRAFANA_LICENSE_OSS = 'OpenSource';
|
||||
|
||||
export const GRAFANA_LICENSE_CLOUD = 'Cloud';
|
||||
|
||||
export const FALLBACK_LICENSE = CLOUD_VERSION_REGEX.test(APP_VERSION) ? GRAFANA_LICENSE_CLOUD : GRAFANA_LICENSE_OSS;
|
||||
|
||||
// height of new Grafana sticky header with breadcrumbs
|
||||
export const GRAFANA_HEADER_HEIGHT = 80;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,12 @@ jest.mock('@grafana/faro-web-tracing', () => ({
|
|||
TracingInstrumentation: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('./consts', () => ({
|
||||
__esModule: true,
|
||||
...jest.requireActual('./consts'),
|
||||
IS_CURRENT_ENV_CLOUD: true,
|
||||
}));
|
||||
|
||||
describe('Faro', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ import {
|
|||
FARO_ENDPOINT_DEV,
|
||||
FARO_ENDPOINT_OPS,
|
||||
FARO_ENDPOINT_PROD,
|
||||
IS_CURRENT_ENV_CLOUD,
|
||||
ONCALL_DEV,
|
||||
ONCALL_OPS,
|
||||
ONCALL_PROD,
|
||||
getIsDevelopmentEnv,
|
||||
getPluginId,
|
||||
} from './consts';
|
||||
import { safeJSONStringify } from './string';
|
||||
|
|
@ -33,7 +33,7 @@ class BaseFaroHelper {
|
|||
faro: Faro;
|
||||
|
||||
initializeFaro(onCallApiUrl: string) {
|
||||
if (this.faro || getIsDevelopmentEnv()) {
|
||||
if (this.faro || !IS_CURRENT_ENV_CLOUD) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ import { isArray, concat, every, isEmpty, isObject, isPlainObject, flatMap, map,
|
|||
|
||||
import { isNetworkError } from 'network/network';
|
||||
|
||||
import { CLOUD_VERSION_REGEX, getPluginId } from './consts';
|
||||
|
||||
export class KeyValuePair<T = string | number> {
|
||||
key: T;
|
||||
value: string;
|
||||
|
|
@ -153,8 +151,6 @@ export const isCurrentGrafanaVersionEqualOrGreaterThan = ({
|
|||
);
|
||||
};
|
||||
|
||||
export const getIsRunningOpenSourceVersion = () => !CLOUD_VERSION_REGEX.test(config.apps[getPluginId()]?.version);
|
||||
|
||||
export const getIsExternalServiceAccountFeatureAvailable = () =>
|
||||
isCurrentGrafanaVersionEqualOrGreaterThan({ minMajor: 10, minMinor: 3 }) &&
|
||||
config.featureToggles.externalServiceAccounts;
|
||||
|
|
|
|||
|
|
@ -2,19 +2,17 @@ import React from 'react';
|
|||
|
||||
import { cx } from '@emotion/css';
|
||||
import { Card, Stack, useStyles2 } from '@grafana/ui';
|
||||
import { APP_SUBTITLE } from 'helpers/consts';
|
||||
import { APP_SUBTITLE, IS_CURRENT_ENV_OSS } from 'helpers/consts';
|
||||
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 { useStore } from 'state/useStore';
|
||||
|
||||
import { getHeaderStyles } from './Header.styles';
|
||||
|
||||
export const Header = observer(() => {
|
||||
const store = useStore();
|
||||
const styles = useStyles2(getHeaderStyles);
|
||||
|
||||
return (
|
||||
|
|
@ -34,7 +32,7 @@ export const Header = observer(() => {
|
|||
);
|
||||
|
||||
function renderHeading() {
|
||||
if (store.isOpenSource) {
|
||||
if (IS_CURRENT_ENV_OSS) {
|
||||
return (
|
||||
<div className={cx('heading')}>
|
||||
<h1 className={styles.pageHeaderTitle}>Grafana OnCall</h1>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import {
|
|||
useSceneApp,
|
||||
} from '@grafana/scenes';
|
||||
import { Alert, LoadingPlaceholder, Stack, useStyles2 } from '@grafana/ui';
|
||||
import { DOCS_ROOT, StackSize, PLUGIN_ROOT } from 'helpers/consts';
|
||||
import { DOCS_ROOT, StackSize, PLUGIN_ROOT, IS_CURRENT_ENV_OSS } from 'helpers/consts';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import { Text } from 'components/Text/Text';
|
||||
|
|
@ -40,7 +40,6 @@ import getVariables from './variables';
|
|||
|
||||
export const Insights = observer(() => {
|
||||
const {
|
||||
isOpenSource,
|
||||
insightsDatasource,
|
||||
organizationStore: { currentOrganization },
|
||||
} = useStore();
|
||||
|
|
@ -49,11 +48,11 @@ export const Insights = observer(() => {
|
|||
|
||||
const config = useMemo(
|
||||
() => ({
|
||||
isOpenSource,
|
||||
datasource: { uid: isOpenSource ? '$datasource' : insightsDatasource },
|
||||
isOpenSource: IS_CURRENT_ENV_OSS,
|
||||
datasource: { uid: IS_CURRENT_ENV_OSS ? '$datasource' : insightsDatasource },
|
||||
stack: currentOrganization?.stack_slug,
|
||||
}),
|
||||
[isOpenSource, currentOrganization?.stack_slug]
|
||||
[currentOrganization?.stack_slug]
|
||||
);
|
||||
|
||||
const variables = useMemo(() => getVariables(config), [config]);
|
||||
|
|
@ -69,7 +68,7 @@ export const Insights = observer(() => {
|
|||
return undefined;
|
||||
}
|
||||
const dataSourceListener =
|
||||
isOpenSource &&
|
||||
IS_CURRENT_ENV_OSS &&
|
||||
variables.datasource.subscribeToState(({ text }) => {
|
||||
setDatasource(`${text}`);
|
||||
});
|
||||
|
|
@ -86,7 +85,7 @@ export const Insights = observer(() => {
|
|||
<InsightsGeneralInfo />
|
||||
{isAnyAlertCreatedMoreThan20SecsAgo ? (
|
||||
<>
|
||||
{isOpenSource && !datasource && <NoDatasourceWarning />}
|
||||
{IS_CURRENT_ENV_OSS && !datasource && <NoDatasourceWarning />}
|
||||
<appScene.Component model={appScene} />
|
||||
</>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { css } from '@emotion/css';
|
|||
import { AppRootProps, GrafanaTheme2 } from '@grafana/data';
|
||||
import { Alert, Icon, Stack, Themeable2, withTheme2 } from '@grafana/ui';
|
||||
import { LocationHelper } from 'helpers/LocationHelper';
|
||||
import { IS_CURRENT_ENV_OSS } from 'helpers/consts';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import { VerticalTabsBar, VerticalTab } from 'components/VerticalTabsBar/VerticalTabsBar';
|
||||
|
|
@ -46,10 +47,10 @@ export class _ChatOpsPage extends React.Component<ChatOpsProps, ChatOpsState> {
|
|||
|
||||
render() {
|
||||
const { activeTab } = this.state;
|
||||
const { store, theme } = this.props;
|
||||
const { theme } = this.props;
|
||||
const styles = getStyles(theme);
|
||||
|
||||
if (!this.isChatOpsConfigured() && store.isOpenSource) {
|
||||
if (!this.isChatOpsConfigured() && IS_CURRENT_ENV_OSS) {
|
||||
return this.renderNoChatOpsBannerInfo();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -352,11 +352,11 @@ class Users extends React.Component<UsersProps, UsersState> {
|
|||
|
||||
// Show warnining if no notifications are set
|
||||
if (!this.renderNotificationsChain(user)) {
|
||||
warnings.push('No Default Notifications');
|
||||
warnings.push('No default notification rules');
|
||||
}
|
||||
|
||||
if (!this.renderImportantNotificationsChain(user)) {
|
||||
warnings.push('No Important Notifications');
|
||||
warnings.push('No important notification rules');
|
||||
}
|
||||
|
||||
let phone_verified = user.verified_phone_number !== null;
|
||||
|
|
@ -428,13 +428,13 @@ class Users extends React.Component<UsersProps, UsersState> {
|
|||
},
|
||||
{
|
||||
width: '20%',
|
||||
title: 'Default Notifications',
|
||||
title: 'Default notification rules',
|
||||
key: 'notifications-chain',
|
||||
render: this.renderNotificationsChain,
|
||||
},
|
||||
{
|
||||
width: '20%',
|
||||
title: 'Important Notifications',
|
||||
title: 'Important notification rules',
|
||||
key: 'important-notifications-chain',
|
||||
render: this.renderImportantNotificationsChain,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { OnCallAppPluginMeta } from 'app-types';
|
||||
import { retryFailingPromises } from 'helpers/async';
|
||||
import { APP_VERSION, CLOUD_VERSION_REGEX, GRAFANA_LICENSE_CLOUD, GRAFANA_LICENSE_OSS } from 'helpers/consts';
|
||||
import { loadJs } from 'helpers/loadJs';
|
||||
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
|
||||
import { action, makeObservable, observable, runInAction } from 'mobx';
|
||||
import qs from 'query-string';
|
||||
|
||||
import { AlertReceiveChannelStore } from 'models/alert_receive_channel/alert_receive_channel';
|
||||
|
|
@ -43,12 +42,6 @@ export class RootBaseStore {
|
|||
@observable
|
||||
isBasicDataLoaded = false;
|
||||
|
||||
@observable
|
||||
backendVersion = '';
|
||||
|
||||
@observable
|
||||
backendLicense = '';
|
||||
|
||||
@observable
|
||||
recaptchaSiteKey = '';
|
||||
|
||||
|
|
@ -148,21 +141,6 @@ export class RootBaseStore {
|
|||
// todo use AppFeature only
|
||||
hasFeature = (feature: string | AppFeature) => this.features?.[feature];
|
||||
|
||||
get license() {
|
||||
if (this.backendLicense) {
|
||||
return this.backendLicense;
|
||||
}
|
||||
if (CLOUD_VERSION_REGEX.test(APP_VERSION)) {
|
||||
return GRAFANA_LICENSE_CLOUD;
|
||||
}
|
||||
return GRAFANA_LICENSE_OSS;
|
||||
}
|
||||
|
||||
@computed
|
||||
get isOpenSource(): boolean {
|
||||
return this.license === GRAFANA_LICENSE_OSS;
|
||||
}
|
||||
|
||||
@action.bound
|
||||
async updateFeatures() {
|
||||
const response = await makeRequest('/features/', {});
|
||||
|
|
|
|||
5
grafana-plugin/src/version.ts
Normal file
5
grafana-plugin/src/version.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// NOTE: This file is replaced by the release script, so do not expect it to be as it is always.
|
||||
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
|
||||
Loading…
Add table
Reference in a new issue