Skip to content

Commit

Permalink
v1.9.27
Browse files Browse the repository at this point in the history
  • Loading branch information
joeyorlando authored Sep 23, 2024
2 parents d82ca01 + e882e97 commit 1f3edd6
Show file tree
Hide file tree
Showing 28 changed files with 303 additions and 178 deletions.
42 changes: 24 additions & 18 deletions .github/actions/build-sign-and-package-plugin/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,35 @@ 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"
value: ${{ steps.artifact-filename.outputs.filename }}
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:
Expand All @@ -36,16 +40,18 @@ runs:
run: go install github.com/magefile/[email protected]
- 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 changes: 0 additions & 3 deletions .github/workflows/on-release-published.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
28 changes: 14 additions & 14 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
- [email protected]
- id: prettier
name: prettier - json
types_or: [json]
additional_dependencies:
- [email protected]
# - 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:
# - [email protected]
# - id: prettier
# name: prettier - json
# types_or: [json]
# additional_dependencies:
# - [email protected]

- repo: https://github.com/thibaudcolas/pre-commit-stylelint
rev: v13.13.1
Expand Down
32 changes: 32 additions & 0 deletions docs/sources/oncall-api-reference/alertgroups.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,38 @@ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/unresolve" \

`POST {{API_URL}}/api/v1/alert_groups/<ALERT_GROUP_ID>/unresolve`

## Silence an alert group

```shell
curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/silence" \
--request POST \
--header "Authorization: meowmeowmeow" \
--header "Content-Type: application/json" \
--data '{
"delay": 10800
}'
```

**HTTP request**

`POST {{API_URL}}/api/v1/alert_groups/<ALERT_GROUP_ID>/silence`

| Parameter | Required | Description |
|-----------|:--------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `delay` | Yes | The duration of silence in seconds, `-1` for silencing the alert forever |

## Unsilence an alert group

```shell
curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/unsilence" \
--request POST \
--header "Authorization: meowmeowmeow"
```

**HTTP request**

`POST {{API_URL}}/api/v1/alert_groups/<ALERT_GROUP_ID>/unsilence`

## Delete an alert group

```shell
Expand Down
95 changes: 95 additions & 0 deletions engine/apps/public_api/tests/test_alert_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,3 +635,98 @@ def test_alert_group_unresolve(
alert_group.refresh_from_db()
assert alert_group.resolved is False
assert alert_group.log_records.last().action_source == ActionSource.API


@pytest.mark.parametrize(
"acknowledged,resolved,attached,status_code,data,response_msg",
[
(False, False, False, status.HTTP_200_OK, {"delay": 60}, None),
(False, False, False, status.HTTP_400_BAD_REQUEST, {"delay": -2}, "invalid delay value"),
(False, False, False, status.HTTP_400_BAD_REQUEST, {"delay": "fuzz"}, "invalid delay value"),
(False, False, False, status.HTTP_400_BAD_REQUEST, {}, "delay is required"),
(True, False, False, status.HTTP_400_BAD_REQUEST, {"delay": 60}, "Can't silence an acknowledged alert group"),
(False, True, False, status.HTTP_400_BAD_REQUEST, {"delay": 60}, "Can't silence a resolved alert group"),
(False, False, True, status.HTTP_400_BAD_REQUEST, {"delay": 60}, "Can't silence an attached alert group"),
],
)
@pytest.mark.django_db
def test_alert_group_silence(
make_organization_and_user_with_token,
make_alert_receive_channel,
make_alert_group,
acknowledged,
resolved,
attached,
status_code,
data,
response_msg,
):
organization, _, token = make_organization_and_user_with_token()
alert_receive_channel = make_alert_receive_channel(organization)
root_alert_group = make_alert_group(alert_receive_channel)
alert_group = make_alert_group(
alert_receive_channel,
acknowledged=acknowledged,
resolved=resolved,
root_alert_group=root_alert_group if attached else None,
)

client = APIClient()
url = reverse("api-public:alert_groups-silence", kwargs={"pk": alert_group.public_primary_key})
response = client.post(url, data=data, HTTP_AUTHORIZATION=token)

if status_code == status.HTTP_200_OK:
alert_group.refresh_from_db()
assert alert_group.silenced is True
assert alert_group.log_records.last().action_source == ActionSource.API
else:
assert alert_group.silenced is False
assert response.status_code == status_code
assert response_msg == response.json()["detail"]


@pytest.mark.parametrize(
"silenced,resolved,acknowledged,attached,status_code,response_msg",
[
(True, False, False, False, status.HTTP_200_OK, None),
(False, False, False, False, status.HTTP_400_BAD_REQUEST, "Can't unsilence an unsilenced alert group"),
(True, True, False, False, status.HTTP_400_BAD_REQUEST, "Can't unsilence a resolved alert group"),
(True, False, True, False, status.HTTP_400_BAD_REQUEST, "Can't unsilence an acknowledged alert group"),
(True, False, False, True, status.HTTP_400_BAD_REQUEST, "Can't unsilence an attached alert group"),
],
)
@pytest.mark.django_db
def test_alert_group_unsilence(
make_organization_and_user_with_token,
make_alert_receive_channel,
make_alert_group,
silenced,
resolved,
acknowledged,
attached,
status_code,
response_msg,
):
organization, _, token = make_organization_and_user_with_token()
alert_receive_channel = make_alert_receive_channel(organization)
root_alert_group = make_alert_group(alert_receive_channel)
alert_group = make_alert_group(
alert_receive_channel,
acknowledged=acknowledged,
resolved=resolved,
silenced=silenced,
root_alert_group=root_alert_group if attached else None,
)

client = APIClient()
url = reverse("api-public:alert_groups-unsilence", kwargs={"pk": alert_group.public_primary_key})
response = client.post(url, HTTP_AUTHORIZATION=token)

if status_code == status.HTTP_200_OK:
alert_group.refresh_from_db()
assert alert_group.silenced is False
assert alert_group.log_records.last().action_source == ActionSource.API
else:
assert alert_group.silenced == silenced
assert response.status_code == status_code
assert response_msg == response.json()["detail"]
46 changes: 46 additions & 0 deletions engine/apps/public_api/views/alert_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,49 @@ def unresolve(self, request, pk):

alert_group.un_resolve_by_user_or_backsync(self.request.user, action_source=ActionSource.API)
return Response(status=status.HTTP_200_OK)

@action(methods=["post"], detail=True)
def silence(self, request, pk=None):
alert_group = self.get_object()

delay = request.data.get("delay")
if delay is None:
raise BadRequest(detail="delay is required")
try:
delay = int(delay)
except ValueError:
raise BadRequest(detail="invalid delay value")
if delay < -1:
raise BadRequest(detail="invalid delay value")

if alert_group.resolved:
raise BadRequest(detail="Can't silence a resolved alert group")

if alert_group.acknowledged:
raise BadRequest(detail="Can't silence an acknowledged alert group")

if alert_group.root_alert_group is not None:
raise BadRequest(detail="Can't silence an attached alert group")

alert_group.silence_by_user_or_backsync(request.user, silence_delay=delay, action_source=ActionSource.API)
return Response(status=status.HTTP_200_OK)

@action(methods=["post"], detail=True)
def unsilence(self, request, pk=None):
alert_group = self.get_object()

if not alert_group.silenced:
raise BadRequest(detail="Can't unsilence an unsilenced alert group")

if alert_group.resolved:
raise BadRequest(detail="Can't unsilence a resolved alert group")

if alert_group.acknowledged:
raise BadRequest(detail="Can't unsilence an acknowledged alert group")

if alert_group.root_alert_group is not None:
raise BadRequest(detail="Can't unsilence an attached alert group")

alert_group.un_silence_by_user_or_backsync(request.user, action_source=ActionSource.API)

return Response(status=status.HTTP_200_OK)
8 changes: 7 additions & 1 deletion grafana-plugin/e2e-tests/schedules/addOverride.test.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion grafana-plugin/e2e-tests/schedules/timezones.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion grafana-plugin/e2e-tests/utils/userSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
7 changes: 3 additions & 4 deletions grafana-plugin/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -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",
Expand Down
4 changes: 2 additions & 2 deletions grafana-plugin/pkg/plugin/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
Loading

0 comments on commit 1f3edd6

Please sign in to comment.