mirror of
https://github.com/Unleash/unleash.git
synced 2024-10-28 19:06:12 +01:00
521cc24a22
https://linear.app/unleash/issue/2-1253/add-support-for-more-events-in-the-slack-app-integration Adds support for a lot more events in our integrations. Here is how the full list looks like: - ADDON_CONFIG_CREATED - ADDON_CONFIG_DELETED - ADDON_CONFIG_UPDATED - API_TOKEN_CREATED - API_TOKEN_DELETED - CHANGE_ADDED - CHANGE_DISCARDED - CHANGE_EDITED - CHANGE_REQUEST_APPLIED - CHANGE_REQUEST_APPROVAL_ADDED - CHANGE_REQUEST_APPROVED - CHANGE_REQUEST_CANCELLED - CHANGE_REQUEST_CREATED - CHANGE_REQUEST_DISCARDED - CHANGE_REQUEST_REJECTED - CHANGE_REQUEST_SENT_TO_REVIEW - CONTEXT_FIELD_CREATED - CONTEXT_FIELD_DELETED - CONTEXT_FIELD_UPDATED - FEATURE_ARCHIVED - FEATURE_CREATED - FEATURE_DELETED - FEATURE_ENVIRONMENT_DISABLED - FEATURE_ENVIRONMENT_ENABLED - FEATURE_ENVIRONMENT_VARIANTS_UPDATED - FEATURE_METADATA_UPDATED - FEATURE_POTENTIALLY_STALE_ON - FEATURE_PROJECT_CHANGE - FEATURE_REVIVED - FEATURE_STALE_OFF - FEATURE_STALE_ON - FEATURE_STRATEGY_ADD - FEATURE_STRATEGY_REMOVE - FEATURE_STRATEGY_UPDATE - FEATURE_TAGGED - FEATURE_UNTAGGED - GROUP_CREATED - GROUP_DELETED - GROUP_UPDATED - PROJECT_CREATED - PROJECT_DELETED - SEGMENT_CREATED - SEGMENT_DELETED - SEGMENT_UPDATED - SERVICE_ACCOUNT_CREATED - SERVICE_ACCOUNT_DELETED - SERVICE_ACCOUNT_UPDATED - USER_CREATED - USER_DELETED - USER_UPDATED I added the events that I thought were relevant based on my own discretion. Know of any event we should add? Let me know and I'll add it 🙂 For now I only added these events to the new Slack App integration, but we can add them to the other integrations as well since they are now supported. The event formatter was refactored and changed quite a bit in order to make it easier to maintain and add new events in the future. As a result, events are now posted with different text. Do we consider this a breaking change? If so, I can keep the old event formatter around, create a new one and only use it for the new Slack App integration. I noticed we don't have good 404 behaviors in the UI for things that are deleted in the meantime, that's why I avoided some links to specific resources (like feature strategies, integration configurations, etc), but we could add them later if we improve this. This PR also tries to add some consistency to the the way we log events.
111 lines
3.3 KiB
TypeScript
111 lines
3.3 KiB
TypeScript
import Addon from './addon';
|
|
|
|
import slackDefinition from './slack-definition';
|
|
import { IAddonConfig } from '../types/model';
|
|
|
|
import {
|
|
FeatureEventFormatter,
|
|
FeatureEventFormatterMd,
|
|
LinkStyle,
|
|
} from './feature-event-formatter-md';
|
|
import { IEvent } from '../types/events';
|
|
|
|
interface ISlackAddonParameters {
|
|
url: string;
|
|
username?: string;
|
|
defaultChannel: string;
|
|
emojiIcon?: string;
|
|
customHeaders?: string;
|
|
}
|
|
export default class SlackAddon extends Addon {
|
|
private msgFormatter: FeatureEventFormatter;
|
|
|
|
constructor(args: IAddonConfig) {
|
|
super(slackDefinition, args);
|
|
this.msgFormatter = new FeatureEventFormatterMd(
|
|
args.unleashUrl,
|
|
LinkStyle.SLACK,
|
|
);
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
async handleEvent(
|
|
event: IEvent,
|
|
parameters: ISlackAddonParameters,
|
|
): Promise<void> {
|
|
const {
|
|
url,
|
|
defaultChannel,
|
|
username = 'Unleash',
|
|
emojiIcon = ':unleash:',
|
|
customHeaders,
|
|
} = parameters;
|
|
|
|
const slackChannels = this.findSlackChannels(event);
|
|
|
|
if (slackChannels.length === 0) {
|
|
slackChannels.push(defaultChannel);
|
|
}
|
|
|
|
const { text, url: featureLink } = this.msgFormatter.format(event);
|
|
|
|
const requests = slackChannels.map((channel) => {
|
|
const body = {
|
|
username,
|
|
icon_emoji: emojiIcon, // eslint-disable-line camelcase
|
|
text,
|
|
channel: `#${channel}`,
|
|
attachments: [
|
|
{
|
|
actions: [
|
|
{
|
|
name: 'featureToggle',
|
|
text: 'Open in Unleash',
|
|
type: 'button',
|
|
value: 'featureToggle',
|
|
style: 'primary',
|
|
url: featureLink,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
let extraHeaders = {};
|
|
if (typeof customHeaders === 'string' && customHeaders.length > 1) {
|
|
try {
|
|
extraHeaders = JSON.parse(customHeaders);
|
|
} catch (e) {
|
|
this.logger.warn(
|
|
`Could not parse the json in the customHeaders parameter. [${customHeaders}]`,
|
|
);
|
|
}
|
|
}
|
|
const requestOpts = {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
...extraHeaders,
|
|
},
|
|
body: JSON.stringify(body),
|
|
};
|
|
|
|
return this.fetchRetry(url, requestOpts);
|
|
});
|
|
|
|
const results = await Promise.all(requests);
|
|
const codes = results.map((res) => res.status).join(', ');
|
|
this.logger.info(`Handled event ${event.type}. Status codes=${codes}`);
|
|
}
|
|
|
|
findSlackChannels({ tags }: Pick<IEvent, 'tags'>): string[] {
|
|
if (tags) {
|
|
return tags
|
|
.filter((tag) => tag.type === 'slack')
|
|
.map((t) => t.value);
|
|
}
|
|
return [];
|
|
}
|
|
}
|
|
|
|
module.exports = SlackAddon;
|