Skip to content

Commit 186e9e8

Browse files
authored
feat(aci): add default action configs + data in automation builder (#94551)
added default values for `Select` fields when adding new actions to automation builder <img width="1060" alt="Screenshot 2025-06-27 at 10 31 08 AM" src="https://github.com/user-attachments/assets/9c1796ec-bbe9-4c52-b3bd-9743781a9dc0" />
1 parent e7ecd4c commit 186e9e8

File tree

6 files changed

+61
-30
lines changed

6 files changed

+61
-30
lines changed

static/app/types/workflowEngine/actions.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import type {IssueConfigField} from 'sentry/types/integrations';
22

33
export interface Action {
4-
config: {
5-
target_type: ActionTarget | null;
6-
sentry_app_identifier?: SentryAppIdentifier;
7-
target_display?: string;
8-
target_identifier?: string;
9-
};
4+
config: ActionConfig;
105
data: Record<string, any>;
116
id: string;
127
type: ActionType;
@@ -22,6 +17,13 @@ export interface TicketCreationAction extends Action {
2217
integrationId: string;
2318
}
2419

20+
export interface ActionConfig {
21+
target_type: ActionTarget | null;
22+
sentry_app_identifier?: SentryAppIdentifier;
23+
target_display?: string;
24+
target_identifier?: string;
25+
}
26+
2527
export enum ActionTarget {
2628
SPECIFIC = 0,
2729
USER = 1,

static/app/views/automations/components/actionNodes.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export function useActionNodeContext(): ActionNodeProps {
6868

6969
type ActionNode = {
7070
action: React.ComponentType<any>;
71+
defaultData?: Record<string, any>;
7172
details?: React.ComponentType<any>;
7273
label?: string;
7374
link?: string;
@@ -87,7 +88,12 @@ export const actionNodesMap = new Map<ActionType, ActionNode>([
8788
],
8889
[
8990
ActionType.EMAIL,
90-
{label: t('Notify on preferred channel'), action: EmailNode, details: EmailDetails},
91+
{
92+
label: t('Notify on preferred channel'),
93+
action: EmailNode,
94+
details: EmailDetails,
95+
defaultData: {fallthrough_type: 'ActiveMembers'},
96+
},
9197
],
9298
[
9399
ActionType.DISCORD,
@@ -145,14 +151,20 @@ export const actionNodesMap = new Map<ActionType, ActionNode>([
145151
],
146152
[
147153
ActionType.OPSGENIE,
148-
{label: t('Opsgenie'), action: OpsgenieNode, details: OpsgenieDetails},
154+
{
155+
label: t('Opsgenie'),
156+
action: OpsgenieNode,
157+
details: OpsgenieDetails,
158+
defaultData: {priority: 'P1'},
159+
},
149160
],
150161
[
151162
ActionType.PAGERDUTY,
152163
{
153164
label: t('Pagerduty'),
154165
action: PagerdutyNode,
155166
details: PagerdutyDetails,
167+
defaultData: {priority: 'default'},
156168
},
157169
],
158170
[

static/app/views/automations/components/actions/email.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ export function EmailDetails({action}: {action: Action}) {
3939
if (target_type === ActionTarget.ISSUE_OWNERS) {
4040
return tct('Notify Suggested Assignees and, if none found, notify [fallthrough]', {
4141
fallthrough:
42-
FALLTHROUGH_CHOICES.find(choice => choice.value === action.data.fallthroughType)
43-
?.label || String(action.data.fallthroughType),
42+
FALLTHROUGH_CHOICES.find(choice => choice.value === action.data.fallthrough_type)
43+
?.label || String(action.data.fallthrough_type),
4444
});
4545
}
4646

@@ -79,9 +79,9 @@ function TargetTypeField() {
7979
name={`${actionId}.config.target_type`}
8080
value={action.config.target_type}
8181
options={TARGET_TYPE_CHOICES}
82-
onChange={(option: SelectValue<string>) =>
83-
onUpdate({config: {target_type: option.value, target_identifier: undefined}})
84-
}
82+
onChange={(option: SelectValue<string>) => {
83+
onUpdate({config: {target_type: option.value, target_identifier: undefined}});
84+
}}
8585
/>
8686
);
8787
}
@@ -96,9 +96,9 @@ function IdentifierField() {
9696
<TeamSelector
9797
name={`${actionId}.config.target_identifier`}
9898
value={action.config.target_identifier}
99-
onChange={(value: any) =>
100-
onUpdate({config: {target_identifier: value.actor.id}, data: {}})
101-
}
99+
onChange={(value: any) => {
100+
onUpdate({config: {target_identifier: value.actor.id}, data: {}});
101+
}}
102102
useId
103103
styles={selectControlStyles}
104104
/>
@@ -120,20 +120,20 @@ function IdentifierField() {
120120
</SelectWrapper>
121121
);
122122
}
123-
return tct('and, if none found, notify [fallThrough]', {
124-
fallThrough: <FallthroughField />,
123+
return tct('and, if none found, notify [fallthrough]', {
124+
fallthrough: <FallthroughField />,
125125
});
126126
}
127127

128128
function FallthroughField() {
129129
const {action, actionId, onUpdate} = useActionNodeContext();
130130
return (
131131
<AutomationBuilderSelect
132-
name={`${actionId}.data.fallthroughType`}
133-
value={action.data.fallthroughType}
132+
name={`${actionId}.data.fallthrough_type`}
133+
value={action.data.fallthrough_type}
134134
options={FALLTHROUGH_CHOICES}
135135
onChange={(option: SelectValue<string>) =>
136-
onUpdate({data: {fallthroughType: option.value}})
136+
onUpdate({data: {fallthrough_type: option.value}})
137137
}
138138
/>
139139
);

static/app/views/automations/components/actions/integrationField.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ export function IntegrationField() {
1515
value: team.id,
1616
}))}
1717
onChange={(option: SelectValue<string>) => {
18+
const integration = handler.integrations?.find(i => i.id === option.value);
19+
const defaultService = integration?.services?.[0]?.id;
1820
onUpdate({
1921
integrationId: option.value,
22+
...(defaultService && {config: {target_identifier: defaultService}}),
2023
});
2124
}}
2225
/>

static/app/views/automations/components/actions/sentryApp.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function SentryAppActionSettingsButton() {
4848
{...deps}
4949
sentryAppInstallationUuid={sentryApp.installationUuid}
5050
config={sentryApp.settings as SchemaFormConfig}
51-
appName={sentryApp.title ?? sentryApp.name}
51+
appName={sentryApp.name}
5252
onSubmitSuccess={(formData: Record<string, string>) =>
5353
onUpdate({data: formData})
5454
}

static/app/views/automations/components/automationBuilderContext.tsx

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {createContext, type Reducer, useCallback, useContext, useReducer} from '
22
import {uuid4} from '@sentry/core';
33

44
import {
5+
type ActionConfig,
56
type ActionHandler,
67
ActionTarget,
78
ActionType,
@@ -11,6 +12,7 @@ import {
1112
DataConditionGroupLogicType,
1213
type DataConditionType,
1314
} from 'sentry/types/workflowEngine/dataConditions';
15+
import {actionNodesMap} from 'sentry/views/automations/components/actionNodes';
1416
import {dataConditionNodesMap} from 'sentry/views/automations/components/dataConditionNodes';
1517

1618
export function useAutomationBuilderReducer() {
@@ -506,13 +508,27 @@ function getActionTargetType(actionType: ActionType): ActionTarget | null {
506508
}
507509
}
508510

511+
function getDefaultConfig(actionHandler: ActionHandler): ActionConfig {
512+
const targetType = getActionTargetType(actionHandler.type);
513+
const targetIdentifier =
514+
actionHandler.sentryApp?.id ??
515+
actionHandler.integrations?.[0]?.services?.[0]?.id ??
516+
actionHandler.services?.[0]?.slug ??
517+
undefined;
518+
519+
return {
520+
target_type: targetType,
521+
...(targetIdentifier && {target_identifier: targetIdentifier}),
522+
};
523+
}
524+
509525
function addIfAction(
510526
state: AutomationBuilderState,
511527
action: AddIfActionAction
512528
): AutomationBuilderState {
513529
const {groupId, actionId, actionHandler} = action;
514530

515-
const targetType = getActionTargetType(actionHandler.type);
531+
const defaultIntegration = actionHandler.integrations?.[0];
516532

517533
return {
518534
...state,
@@ -527,13 +543,11 @@ function addIfAction(
527543
{
528544
id: actionId,
529545
type: actionHandler.type,
530-
config: {
531-
target_type: targetType,
532-
...(actionHandler.sentryApp
533-
? {target_identifier: actionHandler.sentryApp.id}
534-
: {}),
535-
},
536-
data: {},
546+
config: getDefaultConfig(actionHandler),
547+
...(defaultIntegration && {
548+
integrationId: defaultIntegration.id,
549+
}),
550+
data: actionNodesMap.get(actionHandler.type)?.defaultData || {},
537551
},
538552
],
539553
};

0 commit comments

Comments
 (0)