1import { Command } from '@expo/commander';
2
3import * as GitHub from '../GitHub';
4import * as Linear from '../Linear';
5import logger from '../Logger';
6
7type ActionOptions = {
8  issue: string;
9};
10
11export default (program: Command) => {
12  program
13    .command('close-linear-issue-from-github')
14    .alias('clifg')
15    .description('Close a Linear issue imported from GitHub.')
16    .option('-i, --issue <string>', 'Number of the original GitHub issue.')
17    .asyncAction(action);
18};
19
20async function action(options: ActionOptions) {
21  if (isNaN(Number(options.issue))) {
22    throw new Error('Flag `--issue` must be provided with a number value');
23  }
24  if (!process.env.GITHUB_TOKEN) {
25    throw new Error('Environment variable `GITHUB_TOKEN` is required for this command.');
26  }
27  if (!process.env.LINEAR_API_KEY) {
28    throw new Error('Environment variable `LINEAR_API_KEY` is required for this command.');
29  }
30
31  try {
32    await closeIssueAsync(+options.issue);
33  } catch (error) {
34    logger.error(error);
35    throw error;
36  }
37}
38
39async function closeIssueAsync(githubIssueNumber: number) {
40  const linearIssues = await Linear.getIssuesAsync({
41    teamId: Linear.ENG_TEAM_ID,
42    filter: {
43      description: {
44        containsIgnoreCase: `https://github.com/expo/expo/issues/${githubIssueNumber}`,
45      },
46      labels: {
47        some: {
48          name: { eq: 'GitHub' },
49        },
50      },
51    },
52  });
53  const linearIssue = linearIssues?.[0];
54
55  if (!linearIssue) {
56    throw new Error(
57      `Unable to find a Linear issue referring to the Github issue #${githubIssueNumber}.`
58    );
59  }
60
61  await Linear.closeIssueAsync({ issueId: linearIssue.id, teamId: Linear.ENG_TEAM_ID });
62
63  const issueCloserPR = await GitHub.getIssueCloserPrUrlAsync(githubIssueNumber);
64
65  if (issueCloserPR) {
66    await Linear.commentIssueAsync({
67      issueId: linearIssue.id,
68      comment: `This issue was automatically marked as done by ${issueCloserPR}`,
69    });
70  }
71}
72