Skip to content

Commit

Permalink
feat: add body review as attachment in slack message
Browse files Browse the repository at this point in the history
  • Loading branch information
christophehurpeau committed May 2, 2020
1 parent 41e747d commit 6a54ef7
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 43 deletions.
44 changes: 43 additions & 1 deletion scripts/test-slack.js
Expand Up @@ -16,8 +16,50 @@ if (!process.env.ORNIKAR_SLACK_TOKEN) {
);
const im = await slackClient.im.open({ user: member.id });

await slackClient.chat.postMessage({
const message = await slackClient.chat.postMessage({
channel: im.channel.id,
text: '<https://github.com/ornikar/www/pull/2945|www#2945>',
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: '<https://github.com/ornikar/www/pull/2945|www#2945>',
},
},
],
attachments: [
{
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `### :warning: Artifact update problem
Renovate failed to update an artifact related to this branch. You probably do not want to merge this PR as-is.
:recycle: Renovate will retry this branch, including artifacts, only when one of the following happens:
- any of the package files in this branch needs updating, or
- the branch becomes conflicted, or
- you check the rebase/retry checkbox if found above, or
- you rename this PR's title to start with "rebase!" to trigger it manually
The artifact failure details are included below:
##### File name: yarn.lock
\`\`\`
error An unexpected error occurred: "Unknown token: { line: 3, col: 2, type: 'INVALID', value: undefined } 3:2 in /mnt/renovate/gh/christophehurpeau/eslint-config-pob/yarn.lock".
\`\`\`
`,
},
},
],
},
],
});
console.log(message);
})();
47 changes: 34 additions & 13 deletions src/context/initTeamSlack.ts
@@ -1,25 +1,36 @@
import Webhooks from '@octokit/webhooks';
import { WebClient } from '@slack/web-api';
import { WebClient, KnownBlock } from '@slack/web-api';
import { Context, Octokit } from 'probot';
import { ExcludesFalsy } from '../utils/ExcludesFalsy';
import { Config } from '../orgsConfigs';
import { getKeys } from './utils';

interface SlackMessage {
text: string;
blocks?: KnownBlock[];
secondaryBlocks?: KnownBlock[];
ts?: string;
}

interface SlackMessageResult {
ts: string;
}

export interface TeamSlack {
mention: (githubLogin: string) => string;
postMessage: (githubLogin: string, text: string) => Promise<void>;
postMessage: (
githubLogin: string,
message: SlackMessage,
) => Promise<SlackMessageResult | null>;
prLink: <T extends Webhooks.WebhookPayloadPullRequest>(
pr: Octokit.PullsGetResponse,
context: Context<T>,
) => string;
}

const ExcludesFalsy = (Boolean as any) as <T>(
x: T | false | null | undefined,
) => x is T;

export const voidTeamSlack = (): TeamSlack => ({
mention: (): string => '',
postMessage: (): Promise<void> => Promise.resolve(),
postMessage: (): Promise<null> => Promise.resolve(null),
prLink: (): string => '',
});

Expand Down Expand Up @@ -81,17 +92,27 @@ export const initTeamSlack = async <GroupNames extends string>(
if (!user) return githubLogin;
return `<@${user.member.id}>`;
},
postMessage: async (githubLogin: string, text: string): Promise<void> => {
context.log.debug('send slack', { githubLogin, text });
if (process.env.DRY_RUN) return;
postMessage: async (
githubLogin: string,
message: SlackMessage,
): Promise<null | SlackMessageResult> => {
context.log.debug('send slack', { githubLogin, message });
if (process.env.DRY_RUN) return null;

const user = getUserFromGithubLogin(githubLogin);
if (!user || !user.im) return;
await slackClient.chat.postMessage({
if (!user || !user.im) return null;
const result = await slackClient.chat.postMessage({
username: process.env.REVIEWFLOW_NAME,
channel: user.im.id,
text,
text: message.text,
blocks: message.blocks,
attachments: message.secondaryBlocks
? [{ blocks: message.secondaryBlocks }]
: undefined,
thread_ts: message.ts,
});
if (!result.ok) return null;
return { ts: result.ts as string };
},
prLink: <T extends Webhooks.WebhookPayloadPullRequest>(
pr: Octokit.PullsGetResponse,
Expand Down
4 changes: 1 addition & 3 deletions src/context/orgContext.ts
@@ -1,5 +1,6 @@
import { Context } from 'probot';
import { Config } from '../orgsConfigs';
import { ExcludesFalsy } from '../utils/ExcludesFalsy';
import { initTeamSlack, TeamSlack } from './initTeamSlack';
import { getKeys } from './utils';

Expand All @@ -21,9 +22,6 @@ export interface OrgContext<
}: { includesReviewerGroup?: boolean; includesWaitForGroups?: boolean },
) => boolean;
}
const ExcludesFalsy = (Boolean as any) as <T>(
x: T | false | null | undefined,
) => x is T;

const initTeamContext = async (
context: Context<any>,
Expand Down
5 changes: 1 addition & 4 deletions src/context/repoContext.ts
Expand Up @@ -5,6 +5,7 @@ import { Context } from 'probot';
import { orgsConfigs, Config, defaultConfig } from '../orgsConfigs';
// eslint-disable-next-line import/no-cycle
import { autoMergeIfPossible } from '../pr-handlers/actions/autoMergeIfPossible';
import { ExcludesFalsy } from '../utils/ExcludesFalsy';
import { initRepoLabels, LabelResponse, Labels } from './initRepoLabels';
import { obtainOrgContext, OrgContext } from './orgContext';

Expand Down Expand Up @@ -37,10 +38,6 @@ interface RepoContextWithoutTeamContext<GroupNames extends string> {
pushAutomergeQueue(pr: LockedMergePr): void;
}

const ExcludesFalsy = (Boolean as any) as <T>(
x: T | false | null | undefined,
) => x is T;

export type RepoContext<GroupNames extends string = any> = OrgContext<
GroupNames
> &
Expand Down
5 changes: 1 addition & 4 deletions src/pr-handlers/actions/editOpenedPR.ts
Expand Up @@ -2,6 +2,7 @@
import Webhooks from '@octokit/webhooks';
import { StatusError, StatusInfo } from '../../orgsConfigs/types';
import { PRHandler } from '../utils';
import { ExcludesFalsy } from '../../utils/ExcludesFalsy';
import { cleanTitle } from './utils/cleanTitle';
import { updateBody } from './utils/updateBody';
import { autoMergeIfPossible } from './autoMergeIfPossible';
Expand All @@ -24,10 +25,6 @@ interface StatusWithError {

type Status = StatusWithInfo | StatusWithError;

const ExcludesFalsy = (Boolean as any) as <T>(
x: T | false | null | undefined,
) => x is T;

export const editOpenedPR: PRHandler<
Webhooks.WebhookPayloadPullRequest,
{ skipAutoMerge: boolean },
Expand Down
14 changes: 6 additions & 8 deletions src/pr-handlers/reviewDismissed.ts
Expand Up @@ -34,25 +34,23 @@ export default function reviewDismissed(app: Application): void {

if (repoContext.slack) {
if (sender.login === reviewer.login) {
repoContext.slack.postMessage(
pr.user.login,
`:skull: ${repoContext.slack.mention(
repoContext.slack.postMessage(pr.user.login, {
text: `:skull: ${repoContext.slack.mention(
reviewer.login,
)} dismissed his review on ${repoContext.slack.prLink(
pr,
context,
)}`,
);
});
} else {
repoContext.slack.postMessage(
reviewer.login,
`:skull: ${repoContext.slack.mention(
repoContext.slack.postMessage(reviewer.login, {
text: `:skull: ${repoContext.slack.mention(
sender.login,
)} dismissed your review on ${repoContext.slack.prLink(
pr,
context,
)}`,
);
});
}
}
},
Expand Down
7 changes: 3 additions & 4 deletions src/pr-handlers/reviewRequestRemoved.ts
Expand Up @@ -62,15 +62,14 @@ export default function reviewRequestRemoved(app: Application): void {
if (sender.login === reviewer.login) return;

if (repoContext.slack) {
repoContext.slack.postMessage(
reviewer.login,
`:skull_and_crossbones: ${repoContext.slack.mention(
repoContext.slack.postMessage(reviewer.login, {
text: `:skull_and_crossbones: ${repoContext.slack.mention(
sender.login,
)} removed the request for your review on ${repoContext.slack.prLink(
pr,
context,
)}`,
);
});
}
},
),
Expand Down
7 changes: 3 additions & 4 deletions src/pr-handlers/reviewRequested.ts
Expand Up @@ -43,15 +43,14 @@ export default function reviewRequested(app: Application): void {
if (sender.login === reviewer.login) return;

if (!shouldWait && repoContext.slack) {
repoContext.slack.postMessage(
reviewer.login,
`:eyes: ${repoContext.slack.mention(
repoContext.slack.postMessage(reviewer.login, {
text: `:eyes: ${repoContext.slack.mention(
sender.login,
)} requests your review on ${repoContext.slack.prLink(
pr,
context,
)} !\n> ${pr.title}`,
);
});
}
},
),
Expand Down
26 changes: 24 additions & 2 deletions src/pr-handlers/reviewSubmitted.ts
Expand Up @@ -9,7 +9,7 @@ export default function reviewSubmitted(app: Application): void {
'pull_request_review.submitted',
createHandlerPullRequestChange(
async (pr, context, repoContext): Promise<void> => {
const { user: reviewer, state } = (context.payload as any).review;
const { user: reviewer, state, body } = (context.payload as any).review;
if (pr.user.login === reviewer.login) return;

const reviewerGroup = repoContext.getReviewerGroup(reviewer.login);
Expand Down Expand Up @@ -87,7 +87,29 @@ export default function reviewSubmitted(app: Application): void {
return `:speech_balloon: ${mention} commented on ${prUrl}`;
})();

repoContext.slack.postMessage(pr.user.login, message);
repoContext.slack.postMessage(pr.user.login, {
text: message,
blocks: [
{
type: 'section' as const,
text: {
type: 'mrkdwn' as const,
text: message,
},
},
],
secondaryBlocks: !body
? undefined
: [
{
type: 'section' as const,
text: {
type: 'mrkdwn' as const,
text: body,
},
},
],
});
},
),
);
Expand Down
3 changes: 3 additions & 0 deletions src/utils/ExcludesFalsy.ts
@@ -0,0 +1,3 @@
export const ExcludesFalsy = (Boolean as any) as <T>(
x: T | false | null | undefined,
) => x is T;

0 comments on commit 6a54ef7

Please sign in to comment.