refactor: adjust to refactored GitLab API

This commit is contained in:
Karl-Philipp Wulfert
2019-02-05 15:52:28 +01:00
parent 201ec093b7
commit cd48929ca1
4 changed files with 37 additions and 57 deletions

View File

@@ -13,14 +13,12 @@
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Api} from '@openstapps/gitlab-api'; import {Api} from '@openstapps/gitlab-api';
import {MergeRequest} from '@openstapps/gitlab-api/lib/types';
import {Logger} from '@openstapps/logger'; import {Logger} from '@openstapps/logger';
import {WebClient} from '@slack/client';
import {asyncPool} from 'async-pool-native/dist/async-pool';
import * as commander from 'commander'; import * as commander from 'commander';
import {existsSync, readFileSync} from 'fs'; import {existsSync, readFileSync} from 'fs';
import {join} from 'path'; import {join} from 'path';
import {GITLAB_API_URL, GROUPS} from './configuration'; import {GITLAB_API_URL} from './configuration';
import {remind} from './tasks/remind';
import {report} from './tasks/report'; import {report} from './tasks/report';
import {tidy} from './tasks/tidy'; import {tidy} from './tasks/tidy';
import {unlabel} from './tasks/unlabel'; import {unlabel} from './tasks/unlabel';
@@ -69,38 +67,8 @@ commander
commander commander
.command('remind') .command('remind')
.action(async () => { .action(async () => {
const mergeRequests: MergeRequest[] = await remind(gitlabApi);
await gitlabApi.makeGitLabAPIRequest(`groups/${GROUPS[0]}/merge_requests?state=opened`); logger.ok('Done!');
const client = new WebClient(process.env.SLACK_API_TOKEN);
await asyncPool(2, mergeRequests, async (mergeRequest) => {
if (mergeRequest.title.indexOf('WIP') !== 0) {
const config = await gitlabApi.makeGitLabAPIRequest(
`/projects/${mergeRequest.project_id}/merge_requests/${mergeRequest.iid}/approvals`,
);
if (config.merge_status === 'can_be_merged') {
if (config.approvals_left > 0) {
logger.warn(`Merge request '${mergeRequest.title}' needs more approvals!`);
await client.chat.postMessage({
channel: 'C762UG76Z',
text: `Merge request '${mergeRequest.title}' needs more approvals! See ${mergeRequest.web_url}!`,
});
} else {
logger.log(`Merge request '${mergeRequest.title}' is ready to be merged!`);
await client.chat.postMessage({
channel: 'C762UG76Z',
text: `Merge request '${mergeRequest.title}' is ready to be merged! See ${mergeRequest.web_url}!`,
});
}
}
} else {
logger.info(`Merge request '${mergeRequest.title}' is WIP.`);
}
});
}); });
commander commander

View File

@@ -13,7 +13,7 @@
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Api} from '@openstapps/gitlab-api'; import {Api} from '@openstapps/gitlab-api';
import {Issue, Project, User} from '@openstapps/gitlab-api/lib/types'; import {Issue, IssueState, MembershipScope, MergeRequestState, Project, User} from '@openstapps/gitlab-api/lib/types';
import {asyncPool} from 'async-pool-native/dist/async-pool'; import {asyncPool} from 'async-pool-native/dist/async-pool';
import {readFileSync, writeFile} from 'fs'; import {readFileSync, writeFile} from 'fs';
import * as moment from 'moment'; import * as moment from 'moment';
@@ -30,7 +30,7 @@ const asyncWriteFile = promisify(writeFile);
* *
* @param state State to check * @param state State to check
*/ */
export function issueStateIsOpenedOrClosed(state: string): state is 'opened' | 'closed' { export function issueStateIsOpenedOrClosed(state: IssueState): state is IssueState.OPENED | IssueState.CLOSED {
return ['opened', 'closed'].indexOf(state) >= 0; return ['opened', 'closed'].indexOf(state) >= 0;
} }
@@ -191,8 +191,8 @@ export function groupIssuesByAssignee(issues: Issue[]): { [k: number]: AssigneeW
}; };
} }
if (issue.state === 'reopened') { if (issue.state === IssueState.REOPENED) {
issue.state = 'opened'; issue.state = IssueState.OPENED;
} }
if (issueStateIsOpenedOrClosed(issue.state)) { if (issueStateIsOpenedOrClosed(issue.state)) {
@@ -273,7 +273,7 @@ export async function getMergeRequestsForProjects(api: Api,
} }
// get all merge requests for project // get all merge requests for project
const mergeRequests = await api.getMergeRequestsForProject(project.id); const mergeRequests = await api.getMergeRequests(MembershipScope.PROJECTS, project.id, MergeRequestState.OPENED);
// extract issue number from merge request // extract issue number from merge request
projectMergeRequests[project.id] = mergeRequests.map((mergeRequest) => { projectMergeRequests[project.id] = mergeRequests.map((mergeRequest) => {
@@ -332,11 +332,11 @@ export async function report(api: Api, label: string) {
} }
}); });
if (a.state === 'closed') { if (a.state === IssueState.CLOSED) {
weightA -= 10; weightA -= 10;
} }
if (b.state === 'closed') { if (b.state === IssueState.CLOSED) {
weightB -= 10; weightB -= 10;
} }

View File

@@ -13,7 +13,14 @@
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Api} from '@openstapps/gitlab-api'; import {Api} from '@openstapps/gitlab-api';
import {AccessLevel, Label, Milestone, Project} from '@openstapps/gitlab-api/lib/types'; import {
AccessLevel,
IssueState,
MembershipScope,
Milestone,
Project,
Scope,
} from '@openstapps/gitlab-api/lib/types';
import {asyncPool} from 'async-pool-native/dist/async-pool'; import {asyncPool} from 'async-pool-native/dist/async-pool';
import {flatten2dArray, getProjects, logger} from '../common'; import {flatten2dArray, getProjects, logger} from '../common';
import {GROUPS, NEEDED_LABELS, NEEDED_MILESTONES, NOTE_PREFIX, PROTECTED_BRANCHES, SCHOOLS} from '../configuration'; import {GROUPS, NEEDED_LABELS, NEEDED_MILESTONES, NOTE_PREFIX, PROTECTED_BRANCHES, SCHOOLS} from '../configuration';
@@ -31,7 +38,7 @@ export async function tidyIssuesWithoutMilestone(api: Api): Promise<void> {
return api.getIssues({ return api.getIssues({
groupId: groupId, groupId: groupId,
milestone: 'No Milestone', milestone: 'No Milestone',
state: 'opened', state: IssueState.OPENED,
}); });
}); });
@@ -66,6 +73,7 @@ export async function tidyIssuesWithoutMilestone(api: Api): Promise<void> {
await api.createNote( await api.createNote(
issue.project_id, issue.project_id,
Scope.ISSUES,
issue.iid, issue.iid,
`${NOTE_PREFIX} Milestone was set automatically to \`Meeting\`.`, `${NOTE_PREFIX} Milestone was set automatically to \`Meeting\`.`,
); );
@@ -86,7 +94,7 @@ export async function tidyOpenIssuesWithoutMeetingLabel(api: Api): Promise<void>
const issueResults = await asyncPool(3, GROUPS, (groupId) => { const issueResults = await asyncPool(3, GROUPS, (groupId) => {
return api.getIssues({ return api.getIssues({
groupId: groupId, groupId: groupId,
state: 'opened', state: IssueState.OPENED,
}); });
}); });
@@ -110,6 +118,7 @@ export async function tidyOpenIssuesWithoutMeetingLabel(api: Api): Promise<void>
return api.createNote( return api.createNote(
issue.project_id, issue.project_id,
Scope.ISSUES,
issue.iid, issue.iid,
`${NOTE_PREFIX} Automatically adding label 'meeting'\n\n/label ~meeting`); `${NOTE_PREFIX} Automatically adding label 'meeting'\n\n/label ~meeting`);
}); });
@@ -128,21 +137,21 @@ export async function tidyLabels(api: Api, projects: Project[]): Promise<void> {
const labels = await api.getLabels(project.id); const labels = await api.getLabels(project.id);
const neededLabels = NEEDED_LABELS.slice(0); const neededLabels = NEEDED_LABELS.slice(0);
const extraneousLabels: Label[] = []; // const extraneousLabels: Label[] = [];
labels.forEach((label) => { labels.forEach((label) => {
let needed = false; // let needed = false;
neededLabels.forEach((neededLabel, neededLabelIdx) => { neededLabels.forEach((neededLabel, neededLabelIdx) => {
if (neededLabel.name.toLowerCase() === label.name.toLowerCase()) { if (neededLabel.name.toLowerCase() === label.name.toLowerCase()) {
neededLabels.splice(neededLabelIdx, 1); neededLabels.splice(neededLabelIdx, 1);
needed = true; // needed = true;
} }
}); });
if (!needed) { /* if (!needed) {
extraneousLabels.push(label); extraneousLabels.push(label);
} } */
}); });
await asyncPool(2, neededLabels, async (neededLabel) => { await asyncPool(2, neededLabels, async (neededLabel) => {
@@ -225,7 +234,7 @@ export async function tidyProtectedBranches(api: Api, projects: Project[]): Prom
* @param api GitLab API instance to use for the requests * @param api GitLab API instance to use for the requests
*/ */
export async function tidySubGroupMembers(api: Api): Promise<void> { export async function tidySubGroupMembers(api: Api): Promise<void> {
const stappsMembers = await api.getMembers('groups', GROUPS[0]); const stappsMembers = await api.getMembers(MembershipScope.GROUPS, GROUPS[0]);
const stappsMemberIds = stappsMembers.map((member) => member.id); const stappsMemberIds = stappsMembers.map((member) => member.id);
const groupIdsToSchool: any = {}; const groupIdsToSchool: any = {};
@@ -235,12 +244,12 @@ export async function tidySubGroupMembers(api: Api): Promise<void> {
}); });
await asyncPool(2, GROUPS.slice(1), async (groupId) => { await asyncPool(2, GROUPS.slice(1), async (groupId) => {
const members = await api.getMembers('groups', groupId); const members = await api.getMembers(MembershipScope.GROUPS, groupId);
const memberIds = members.map((member) => member.id); const memberIds = members.map((member) => member.id);
await asyncPool(2, stappsMembers, async (stappsMember) => { await asyncPool(2, stappsMembers, async (stappsMember) => {
if (memberIds.indexOf(stappsMember.id) === -1) { if (memberIds.indexOf(stappsMember.id) === -1) {
await api.addMember('groups', groupId, stappsMember.id, AccessLevel.Developer); await api.addMember(MembershipScope.GROUPS, groupId, stappsMember.id, AccessLevel.Developer);
logger.log('Added ' + stappsMember.name + ' to group ' + groupIdsToSchool[groupId] + '.'); logger.log('Added ' + stappsMember.name + ' to group ' + groupIdsToSchool[groupId] + '.');
} }
@@ -248,7 +257,7 @@ export async function tidySubGroupMembers(api: Api): Promise<void> {
await asyncPool(2, members, async (member) => { await asyncPool(2, members, async (member) => {
if (stappsMemberIds.indexOf(member.id) === -1) { if (stappsMemberIds.indexOf(member.id) === -1) {
await api.deleteMember('groups', groupId, member.id); await api.deleteMember(MembershipScope.GROUPS, groupId, member.id);
logger.log('Deleted member ' + member.name + ' from group ' + groupIdsToSchool[groupId] + '.'); logger.log('Deleted member ' + member.name + ' from group ' + groupIdsToSchool[groupId] + '.');
} }
@@ -270,7 +279,7 @@ export async function tidyIssuesWithoutAssignee(api: Api): Promise<void> {
const issueResults = await asyncPool(3, GROUPS, (groupId) => { const issueResults = await asyncPool(3, GROUPS, (groupId) => {
return api.getIssues({ return api.getIssues({
groupId: groupId, groupId: groupId,
state: 'opened', state: IssueState.OPENED,
}); });
}); });
@@ -290,6 +299,7 @@ export async function tidyIssuesWithoutAssignee(api: Api): Promise<void> {
await api.createNote( await api.createNote(
issue.project_id, issue.project_id,
Scope.ISSUES,
issue.iid, issue.iid,
`${NOTE_PREFIX} Assignee was set automatically to author.`, `${NOTE_PREFIX} Assignee was set automatically to author.`,
); );

View File

@@ -13,6 +13,7 @@
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Api} from '@openstapps/gitlab-api'; import {Api} from '@openstapps/gitlab-api';
import {IssueState, Scope} from '@openstapps/gitlab-api/lib/types';
import {asyncPool} from 'async-pool-native/dist/async-pool'; import {asyncPool} from 'async-pool-native/dist/async-pool';
import {flatten2dArray, logger} from '../common'; import {flatten2dArray, logger} from '../common';
import {GROUPS, NOTE_PREFIX} from '../configuration'; import {GROUPS, NOTE_PREFIX} from '../configuration';
@@ -26,7 +27,7 @@ export async function unlabel(api: Api) {
const issueResults = await asyncPool(3, GROUPS, (groupId) => { const issueResults = await asyncPool(3, GROUPS, (groupId) => {
return api.getIssues({ return api.getIssues({
groupId: groupId, groupId: groupId,
state: 'closed', state: IssueState.CLOSED,
}); });
}); });
@@ -40,6 +41,7 @@ export async function unlabel(api: Api) {
await api.createNote( await api.createNote(
issue.project_id, issue.project_id,
Scope.ISSUES,
issue.iid, issue.iid,
`${NOTE_PREFIX} Removed label \`meeting\` automatically. `${NOTE_PREFIX} Removed label \`meeting\` automatically.
/unlabel ~meeting`, /unlabel ~meeting`,