From 201ec093b7ab676d5d7a84972c5d9e64664af7e0 Mon Sep 17 00:00:00 2001 From: Karl-Philipp Wulfert Date: Tue, 5 Feb 2019 15:52:08 +0100 Subject: [PATCH] feat: add new task to remind about open merge requests --- src/tasks/remind.ts | 105 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/tasks/remind.ts diff --git a/src/tasks/remind.ts b/src/tasks/remind.ts new file mode 100644 index 00000000..33eb7add --- /dev/null +++ b/src/tasks/remind.ts @@ -0,0 +1,105 @@ +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 { + // 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}!`, + ); + } + } + }); +}