Skip to content
This repository has been archived by the owner on May 29, 2023. It is now read-only.

feat: add ability to filter by type #77

Merged
merged 3 commits into from
Nov 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {reconcileLabels} from './label';
import {reconcileUsers, reconcileTeams, reconcileRepos} from './users';
import {syncRepoSettings} from './repos';
import * as updateNotifier from 'update-notifier';
import {Flags} from './types';

const pkg = require('../../package.json');

Expand All @@ -39,10 +40,12 @@ const cli = meow(
--language Filter by a given language
--repo Filter by a given repository
--pr Filter to show only PRs
--type Filter to show only issues of a given type
--pri Filter to show only issues with a given priorty

Examples
$ sloth [--csv][--api]
$ sloth issues [--csv][--untriaged][--outOfSLO][--language][--repo][--api][--pr]
$ sloth issues [--csv][--untriaged][--outOfSLO][--language][--repo][--api][--pr][--type]
$ sloth apis
$ sloth tag-issues
$ sloth users
Expand All @@ -59,7 +62,9 @@ const cli = meow(
outOfSLO: {type: 'boolean'},
csv: {type: 'boolean'},
api: {type: 'string'},
pr: {type: 'boolean'}
pr: {type: 'boolean'},
type: {type: 'string'},
pri: {type: 'string'}
}
});

Expand All @@ -80,7 +85,7 @@ switch (cmd) {
p = reconcileUsers();
break;
case 'issues':
p = showIssues(cli.flags);
p = showIssues(cli.flags as Flags);
break;
case 'repos':
p = reconcileRepos();
Expand Down
102 changes: 50 additions & 52 deletions src/issue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import * as Octokit from '@octokit/rest';

import {getPri} from './slo';
import {getPri, getType} from './slo';
import {Flags, Issue, IssueResult, Repo} from './types';
import {octo, repos} from './util';

Expand All @@ -23,15 +23,19 @@ import {isTriaged, isOutOfSLO, hasLabel, isApi, isPullRequest, hoursOld, getApi}
const truncate = require('truncate');
const CSV = require('csv-string');

export async function getIssues(): Promise<IssueResult[]> {
export async function getIssues(flags?: Flags): Promise<IssueResult[]> {
const promises = new Array<Promise<IssueResult>>();
repos.forEach(repo => {
promises.push(getRepoIssues(repo));
// if we're filtering by --language, don't even snag the issues
if (flags && flags.language && repo.language !== flags.language) {
return;
}
promises.push(getRepoIssues(repo, flags));
});
return Promise.all(promises);
}

async function getRepoIssues(repo: Repo): Promise<IssueResult> {
async function getRepoIssues(repo: Repo, flags?: Flags): Promise<IssueResult> {
const [owner, name] = repo.repo.split('/');
const result = {issues: new Array<Issue>(), repo};
let res: Octokit.AnyResponse;
Expand All @@ -45,10 +49,46 @@ async function getRepoIssues(repo: Repo): Promise<IssueResult> {
console.error(e);
throw e;
}
for (const r of res.data) {
for (const r of res.data as Issue[]) {
r.language = repo.language;
r.repo = repo.repo;
result.issues.push(r);
r.type = getType(r);
r.api = getApi(r);
r.isOutOfSLO = isOutOfSLO(r);
r.isTriaged = isTriaged(r);
r.pri = getPri(r);
r.isPR = isPullRequest(r);

let use = true;
if (flags) {
if (flags.api && r.api !== flags.api) {
use = false;
}
if (flags.repo && r.repo !== flags.repo) {
use = false;
}
if (flags.api && r.api !== flags.api) {
use = false;
}
if (flags.outOfSlo && !r.isOutOfSLO) {
use = false;
}
if (flags.untriaged && r.isTriaged) {
use = false;
}
if (flags.pri && r.pri !== flags.pri) {
use = false;
}
if (flags.pr && !r.isPR) {
use = false;
}
if (flags.type && r.type !== flags.type) {
use = false;
}
}
if (use) {
result.issues.push(r);
}
}
i++;
} while (res.headers && res.headers.link &&
Expand All @@ -72,8 +112,6 @@ export async function tagIssues() {
repos.forEach(r => {
r.issues.forEach(i => {
const [owner, name] = r.repo.repo.split('/');
i.isTriaged = isTriaged(i);
i.isOutOfSLO = isOutOfSLO(i);
i.repo = name;
i.owner = owner;
if (!i.isTriaged && !hasLabel(i, 'triage me') &&
Expand Down Expand Up @@ -122,52 +160,12 @@ function untagIssue(
});
}

export async function showIssues(flags: Flags) {
const options = {
csv: flags.csv,
language: flags.language,
outOfSLO: flags.outOfSlo,
untriaged: flags.untriaged,
repo: flags.repo,
api: flags.api,
pr: flags.pr
};
const repos = await getIssues();
// tslint:disable-next-line no-any
export async function showIssues(options: Flags) {
const repos = await getIssues(options);
const issues = new Array<Issue>();
repos.forEach(r => {
if (options.language &&
options.language.toLowerCase() !== r.repo.language.toLowerCase()) {
return;
}
if (options.repo &&
options.repo.toLowerCase() !== r.repo.repo.toLowerCase()) {
return;
}
r.issues.forEach(i => {
if (options.pr) {
if (!isPullRequest(i)) {
return;
}
} else {
if (isPullRequest(i)) {
return;
}
}
i.api = getApi(i);
if (options.api && !isApi(i, options.api)) {
return;
}
i.isTriaged = isTriaged(i);
if (options.untriaged && i.isTriaged) {
return;
}
i.isOutOfSLO = isOutOfSLO(i);
if (options.outOfSLO && !i.isOutOfSLO) {
return;
}
i.pri = getPri(i);
issues.push(i);
});
r.issues.forEach(i => issues.push(i));
});
let table: Table;
const output = new Array<string>();
Expand Down
14 changes: 12 additions & 2 deletions src/slo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.

import {getIssues} from './issue';
import {ApiResult, Issue, IssueResult, LanguageResult, RepoResult} from './types';
import {ApiResult, Flags, Issue, IssueResult, LanguageResult, RepoResult} from './types';
import {languages} from './util';

import Table = require('cli-table');
Expand Down Expand Up @@ -235,6 +235,16 @@ export function getApi(i: Issue) {
return undefined;
}

export function getType(i: Issue) {
for (const label of i.labels) {
const name = label.name.toLowerCase();
if (name.startsWith('type: ')) {
return name.slice(6);
}
}
return undefined;
}

/**
* Determine if an issue has been triaged. An issue is triaged if:
* - It has a `priority` label OR
Expand Down Expand Up @@ -418,7 +428,7 @@ export async function showApiSLOs(cli: meow.Result) {

export async function showLanguageSLOs(cli: meow.Result) {
const output = new Array<string>();
const issues = await getIssues();
const issues = await getIssues(cli.flags as Flags);
const res = getLanguageResults(issues, cli.flags.api);
const languageHeader =
['Language', 'Total', 'P0', 'P1', 'P2', 'Untriaged', 'Out of SLO'];
Expand Down
13 changes: 11 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ export interface Member {
}

export interface Issue {
isPR?: boolean;
api?: string;
type?: string;
pri?: string;
language: string;
repo: string;
Expand Down Expand Up @@ -154,8 +156,15 @@ export interface Organization {
}

export interface Flags {
// tslint:disable-next-line no-any
[index: string]: any;
csv: boolean;
language: string;
outOfSlo: boolean;
untriaged: boolean;
repo: string;
api: string;
pr: boolean;
type: string;
pri: string;
}

export interface GetBranchProtectionResult {
Expand Down