Skip to content

Commit 5d00be2

Browse files
authored
Merge branch 'main' into hmg/tag
2 parents 8c758a1 + 75493f8 commit 5d00be2

File tree

35 files changed

+1504
-212
lines changed

35 files changed

+1504
-212
lines changed

.github/workflows/test-pr-integrations.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ on:
55
- main
66
paths:
77
- "keep/**"
8+
- "tests/**"
89
pull_request:
910
paths:
1011
- "keep/**"
12+
- "tests/**"
1113
workflow_dispatch:
1214

1315
permissions:

.github/workflows/test-pr-ut.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ on:
55
- main
66
paths:
77
- "keep/**"
8+
- "tests/**"
89
pull_request:
910
paths:
1011
- "keep/**"
12+
- "tests/**"
1113
workflow_dispatch:
1214

1315
permissions:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ scripts/keep_slack_bot.py
218218
providers_cache.json
219219

220220
tests/provision/*
221+
!tests/provision/workflows*
221222
grafana/*
222223
!grafana/provisioning/
223224
!grafana/dashboards/

docs/providers/documentation/teams-provider.mdx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ When using Adaptive Cards (`typeCard="message"`):
8383
- `themeColor` is ignored for Adaptive Cards
8484
- If no sections are provided, the message will be displayed as a simple text block
8585
- Both `sections` and `attachments` can be provided as JSON strings or arrays
86+
- You can mention users in your Adaptive Cards using the `mentions` parameter
8687

8788
### Workflow Example
8889

@@ -112,8 +113,12 @@ actions:
112113
message: ""
113114
sections: '[{"type": "TextBlock", "text": "{{alert.name}}"}, {"type": "TextBlock", "text": "Tal from Keep"}]'
114115
typeCard: message
116+
# Optional: Add mentions to notify specific users
117+
# mentions: '[{"id": "user@example.com", "name": "User Name"}]'
115118
```
116119

120+
You can also find an example with user mentions in our [examples](https://github.com/keephq/keep/tree/main/examples/workflows/keep-teams-adaptive-cards-with-mentions.yaml) folder.
121+
117122
<Note>
118123
The sections parameter is a JSON string that follows the Adaptive Cards schema, but can also be an object.
119124
If it's a string, it will be parsed as a JSON string.
@@ -159,6 +164,71 @@ provider.notify(
159164
)
160165
```
161166

167+
### Using User Mentions in Adaptive Cards
168+
169+
You can mention users in your Adaptive Cards using the `mentions` parameter. The text in your card should include the mention in the format `<at>User Name</at>`, and you need to provide the user's ID and name in the `mentions` parameter.
170+
171+
Teams supports three types of user IDs for mentions:
172+
- Teams User ID (format: `29:1234...`)
173+
- Microsoft Entra Object ID (format: `49c4641c-ab91-4248-aebb-6a7de286397b`)
174+
- User Principal Name (UPN) (format: `user@example.com`)
175+
176+
```python
177+
provider.notify(
178+
typeCard="message",
179+
sections=[
180+
{
181+
"type": "TextBlock",
182+
"text": "Hello <at>John Doe</at>, please review this alert!"
183+
}
184+
],
185+
mentions=[
186+
{
187+
"id": "john.doe@example.com", # Can be UPN, Microsoft Entra Object ID, or Teams User ID
188+
"name": "John Doe"
189+
}
190+
]
191+
)
192+
```
193+
194+
You can also mention multiple users in a single card:
195+
196+
```python
197+
provider.notify(
198+
typeCard="message",
199+
sections=[
200+
{
201+
"type": "TextBlock",
202+
"text": "Hello <at>John Doe</at> and <at>Jane Smith</at>, please review this alert!"
203+
}
204+
],
205+
mentions=[
206+
{
207+
"id": "john.doe@example.com",
208+
"name": "John Doe"
209+
},
210+
{
211+
"id": "49c4641c-ab91-4248-aebb-6a7de286397b", # Microsoft Entra Object ID
212+
"name": "Jane Smith"
213+
}
214+
]
215+
)
216+
```
217+
218+
In YAML workflows, you can provide the mentions as a JSON string:
219+
220+
```yaml
221+
actions:
222+
- name: teams-action
223+
provider:
224+
config: "{{ providers.teams }}"
225+
type: teams
226+
with:
227+
typeCard: message
228+
sections: '[{"type": "TextBlock", "text": "Hello <at>John Doe</at>, please review this alert!"}]'
229+
mentions: '[{"id": "john.doe@example.com", "name": "John Doe"}]'
230+
```
231+
162232
## Useful Links
163233
164234
- https://learn.microsoft.com/pt-br/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook

docs/snippets/providers/teams-snippet-autogenerated.mdx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{/* This snippet is automatically generated using scripts/docs_render_provider_snippets.py
1+
{/* This snippet is automatically generated using scripts/docs_render_provider_snippets.py
22
Do not edit it manually, as it will be overwritten */}
33

44
## Authentication
@@ -25,11 +25,14 @@ actions:
2525
sections: {value} # For MessageCard: Array of custom information sections. For Adaptive Cards: Array of card elements following the Adaptive Card schema. Can be provided as a JSON string or array.
2626
schema: {value} # Schema URL for Adaptive Cards. Default is "http://adaptivecards.io/schemas/adaptive-card.json"
2727
attachments: {value} # Custom attachments array for Adaptive Cards (overrides default attachment structure). Can be provided as a JSON string or array.
28+
mentions: {value} # List of user mentions to include in the Adaptive Card. Each mention should be a dict with 'id' (user ID, Microsoft Entra Object ID, or UPN) and 'name' (display name) keys.
29+
Example: [{"id": "user-id-123", "name": "John Doe"}, {"id": "john.doe@example.com", "name": "John Doe"}]
2830
```
2931
3032
3133
3234
3335
Check the following workflow examples:
3436
- [create_jira_ticket_upon_alerts.yml](https://github.com/keephq/keep/blob/main/examples/workflows/create_jira_ticket_upon_alerts.yml)
37+
- [keep-teams-adaptive-cards-with-mentions.yaml](https://github.com/keephq/keep/blob/main/examples/workflows/keep-teams-adaptive-cards-with-mentions.yaml)
3538
- [keep-teams-adaptive-cards.yaml](https://github.com/keephq/keep/blob/main/examples/workflows/keep-teams-adaptive-cards.yaml)

docs/workflows/syntax/functions.mdx

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,37 @@ steps:
3838
```
3939
---
4040

41+
### `capitalize`
42+
43+
**Description:** Capitalizes the first character of a string.
44+
**Example:**
45+
46+
```yaml
47+
steps:
48+
- name: example-step
49+
provider:
50+
type: mock
51+
with:
52+
message: keep.capitalize("hello world") # Output: "Hello world"
53+
```
54+
55+
---
56+
57+
### `title`
58+
59+
**Description:** Converts a string to title case (capitalizes each word).
60+
**Example:**
61+
62+
```yaml
63+
steps:
64+
- name: example-step
65+
provider:
66+
type: mock
67+
with:
68+
message: keep.title("hello world") # Output: "Hello World"
69+
```
70+
---
71+
4172
### `split`
4273

4374
**Description:** Splits a string into a list using a delimiter.
@@ -389,7 +420,7 @@ steps:
389420

390421
## Utility Functions
391422

392-
### `is_first_time`
423+
### `get_firing_time`
393424

394425
**Description:** Calculates the firing duration of an alert in specified time units.
395426
**Example:**
@@ -406,7 +437,7 @@ steps:
406437

407438
---
408439

409-
### `is_first_time`
440+
### `add_time_to_date`
410441

411442
**Description:** Adds time to a date string based on specified time units.
412443
**Example:**
@@ -422,3 +453,48 @@ steps:
422453
```
423454

424455
---
456+
457+
### `timestamp_delta`
458+
459+
**Description:** Adds or subtracts a time delta to/from a datetime. Use negative values to subtract time.
460+
**Example:**
461+
462+
```yaml
463+
steps:
464+
- name: example-step
465+
provider:
466+
type: mock
467+
with:
468+
# Add 2 hours to the current time
469+
add_hours: keep.timestamp_delta(keep.utcnow(), 2, "hours")
470+
471+
# Subtract 30 minutes from a specific datetime
472+
subtract_minutes: keep.timestamp_delta("2024-01-01T12:00:00Z", -30, "minutes") # Output: 2024-01-01T11:30:00Z
473+
474+
# Add 1 week to a datetime
475+
add_week: keep.timestamp_delta("2024-01-01T00:00:00Z", 1, "weeks") # Output: 2024-01-08T00:00:00Z
476+
477+
```
478+
479+
---
480+
481+
### `is_first_time`
482+
483+
**Description:** Checks if an alert with a given fingerprint is firing for the first time or first time within a specified period.
484+
**Example:**
485+
486+
```yaml
487+
steps:
488+
- name: example-step
489+
provider:
490+
type: mock
491+
with:
492+
# Check if this is the first time the alert is firing
493+
first_time: keep.is_first_time(alert.fingerprint, tenant_id="tenant-id")
494+
495+
# Check if this is the first time the alert is firing in the last 24 hours
496+
first_time_24h: keep.is_first_time(alert.fingerprint, "24h", tenant_id="tenant-id")
497+
498+
```
499+
500+
---
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
workflow:
2+
id: teams-adaptive-card-with-mentions
3+
name: Teams Adaptive Card With Mentions
4+
description: Sends Microsoft Teams notifications using Adaptive Cards with user mentions to notify specific team members.
5+
disabled: false
6+
triggers:
7+
- type: manual
8+
- filters:
9+
- key: source
10+
value: r".*"
11+
type: alert
12+
consts: {}
13+
owners: []
14+
services: []
15+
steps: []
16+
actions:
17+
- name: teams-action
18+
provider:
19+
config: "{{ providers.teams }}"
20+
type: teams
21+
with:
22+
typeCard: message
23+
sections: '[{"type": "TextBlock", "text": "Alert: {{alert.name}}"}, {"type": "TextBlock", "text": "Hello <at>John Doe</at>, please review this alert!"}, {"type": "TextBlock", "text": "Severity: {{alert.severity}}"}]'
24+
mentions: '[{"id": "john.doe@example.com", "name": "John Doe"}]'

examples/workflows/keep-teams-adaptive-cards.yaml

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,23 @@ workflow:
22
id: teams-adaptive-card-notifier
33
name: Teams Adaptive Card Notifier
44
description: Sends customized Microsoft Teams notifications using Adaptive Cards with dynamic alert information and formatted sections.
5-
disabled: false
6-
triggers:
7-
- type: manual
8-
- filters:
9-
- key: source
10-
value: r".*"
11-
type: alert
12-
consts: {}
13-
owners: []
14-
services: []
15-
steps: []
16-
actions:
17-
- name: teams-action
18-
provider:
19-
config: "{{ providers.teams }}"
20-
type: teams
21-
with:
22-
message: ""
23-
sections: '[{"type": "TextBlock", "text": "{{alert.name}}"}, {"type": "TextBlock", "text": "Tal from Keep"}]'
24-
typeCard: message
5+
disabled: false
6+
triggers:
7+
- type: manual
8+
- filters:
9+
- key: source
10+
value: r".*"
11+
type: alert
12+
consts: {}
13+
owners: []
14+
services: []
15+
steps: []
16+
actions:
17+
- name: teams-action
18+
provider:
19+
config: "{{ providers.teams }}"
20+
type: teams
21+
with:
22+
message: ""
23+
sections: '[{"type": "TextBlock", "text": "{{alert.name}}"}, {"type": "TextBlock", "text": "Tal from Keep"}]'
24+
typeCard: message

keep-ui/features/cel-input/cel-input.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ interface CelInputProps {
1212
onClearValue?: () => void;
1313
onKeyDown?: (e: KeyboardEvent) => void;
1414
onFocus?: () => void;
15+
onIsValidChange?: (isValid: boolean) => void;
1516
placeholder?: string;
1617
disabled?: boolean;
1718
}
@@ -21,6 +22,7 @@ const CelInput: FC<CelInputProps> = ({
2122
value = "",
2223
fieldsForSuggestions = [],
2324
onValueChange,
25+
onIsValidChange,
2426
onClearValue,
2527
onKeyDown,
2628
onFocus,
@@ -35,6 +37,7 @@ const CelInput: FC<CelInputProps> = ({
3537
value={value}
3638
fieldsForSuggestions={fieldsForSuggestions}
3739
onValueChange={onValueChange || ((value: string) => {})}
40+
onIsValidChange={onIsValidChange}
3841
onKeyDown={onKeyDown}
3942
onFocus={onFocus}
4043
/>

keep-ui/features/presets/presets-manager/ui/alerts-rules-builder.tsx

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -320,25 +320,6 @@ export const AlertsRulesBuilder = ({
320320
const handleKeyDown = (e: KeyboardEvent) => {
321321
if (e.key === "Enter") {
322322
e.preventDefault(); // Prevents the default action of Enter key in a form
323-
// You can now use `target` which is asserted to be an HTMLTextAreaElement
324-
325-
// check if the CEL is valid by comparing the parsed query with the original CEL
326-
// remove spaces so that "a && b" is the same as "a&&b"
327-
const celQuery = formatQuery(parsedCELRulesToQuery, "cel");
328-
/*
329-
SHAHAR: this is the old way of checking if the CEL is valid
330-
I think its over complicated so let's just check if the query is "1 == 1" (which is parse error)
331-
I'll leave the old code here for reference
332-
333-
const isValidCEL =
334-
celQuery.replace(/\s+/g, "") === celRules.replace(/\s+/g, "") ||
335-
celRules === "";
336-
*/
337-
338-
// SHAHAR: new way of checking if the CEL is valid
339-
const isValidCEL = celRules == "" || celQuery !== "1 == 1";
340-
setIsValidCEL(isValidCEL);
341-
342323
// close the menu
343324
setShowSuggestions(false);
344325
if (isValidCEL) {
@@ -464,6 +445,7 @@ export const AlertsRulesBuilder = ({
464445
value={celRules}
465446
fieldsForSuggestions={alertFields}
466447
onValueChange={onValueChange}
448+
onIsValidChange={setIsValidCEL}
467449
onClearValue={handleClearInput}
468450
onKeyDown={handleKeyDown}
469451
onFocus={() => setShowSuggestions(true)}

keep-ui/features/workflows/test-run/ui/workflow-test-run-button.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ export function WorkflowTestRunButton({
3838
const workflow = getYamlWorkflowDefinition(definition.value);
3939
// NOTE: prevent the workflow from being disabled, so test run doesn't fail
4040
workflow.disabled = false;
41+
if (workflowId) {
42+
// if existing workflow, use it's real id for test run
43+
workflow.id = workflowId;
44+
}
4145
const body = getBodyFromStringOrDefinitionOrObject({
4246
workflow,
4347
});

0 commit comments

Comments
 (0)