UNPKG

branch-remover

Version:

A small application for quickly removing unnecessary branches from GitHub.

184 lines (151 loc) 4.79 kB
import { Octokit, RestEndpointMethodTypes } from '@octokit/rest'; import { Branch, BranchListItem, IBranchesProvider, } from '../../Core'; import { Auth, Commit, PullRequestStatus, } from './Types'; export class GitHubProvider implements IBranchesProvider { private readonly _auth: Auth; private readonly _client: Octokit; private get owner(): string { return this._auth.owner; } private get repo(): string { return this._auth.repo; } public get name(): string { return 'GitHub'; } constructor(auth: Auth) { Object.getOwnPropertyNames(new Auth(null, null, null)).forEach( (x: string): void => { if (!auth[x]) { throw new Error(`The "${x}" property is required. The value must not be empty.`); } } ); this._client = new Octokit({ auth: auth.token, }); this._auth = auth; this.getListBranches = this.getListBranches.bind(this); this.removeBranch = this.removeBranch.bind(this); this.getPullRequestStatus = this.getPullRequestStatus.bind(this); this.getLastCommit = this.getLastCommit.bind(this); } public async getListBranches(): Promise<Array<BranchListItem>> { const result = new Array<BranchListItem>(); const getList = async(page: number): Promise<Array<BranchListItem>> => { const { data }= await this._client.repos.listBranches({ owner: this.owner, repo: this.repo, per_page: 100, page, }); return data.map<BranchListItem>( (x): BranchListItem => { return { name: x.name, lastCommitHash: x.commit.sha, }; } ); }; let page = 1; let list = await getList(page); while (list.length) { result.push(...list); list = await getList(++page); } return result; } public async getBranch(branchName: string, lastCommitHash?: string): Promise<Branch> { const { data } = await this._client.search.issuesAndPullRequests({ q: `repo:${this.owner}/${this.repo} is:pr head:${branchName}` + (lastCommitHash ? ` hash:${lastCommitHash}` : ''), sort: 'updated', order: 'desc', }); const additionalInfo = new Map<string, string>(); let updatedDate: Date = null; let mergedDate: Date = null; let merged = false; let hasUncommittedChanges = false; let status: PullRequestStatus; let item: RestEndpointMethodTypes['search']['issuesAndPullRequests']['response']['data']['items'][0]; if (data.items.length) { for (const x of data.items) { status = await this.getPullRequestStatus(x.number); if (status.sourceBranchName === branchName) { item = x; updatedDate = new Date(status.updatedDate); hasUncommittedChanges = updatedDate > status.mergedDate; break; } } } if (item) { updatedDate = new Date(item.updated_at); if (item.state === 'closed') { merged = status.merged; mergedDate = status.mergedDate; } if (item.pull_request) { additionalInfo.set('Pull Request Url', item.pull_request.html_url); } } else { const commit = await this.getLastCommit(branchName); updatedDate = new Date(commit.date); } return { name: branchName, merged, mergedDate, updatedDate, hasUncommittedChanges, additionalInfo, url: `https://github.com/${this._auth.owner}/${this._auth.repo}/tree/${branchName}`, }; } public async removeBranch(branchName: string): Promise<void> { await this._client.git.deleteRef({ owner: this.owner, repo: this.repo, ref: `heads/${branchName}`, }); } private async getPullRequestStatus(pullRequestNumber: number): Promise<PullRequestStatus> { const { data } = await this._client.pulls.get({ owner: this.owner, repo: this.repo, pull_number: pullRequestNumber, }); return { sourceBranchName: data.head.ref, targetBranchName: data.base.ref, merged: data.merged, mergeable: data.mergeable, mergeableState: data.mergeable_state as any, mergedDate: data.merged_at && new Date(data.merged_at), mergeCommitHash: data.merge_commit_sha, closedDate: data.closed_at && new Date(data.closed_at), updatedDate: data.updated_at && new Date(data.updated_at), createdDate: new Date(data.created_at), }; } private async getLastCommit(branchName: string): Promise<Commit> { const { data } = await this._client.repos.getCommit({ owner: this.owner, repo: this.repo, ref: branchName, }); return { hash: data.sha, date: new Date(data.commit.committer.date), }; } }