1import { Command } from '@expo/commander';
2import chalk from 'chalk';
3
4import { link } from '../Formatter';
5import { commentOnIssueAsync } from '../GitHubActions';
6import logger from '../Logger';
7
8type ActionOptions = {
9  payload: string;
10};
11
12export type CommentatorComment = {
13  issue: number;
14  body: string;
15};
16
17export type CommentatorPayload = CommentatorComment[];
18
19export default (program: Command) => {
20  program
21    .command('commentator')
22    .alias('comment')
23    .option(
24      '-p, --payload <payload>',
25      'Serialized and escaped JSON array describing what and where to comment.'
26    )
27    .description(
28      `To add "Hello!" comment on issue #1234, run it with ${chalk.blue.italic(
29        `--payload "[{\\"issue\\": 1234, \\"body\\": \\"Hello!\\"}]"`
30      )}`
31    )
32    .asyncAction(main);
33};
34
35async function main(options: ActionOptions) {
36  const payload = parsePayload(options.payload);
37  const commentedIssues: number[] = [];
38
39  if (!Array.isArray(payload)) {
40    throw new Error(`Payload must be an array.`);
41  }
42  for (const comment of payload) {
43    if (!comment.issue || !comment.body) {
44      logger.error('Comment payload is incomplete:', comment);
45      continue;
46    }
47    try {
48      await commentOnIssueAsync(comment.issue, comment.body);
49      commentedIssues.push(comment.issue);
50    } catch (e) {
51      logger.error(`Failed to comment on issue #${comment.issue}:`, e);
52    }
53  }
54  if (commentedIssues.length > 0) {
55    logger.log(
56      '✍️  Commented on the following issues: %s',
57      commentedIssues
58        .map((issue) =>
59          link(chalk.blue('#' + issue), `https://github.com/expo/expo/issues/${issue}`)
60        )
61        .join(', ')
62    );
63  } else {
64    logger.log('✍️  Nothing to comment.');
65  }
66}
67
68function parsePayload(payloadString: string): CommentatorPayload {
69  const payload = JSON.parse(payloadString);
70  return payload;
71}
72