Skip to content
Merged
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
59 changes: 59 additions & 0 deletions __tests__/core/utils/slackifyText.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { slackifyText } from '@/core/utils/slackifyText';

jest.mock('slackify-markdown', () => (text: string) => text);

const SLACK_CHARACTER_LIMIT = 3000;

describe('slackifyText', () => {
it('should return the slackified text if within character limit', () => {
const inputText = 'This is a test message.';
const truncatedMessage = '[truncated]';
const result = slackifyText(
inputText,
truncatedMessage,
SLACK_CHARACTER_LIMIT
);

expect(result).toBe(inputText);
});

it('should truncate the text and append the truncatedMessage if character limit is exceeded', () => {
const inputText = 'A'.repeat(SLACK_CHARACTER_LIMIT + 100);
const truncatedMessage = '[truncated]';
const result = slackifyText(
inputText,
truncatedMessage,
SLACK_CHARACTER_LIMIT
);

expect(result).toContain(truncatedMessage);
expect(result.length).toBeLessThanOrEqual(SLACK_CHARACTER_LIMIT);
});

it('should respect provided slackCharacterLimit value', () => {
const customLimit = 2000;
const inputText = 'B'.repeat(customLimit + 50);
const truncatedMessage = '[cut off]';
const result = slackifyText(inputText, truncatedMessage, customLimit);

expect(result).toContain(truncatedMessage);
expect(result.length).toBeLessThanOrEqual(customLimit);
});

it('should handle multiline text and truncate appropriately', () => {
const inputText = `Line1\nLine2\nLine3\n${'C'.repeat(
SLACK_CHARACTER_LIMIT
)}`;
const truncatedMessage = '[truncated]';
const result = slackifyText(
inputText,
truncatedMessage,
SLACK_CHARACTER_LIMIT
);

expect(result.split('\n').length).toBeLessThanOrEqual(
inputText.split('\n').length
);
expect(result).toContain(truncatedMessage);
});
});
12 changes: 6 additions & 6 deletions __tests__/review/noteHook.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ describe('review > noteHook', () => {
blocks: [
{
text: {
text: `This MR needs work. <http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244|View>`,
text: `This MR needs work.\n<http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244|View>`,
type: 'mrkdwn',
},
type: 'section',
Expand All @@ -90,7 +90,7 @@ describe('review > noteHook', () => {
channel: 'channelId',
icon_emoji: ':speech_balloon_blue:',
link_names: true,
text: ':speech_balloon_blue: This MR needs work.',
text: ':speech_balloon_blue: This MR needs work.\n',
thread_ts: 'ts',
unfurl_links: false,
});
Expand Down Expand Up @@ -140,23 +140,23 @@ describe('review > noteHook', () => {
{
text: {
text: `\
This MR needs work. <http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244|View>`,
This MR needs work.\n<http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244|View>`,
type: 'mrkdwn',
},
type: 'section',
},
{
text: {
text: `\
This MR needs work. <http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244|View>`,
This MR needs work.\n<http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244|View>`,
type: 'mrkdwn',
},
type: 'section',
},
{
text: {
text: `\
This MR needs work. <http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244|View>`,
This MR needs work.\n<http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244|View>`,
type: 'mrkdwn',
},
type: 'section',
Expand Down Expand Up @@ -184,7 +184,7 @@ This MR needs work. <http://example.com/gitlab-org/gitlab-test/merge_requests/1#

:speech_balloon_blue: This MR needs work.

:speech_balloon_blue: This MR needs work.`,
:speech_balloon_blue: This MR needs work.\n`,
thread_ts: 'ts',
unfurl_links: false,
});
Expand Down
7 changes: 5 additions & 2 deletions src/changelog/buildChangelogModalView.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { Block, KnownBlock, View } from '@slack/types';
import { generateChangelog } from '@/changelog/utils/generateChangelog';
import { slackifyChangelog } from '@/changelog/utils/slackifyChangelog';
import { getProjectsByChannelId } from '@/core/services/data';
import { fetchProjectById, fetchProjectTags } from '@/core/services/gitlab';
import { logger } from '@/core/services/logger';
import type { GitlabProjectDetails } from '@/core/typings/GitlabProject';
import type { SlackOption } from '@/core/typings/SlackOption';
import { slackifyText } from '@/core/utils/slackifyText';

interface ChangelogModalData {
channelId?: string;
Expand Down Expand Up @@ -169,7 +169,10 @@ export async function buildChangelogModalView({
text: {
type: 'mrkdwn',
text: changelog
? slackifyChangelog(changelog)
? slackifyText(
changelog,
'*⚠️ Changelog truncated due to Slack limitations.*'
)
: 'No change has been found.',
},
},
Expand Down
19 changes: 0 additions & 19 deletions src/changelog/utils/slackifyChangelog.ts

This file was deleted.

23 changes: 23 additions & 0 deletions src/core/utils/slackifyText.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import slackifyMarkdown from 'slackify-markdown';

export const SLACK_CHARACTER_LIMIT = 2980;

export function slackifyText(
text: string,
truncatedMessage: string,
slackCharacterLimit: number = SLACK_CHARACTER_LIMIT
): string {
let slackifiedText = slackifyMarkdown(text);

// Slack allows only 3000 characters in text field
if (slackifiedText.length > slackCharacterLimit - truncatedMessage.length) {
slackifiedText = slackifiedText
.slice(0, SLACK_CHARACTER_LIMIT)
.split('\n')
.slice(0, -2)
.join('\n');

slackifiedText = `${slackifiedText}\n\n${truncatedMessage}`;
}
return slackifiedText;
}
21 changes: 5 additions & 16 deletions src/release/commands/create/utils/slackifyChangelog.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
import slackifyMarkdown from 'slackify-markdown';

const SLACK_CHARACTER_LIMIT = 3000;
import { slackifyText } from '@/core/utils/slackifyText';

export function slackifyChangelog(changelog: string): string {
let slackifiedChangelog = slackifyMarkdown(changelog);

// Slack allows only 3000 characters in text field
if (slackifiedChangelog.length > SLACK_CHARACTER_LIMIT) {
slackifiedChangelog = slackifiedChangelog
.slice(0, SLACK_CHARACTER_LIMIT)
.split('\n')
.slice(0, -2)
.join('\n');

slackifiedChangelog = `${slackifiedChangelog}\n\n*⚠️ Changelog truncated due to Slack limitations.*`;
}
return slackifiedChangelog;
return slackifyText(
changelog,
'*⚠️ Changelog truncated due to Slack limitations.*'
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { generateChangelog } from '@/changelog/utils/generateChangelog';
import { fetchProjectById, fetchProjectTags } from '@/core/services/gitlab';
import type { BlockActionView } from '@/core/typings/BlockActionPayload';
import type { SlackOption } from '@/core/typings/SlackOption';
import { slackifyText } from '@/core/utils/slackifyText';
import getReleaseOptions from '@/release/releaseOptions';
import ConfigHelper from '../../../utils/ConfigHelper';
import { slackifyChangelog } from '../utils/slackifyChangelog';

interface ReleaseModalData {
channelId?: string;
Expand Down Expand Up @@ -236,7 +236,10 @@ export async function buildReleaseModalView({
text: {
type: 'mrkdwn',
text: changelog
? slackifyChangelog(changelog)
? slackifyText(
changelog,
'*⚠️ Changelog truncated due to Slack limitations.*'
)
: 'No change has been found.',
},
},
Expand Down
2 changes: 1 addition & 1 deletion src/release/releaseOptions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { generateChangelog } from '@/changelog/utils/generateChangelog';
import { slackifyChangelog } from '@/changelog/utils/slackifyChangelog';
import ReleasePluginManager from '@/core/pluginManager/ReleasePluginManager';
import {
fetchPipelineBridges,
Expand All @@ -9,6 +8,7 @@ import {
import { logger } from '@/core/services/logger';
import { slackBotWebClient } from '@/core/services/slack';
import { cleanViewState } from '@/core/utils/cleanViewState';
import { slackifyChangelog } from '@/release/commands/create/utils/slackifyChangelog';
import { addLoaderToReleaseModal } from './commands/create/utils/addLoaderToReleaseModal';
import type { ReleaseOptions } from './typings/ReleaseManager';

Expand Down
2 changes: 1 addition & 1 deletion src/release/typings/ReleaseManager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { View } from '@slack/web-api';
import type { generateChangelog } from '@/changelog/utils/generateChangelog';
import type { slackifyChangelog } from '@/changelog/utils/slackifyChangelog';
import type {
fetchPipelineBridges,
fetchPipelineJobs,
Expand All @@ -18,6 +17,7 @@ import type { GitlabDeploymentHook } from '@/core/typings/GitlabDeploymentHook';
import type { SlackOption } from '@/core/typings/SlackOption';
import type { StaticSelectAction } from '@/core/typings/StaticSelectAction';
import type { cleanViewState } from '@/core/utils/cleanViewState';
import type { slackifyChangelog } from '@/release/commands/create/utils/slackifyChangelog';
import type { addLoaderToReleaseModal } from '../commands/create/utils/addLoaderToReleaseModal';
import type { ReleaseStateUpdate } from './ReleaseStateUpdate';
import type { ReleaseTagManager } from './ReleaseTagManager';
Expand Down
24 changes: 17 additions & 7 deletions src/review/commands/share/viewBuilders/buildNoteMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
escapeText,
fetchSlackUserFromGitlabUser,
} from '@/core/services/slack';
import { SLACK_CHARACTER_LIMIT, slackifyText } from '@/core/utils/slackifyText';

export async function buildNoteMessage(
channelId: string,
Expand All @@ -19,7 +20,7 @@ export async function buildNoteMessage(
type: 'section',
text: {
type: 'mrkdwn',
text: `${escapeText(note).replace(/\\_/g, '_')} <${url}|View>`,
text: slackifyNote(note, url),
},
})),
...(author !== undefined
Expand All @@ -42,15 +43,24 @@ export async function buildNoteMessage(
: []),
] as KnownBlock[],
icon_emoji: ':speech_balloon_blue:',
text: noteAttributes
.map(
({ note }) =>
`:speech_balloon_blue: ${escapeText(note).replace(/\\_/g, '_')}`
)
.join('\n\n'),
text: slackifyNote(
noteAttributes
.map(({ note }) => `:speech_balloon_blue: ${note}`)
.join('\n\n')
),
channel: channelId,
thread_ts: reviewMessageTs,
link_names: true,
unfurl_links: false,
};
}

function slackifyNote(note: string, url?: string): string {
const linkToView = url ? `<${url}|View>` : '';

return `${slackifyText(
`${escapeText(note).replace(/\\_/g, '_')}`,
'*⚠️ Note truncated due to Slack limitations.*',
SLACK_CHARACTER_LIMIT - linkToView.length
)}${linkToView}`;
}