Skip to content

Commit

Permalink
feat: add pulls command
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Sep 1, 2021
1 parent 5f163da commit 42531a0
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 9 deletions.
25 changes: 25 additions & 0 deletions src/commands/pulls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Command } from '@oclif/core';
import { cli } from 'cli-ux';
import { sortBy } from 'lodash';
import { Pull, Repos } from '../repos';

export default class Pulls extends Command {
public static description =
'List all pull requests for added repositories. Requires GH_TOKEN to be set in the environment.';
public static examples = ['<%= config.bin %> <%= command.id %>'];
public static disableJsonFlag = true;

public static flags = {};

public async run(): Promise<void> {
const repos = await Repos.create();
const pulls = await repos.fetchPulls();
const columns = {
repo: { header: 'Repo', get: (p: Pull): string => p.repo.split('/')[1] },
title: {},
url: { header: 'URL', get: (p: Pull): string => p.url },
};
const sorted = sortBy(Object.values(pulls), 'repo');
cli.table(sorted, columns, { title: 'Pull Requests' });
}
}
31 changes: 24 additions & 7 deletions src/commands/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,39 @@ export default class Setup extends Command {
directory: Flags.string({
description: 'Location to setup repositories.',
char: 'd',
dependsOn: ['username'],
hidden: true,
}),
username: Flags.string({
description: 'Github username.',
char: 'u',
dependsOn: ['directory'],
hidden: true,
}),
};

public async run(): Promise<void> {
const { flags } = await this.parse(Setup);
const config = await Config.create();
if (!flags.directory) {
const answers = await prompt<{ directory: string }>({
name: 'directory',
type: 'input',
message: 'Where would you link to clone your repositories?',
default: Config.DEFAULT_DIRECTORY,
});
if (!flags.directory || !flags.username) {
const answers = await prompt<{ directory: string; username: string }>([
{
name: 'directory',
type: 'input',
message: 'Where would you link to clone your repositories?',
default: Config.DEFAULT_DIRECTORY,
},
{
name: 'username',
type: 'input',
message: 'What is your github username?',
},
]);
config.set('directory', path.resolve(answers.directory.replace('~', os.homedir())));
config.set('username', answers.username);
} else {
config.set('directory', flags.directory);
config.set('username', flags.username);
}
await config.write();

Expand Down
3 changes: 2 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import { ConfigFile } from './configFile';

export interface Configuration {
directory: string;
username: string;
}

export class Config extends ConfigFile<Configuration> {
public static DEFAULT_DIRECTORY = path.join(os.homedir(), 'repos');

private static DEFAULT_CONFIG: Configuration = { directory: Config.DEFAULT_DIRECTORY };
private static DEFAULT_CONFIG: Configuration = { directory: Config.DEFAULT_DIRECTORY, username: '' };

public constructor() {
super('config.json');
Expand Down
35 changes: 34 additions & 1 deletion src/repos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ export interface RepoIndex {
[key: string]: Repository;
}

export type Pull = {
url: string;
number: number;
title: string;
user: string;
repo: string;
};

export class Repos extends ConfigFile<RepoIndex> {
public static REFRESH_TIME = Duration.weeks(1);
public directory!: Directory;
Expand Down Expand Up @@ -82,6 +90,10 @@ export class Repos extends ConfigFile<RepoIndex> {
}
}

public getOrgs(): string[] {
return Array.from(new Set(Object.values(this.getContents()).map((r) => r.org)));
}

public async fetch(org: string, repo?: string | null): Promise<Repository[]> {
if (repo) {
const response = await this.octokit.request('GET /repos/{owner}/{repo}', { owner: org, repo });
Expand All @@ -92,6 +104,26 @@ export class Repos extends ConfigFile<RepoIndex> {
}
}

public async fetchPulls(): Promise<Pull[]> {
const config = await Config.create();
const response = await this.octokit.paginate('GET /search/issues', {
q: `is:pr is:open author:${config.get('username')}`,
});
const pulls = response
// eslint-disable-next-line arrow-body-style
.map((r) => {
return {
url: r.html_url,
number: r.number,
title: r.title,
user: r.user.login,
repo: r.repository_url.split('/').slice(-2).join('/'),
} as Pull;
})
.filter((r) => this.has(r.repo));
return pulls;
}

public async clone(repo: Repository, method: CloneMethod = 'ssh'): Promise<void> {
const orgDir = path.join(this.directory.name, repo.org);
await mkdir(orgDir, { recursive: true });
Expand All @@ -104,6 +136,7 @@ export class Repos extends ConfigFile<RepoIndex> {
// do nothing
}
}

protected async init(): Promise<void> {
await super.init();
this.octokit = new Octokit({ auth: getToken() });
Expand All @@ -119,7 +152,7 @@ export class Repos extends ConfigFile<RepoIndex> {

private async refresh(): Promise<void> {
const originalRepos = Object.keys(this.getContents());
const orgs = Array.from(new Set(Object.values(this.getContents()).map((r) => r.org)));
const orgs = this.getOrgs();
for (const org of orgs) {
try {
const orgRepos = await this.fetch(org);
Expand Down

0 comments on commit 42531a0

Please sign in to comment.