Commit 201ec093 authored by krlwlfrt's avatar krlwlfrt
Browse files

feat: add new task to remind about open merge requests

parent b15ef713
Loading
Loading
Loading
Loading

src/tasks/remind.ts

0 → 100644
+105 −0
Original line number Diff line number Diff line
import {Api} from '@openstapps/gitlab-api';
import {
  AccessLevel,
  MembershipScope,
  MergeRequestMergeStatus,
  MergeRequestState,
  Scope,
  User,
} from '@openstapps/gitlab-api/lib/types';
import {WebClient} from '@slack/client';
import {asyncPool} from 'async-pool-native/dist/async-pool';
import {logger} from '../common';
import {GROUPS} from '../configuration';

export async function remind(api: Api): Promise<void> {
  // get list of open merge requests
  const mergeRequests = await api.getMergeRequests(MembershipScope.GROUPS, GROUPS[0], MergeRequestState.OPENED);

  logger.info(`Found ${mergeRequests.length} open merge requests.`);

  // instantiate slack client
  const client = new WebClient(process.env.SLACK_API_TOKEN);

  // get members of main group
  const members = await api.getMembers(MembershipScope.GROUPS, GROUPS[0]);

  // filter members with at least maintainer status
  const maintainers = members.filter((member) => member.access_level >= AccessLevel.Maintainer);

  // extract maintainer's usernames
  const maintainerUsernames = maintainers.map((maintainer) => maintainer.username);

  // sort maintainer's usernames alphabetically
  maintainerUsernames.sort((a, b) => {
    return a.localeCompare(b);
  });

  logger.info(`Found ${maintainers.length} maintainer(s).`);

  await asyncPool(2, mergeRequests, async (mergeRequest) => {
    // check if merge request is WIP
    if (mergeRequest.work_in_progress) {
      logger.info(`Merge request '${mergeRequest.title}' is WIP.`);
      return;
    }

    // get merge request approval
    const approval = await api.getMergeRequestApproval(mergeRequest.project_id, mergeRequest.iid);

    if (approval.merge_status === MergeRequestMergeStatus.CAN_BE_MERGED) {
      if (approval.approvals_left > 0) {
        logger.warn(`Merge request '${mergeRequest.title}' needs more approvals!`);

        // get possible appropers, prefixed with '@' and joined with commas
        const possibleApprovers = maintainerUsernames
          .filter((username) => {
            if (approval.approved_by.length === 0) {
              return true;
            }

            return approval.approved_by.find((approver: { user: User }) => {
              return approver.user.username !== username;
            });
          })
          .map((username) => '@' + username)
          .join(', ');

        // send message to slack
        await client.chat.postMessage({
          channel: 'C762UG76Z',
          text: `Merge request '${mergeRequest.title}' needs more approvals! See ${mergeRequest.web_url}!`,
        });

        // create note in merge request
        await api.createNote(
          mergeRequest.project_id,
          Scope.MERGE_REQUESTS,
          mergeRequest.iid,
          `Please review, ${possibleApprovers}!`,
        );
      } else {
        logger.log(`Merge request '${mergeRequest.title}' is ready to be merged!`);

        // send message to slack
        await client.chat.postMessage({
          channel: 'C762UG76Z',
          text: `Merge request '${mergeRequest.title}' is ready to be merged! See ${mergeRequest.web_url}!`,
        });

        // prefix maintainers with '@' and join with commas
        const possibleMergers = maintainerUsernames
          .map((username) => '@' + username)
          .join(', ');

        // create note in merge request
        await api.createNote(
          mergeRequest.project_id,
          Scope.MERGE_REQUESTS,
          mergeRequest.iid,
          `Merge request is ready to be merged, ${possibleMergers}!`,
        );
      }
    }
  });
}