Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.9.21 #4979

Merged
merged 4 commits into from
Sep 4, 2024
Merged

v1.9.21 #4979

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/actions/build-sign-and-package-plugin/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ runs:
GRAFANA_ACCESS_POLICY_TOKEN: ${{ inputs.grafana_access_policy_token }}
run: |
jq --arg v "${{ inputs.plugin_version_number }}" '.version=$v' package.json > package.new && mv package.new package.json && jq '.version' package.json;
yarn build
pnpm build
mage buildAll || true
yarn sign
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
Expand Down
42 changes: 11 additions & 31 deletions .github/actions/install-frontend-dependencies/action.yml
Original file line number Diff line number Diff line change
@@ -1,38 +1,18 @@
name: "Install frontend dependencies"
description: "Setup node + install frontend dependencies"
inputs:
working-directory:
description: "Relative path to oncall/grafana-plugin directory"
required: false
default: "."
name: Install frontend dependencies
description: Setup node/pnpm + install frontend dependencies
runs:
using: "composite"
using: composite
steps:
- name: Determine grafana-plugin directory location
id: grafana-plugin-directory
shell: bash
run: echo "grafana-plugin-directory=${{ inputs.working-directory }}/grafana-plugin" >> $GITHUB_OUTPUT
- name: Determine yarn.lock location
id: yarn-lock-location
shell: bash
# yamllint disable rule:line-length
run: echo "yarn-lock-location=${{ steps.grafana-plugin-directory.outputs.grafana-plugin-directory }}/yarn.lock" >> $GITHUB_OUTPUT
# yamllint enable rule:line-length
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 9.1.4
- uses: actions/setup-node@v4
with:
node-version: 20.15.1
cache: "yarn"
cache-dependency-path: ${{ steps.yarn-lock-location.outputs.yarn-lock-location }}
- name: Use cached frontend dependencies
id: cache-frontend-dependencies
uses: actions/cache@v4
with:
path: ${{ inputs.working-directory }}/grafana-plugin/node_modules
# yamllint disable rule:line-length
key: ${{ runner.os }}-frontend-node-modules-${{ hashFiles(steps.yarn-lock-location.outputs.yarn-lock-location) }}
# yamllint enable rule:line-length
cache: pnpm
cache-dependency-path: grafana-plugin/pnpm-lock.yaml
- name: Install frontend dependencies
if: steps.cache-frontend-dependencies.outputs.cache-hit != 'true'
shell: bash
working-directory: ${{ steps.grafana-plugin-directory.outputs.grafana-plugin-directory }}
run: yarn install --frozen-lockfile --prefer-offline --network-timeout 500000
working-directory: grafana-plugin
run: pnpm install --frozen-lockfile --prefer-offline
8 changes: 4 additions & 4 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ jobs:
uses: actions/cache@v4
with:
path: grafana-plugin/dist
key: ${{ runner.os }}-plugin-frontend-${{ hashFiles('grafana-plugin/src/**/*', 'grafana-plugin/yarn.lock') }}
key: ${{ runner.os }}-plugin-frontend-${{ hashFiles('grafana-plugin/src/**/*', 'grafana-plugin/pnpm.lock') }}

- name: Build plugin frontend
if: steps.cache-plugin-frontend.outputs.cache-hit != 'true'
working-directory: grafana-plugin
run: yarn build:dev
run: pnpm build:dev

# helpful reference for properly caching the playwright binaries/dependencies
# https://playwrightsolutions.com/playwright-github-action-to-cache-the-browser-binaries/
Expand All @@ -107,7 +107,7 @@ jobs:
- name: Install Playwright deps
shell: bash
working-directory: grafana-plugin
run: yarn playwright install
run: pnpm playwright install

# ---------- Expensive e2e tests steps start -----------
- name: Install Go
Expand Down Expand Up @@ -150,7 +150,7 @@ jobs:
if: inputs.run-expensive-tests
shell: bash
env:
E2E_TESTS_CMD: "cd ../../grafana-plugin && yarn test:e2e-expensive"
E2E_TESTS_CMD: "cd ../../grafana-plugin && pnpm test:e2e-expensive"
GRAFANA_VERSION: ${{ inputs.grafana_version }}
GF_FEATURE_TOGGLES_ENABLE: "externalServiceAccounts"
ONCALL_API_URL: "http://oncall-dev-engine:8080"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/linting-and-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
uses: ./.github/actions/install-frontend-dependencies
- name: Build, lint and test frontend
working-directory: grafana-plugin
run: yarn lint && yarn type-check && yarn test && yarn build
run: pnpm lint && pnpm type-check && pnpm test && pnpm build

test-technical-documentation:
name: "Test technical documentation"
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/on-release-published.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ jobs:
repo_secrets: |
GRAFANA_ACCESS_POLICY_TOKEN=github_actions:cloud-access-policy-token
GCS_PLUGIN_PUBLISHER_SERVICE_ACCOUNT_JSON=github_actions:gcs-plugin-publisher
GCOM_PLUGIN_PUBLISHER_API_KEY=github_actions:gcom-plugin-publisher-api-key
- name: Build, sign, and package plugin
id: build-sign-and-package-plugin
uses: ./.github/actions/build-sign-and-package-plugin
Expand All @@ -64,7 +63,7 @@ jobs:
echo url="https://storage.googleapis.com/grafana-oncall-app/releases/grafana-oncall-app-${{ github.ref_name }}.zip" >> $GITHUB_OUTPUT
- name: Publish plugin to grafana.com
run: |
curl -f -w "status=%{http_code}" -s -H "Authorization: Bearer ${{ env.GCOM_PLUGIN_PUBLISHER_API_KEY }}" -d "download[any][url]=${{ steps.gcs-artifact-url.outputs.url }}" -d "download[any][md5]=$(curl -sL ${{ steps.gcs-artifact-url.outputs.url }} | md5sum | cut -d'' '' -f1)" -d url=https://github.com/grafana/oncall/grafana-plugin https://grafana.com/api/plugins
curl -f -w "status=%{http_code}" -s -H "Authorization: Bearer ${{ env.GRAFANA_ACCESS_POLICY_TOKEN }}" -d "download[any][url]=${{ steps.gcs-artifact-url.outputs.url }}" -d "download[any][md5]=$(curl -sL ${{ steps.gcs-artifact-url.outputs.url }} | md5sum | cut -d'' '' -f1)" -d url=https://github.com/grafana/oncall/grafana-plugin https://grafana.com/api/plugins
# yamllint enable rule:line-length

build-engine-docker-image-and-publish-to-dockerhub:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ venv
.DS_Store
.env

yarn.lock
pnpm.lock
node_modules

test-results
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ repos:
rev: v8.25.0
hooks:
- id: eslint
entry: bash -c "cd grafana-plugin && eslint --max-warnings=0 --fix ${@/grafana-plugin\//}" --
entry: bash -c "cd grafana-plugin && eslint --max-warnings=20 --fix ${@/grafana-plugin\//}" --
types: [file]
files: ^grafana-plugin/src/(?:(?!autogenerated).)*\.(js|jsx|ts|tsx)$
additional_dependencies:
Expand Down
6 changes: 3 additions & 3 deletions .tilt/plugin/Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ if is_ci:
"build-ui",
labels=[label],
dir=grafana_plugin_dir,
cmd="yarn build",
cmd="pnpm build",
allow_parallel=True,
)

Expand All @@ -19,9 +19,9 @@ if not is_ci:
"build-ui",
labels=[label],
dir=grafana_plugin_dir,
cmd="yarn install",
cmd="pnpm install",
serve_dir=grafana_plugin_dir,
serve_cmd="yarn watch",
serve_cmd="pnpm watch",
allow_parallel=True,
)

Expand Down
8 changes: 4 additions & 4 deletions .tilt/tests/Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ label = "OnCall.AllTests"

load('ext://uibutton', 'cmd_button', 'location', 'text_input', 'bool_input')

e2e_tests_cmd=os.getenv("E2E_TESTS_CMD", "cd ../../grafana-plugin && yarn test:e2e")
e2e_tests_cmd=os.getenv("E2E_TESTS_CMD", "cd ../../grafana-plugin && pnpm test:e2e")
is_ci=config.tilt_subcommand == "ci"

local_resource(
Expand All @@ -16,7 +16,7 @@ local_resource(

cmd_button(
name="E2E Tests - headless run",
argv=["sh", "-c", "yarn --cwd ./grafana-plugin test:e2e $STOP_ON_FIRST_FAILURE $TESTS_FILTER"],
argv=["sh", "-c", "pnpm --dir ./grafana-plugin test:e2e $STOP_ON_FIRST_FAILURE $TESTS_FILTER"],
text="Restart headless run",
resource="e2e-tests",
icon_name="replay",
Expand All @@ -29,15 +29,15 @@ cmd_button(

cmd_button(
name="E2E Tests - open watch mode",
argv=["sh", "-c", "yarn --cwd grafana-plugin test:e2e:watch"],
argv=["sh", "-c", "pnpm --dir grafana-plugin test:e2e:watch"],
text="Open watch mode",
resource="e2e-tests",
icon_name="visibility",
)

cmd_button(
name="E2E Tests - show report",
argv=["sh", "-c", "yarn --cwd grafana-plugin playwright show-report"],
argv=["sh", "-c", "pnpm --dir grafana-plugin playwright show-report"],
text="Show last HTML report",
resource="e2e-tests",
icon_name="assignment",
Expand Down
1 change: 1 addition & 0 deletions .yamllint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ extends: default

ignore: |
helm/oncall/templates/**/*.yaml
pnpm-lock.yaml

rules:
line-length:
Expand Down
18 changes: 9 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ init: ## build the frontend plugin code then run make start
# this makes sure that it will be available when the grafana container starts up without the need to
# restart the grafana container initially
ifeq ($(findstring $(UI_PROFILE),$(COMPOSE_PROFILES)),$(UI_PROFILE))
$(call run_ui_docker_command,yarn install && yarn build:dev)
$(call run_ui_docker_command,pnpm install && pnpm build:dev)
endif

stop: # stop all of the docker containers
Expand All @@ -168,7 +168,7 @@ install-pre-commit:
fi

lint: install-pre-commit ## run both frontend and backend linters
## may need to run `yarn install` from within `grafana-plugin`
## may need to run `pnpm install` from within `grafana-plugin`
## to install several `pre-commit` dependencies
pre-commit run --all-files

Expand Down Expand Up @@ -203,25 +203,25 @@ engine-manage: ## run Django's `manage.py` script, inside of a docker container
$(call run_engine_docker_command,python manage.py $(CMD))

test-e2e: ## run the e2e tests in headless mode
yarn --cwd grafana-plugin test:e2e
pnpm --dir grafana-plugin test:e2e

test-e2e-watch: ## start e2e tests in watch mode
yarn --cwd grafana-plugin test:e2e:watch
pnpm --dir grafana-plugin test:e2e:watch

test-e2e-show-report: ## open last e2e test report
yarn --cwd grafana-plugin playwright show-report
pnpm --dir grafana-plugin playwright show-report

ui-test: ## run the UI tests
$(call run_ui_docker_command,yarn test)
$(call run_ui_docker_command,pnpm test)

ui-lint: ## run the UI linter
$(call run_ui_docker_command,yarn lint)
$(call run_ui_docker_command,pnpm lint)

ui-build: ## build the UI
$(call run_ui_docker_command,yarn build)
$(call run_ui_docker_command,pnpm build)

ui-command: ## run any command, inside of a UI docker container, passing `$CMD` as arguments.
## e.g. `make ui-command CMD="yarn test"`
## e.g. `make ui-command CMD="pnpm test"`
$(call run_ui_docker_command,$(CMD))

exec-engine: ## exec into engine container's bash
Expand Down
4 changes: 2 additions & 2 deletions dev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Related: [How to develop integrations](/engine/config_integrations/README.md)
- [tilt-dev/ctlptl: Making local Kubernetes clusters fun and easy to set up](https://github.com/tilt-dev/ctlptl)
- [Kind](https://kind.sigs.k8s.io)
- [Node.js v20.x](https://nodejs.org/en/download)
- [Yarn](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable)
- [pnpm](https://pnpm.io/installation)

### Launch the environment

Expand Down Expand Up @@ -519,7 +519,7 @@ In order to automate types creation and prevent API usage pitfalls, OnCall proje

### Instruction

1. Whenever API contract changes, run `yarn generate-types` from `grafana-plugin` directory
1. Whenever API contract changes, run `pnpm generate-types` from `grafana-plugin` directory
2. Then you can start consuming types and you can use fully typed http client:

```ts
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.15 on 2024-09-02 13:34

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('alerts', '0057_remove_alertgroup_slack_log_message_db'),
]

operations = [
migrations.AlterField(
model_name='alertgroup',
name='reason_to_skip_escalation',
field=models.IntegerField(choices=[(0, 'account_inactive'), (1, 'is_archived'), (2, 'no_reason'), (3, 'rate_limited'), (4, 'channel_not_specified'), (5, 'restricted_action'), (6, 'invalid_auth')], default=2),
),
]
13 changes: 11 additions & 2 deletions engine/apps/alerts/models/alert_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,14 +365,23 @@ def status(self) -> int:
else:
return AlertGroup.NEW

ACCOUNT_INACTIVE, CHANNEL_ARCHIVED, NO_REASON, RATE_LIMITED, CHANNEL_NOT_SPECIFIED, RESTRICTED_ACTION = range(6)
(
ACCOUNT_INACTIVE,
CHANNEL_ARCHIVED,
NO_REASON,
RATE_LIMITED,
CHANNEL_NOT_SPECIFIED,
RESTRICTED_ACTION,
INVALID_AUTH,
) = range(7)
REASONS_TO_SKIP_ESCALATIONS = (
(ACCOUNT_INACTIVE, "account_inactive"),
(CHANNEL_ARCHIVED, "channel_archived"),
(CHANNEL_ARCHIVED, "is_archived"),
(NO_REASON, "no_reason"),
(RATE_LIMITED, "rate_limited"),
(CHANNEL_NOT_SPECIFIED, "channel_not_specified"),
(RESTRICTED_ACTION, "restricted_action"),
(INVALID_AUTH, "invalid_auth"),
)
reason_to_skip_escalation = models.IntegerField(choices=REASONS_TO_SKIP_ESCALATIONS, default=NO_REASON)

Expand Down
4 changes: 2 additions & 2 deletions engine/apps/grafana_plugin/serializers/sync_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ def to_representation(self, instance):
class SyncTeamSerializer(serializers.Serializer):
team_id = serializers.IntegerField()
name = serializers.CharField()
email = serializers.EmailField(allow_blank=True)
avatar_url = serializers.CharField()
email = serializers.CharField(allow_blank=True)
avatar_url = serializers.CharField(allow_blank=True)

def create(self, validated_data):
return SyncTeam(**validated_data)
Expand Down
23 changes: 23 additions & 0 deletions engine/apps/grafana_plugin/tests/test_sync_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import pytest
from django.urls import reverse
from rest_framework import status
from rest_framework.exceptions import ValidationError
from rest_framework.test import APIClient

from apps.api.permissions import LegacyAccessControlRole
from apps.grafana_plugin.serializers.sync_data import SyncTeamSerializer
from apps.grafana_plugin.sync_data import SyncData, SyncSettings, SyncUser
from apps.grafana_plugin.tasks.sync_v2 import start_sync_organizations_v2

Expand Down Expand Up @@ -136,3 +138,24 @@ def test_sync_v2_content_encoding(

assert response.status_code == status.HTTP_200_OK
mock_sync.assert_called()


@pytest.mark.parametrize(
"test_team, validation_pass",
[
({"team_id": 1, "name": "Test Team", "email": "", "avatar_url": ""}, True),
({"team_id": 1, "name": "", "email": "", "avatar_url": ""}, False),
({"name": "ABC", "email": "", "avatar_url": ""}, False),
({"team_id": 1, "name": "ABC", "email": "[email protected]", "avatar_url": ""}, True),
({"team_id": 1, "name": "123", "email": "<invalid email>", "avatar_url": ""}, True),
],
)
@pytest.mark.django_db
def test_sync_team_serialization(test_team, validation_pass):
serializer = SyncTeamSerializer(data=test_team)
validation_error = None
try:
serializer.is_valid(raise_exception=True)
except ValidationError as e:
validation_error = e
assert (validation_error is None) == validation_pass
5 changes: 5 additions & 0 deletions engine/apps/slack/scenarios/distribute_alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
SlackAPIChannelArchivedError,
SlackAPIChannelNotFoundError,
SlackAPIError,
SlackAPIInvalidAuthError,
SlackAPIMessageNotFoundError,
SlackAPIRatelimitError,
SlackAPIRestrictedActionError,
Expand Down Expand Up @@ -161,6 +162,10 @@ def _post_alert_group_to_slack(
alert_group.reason_to_skip_escalation = AlertGroup.ACCOUNT_INACTIVE
alert_group.save(update_fields=["reason_to_skip_escalation"])
logger.info("Not delivering alert due to account_inactive.")
except SlackAPIInvalidAuthError:
alert_group.reason_to_skip_escalation = AlertGroup.INVALID_AUTH
alert_group.save(update_fields=["reason_to_skip_escalation"])
logger.info("Not delivering alert due to invalid_auth.")
except SlackAPIChannelArchivedError:
alert_group.reason_to_skip_escalation = AlertGroup.CHANNEL_ARCHIVED
alert_group.save(update_fields=["reason_to_skip_escalation"])
Expand Down
Loading
Loading