Skip to content

Commit

Permalink
Merge pull request #42 from seegno/feature/program-options
Browse files Browse the repository at this point in the history
Update program options
  • Loading branch information
joaonice authored Feb 28, 2018
2 parents 759744b + 99647c9 commit 651bd48
Show file tree
Hide file tree
Showing 10 changed files with 254 additions and 202 deletions.
18 changes: 7 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,21 @@ yarn global add ghlabels
You can provide options as arguments or leave then blank and they will be prompted.

```sh
ghlabels --owner foo --repo bar --token foobar --configFile ./path/somefile
ghlabels --repository foo/bar --token foobar --file ./path/somefile
```

Note: As an alternative you can provide options as enviroment variables (e.g. GITHUB_LABELS_TOKEN).

### Copy from another repo

```sh
ghlabels copy --sourceOwner seegno --sourceRepo github-labels --targetOwner foo --targetRepo bar --token foobar
ghlabels copy --source seegno/github-labels --target foo/bar --token foobar
```

### List

```sh
ghlabels list --owner seegno --repo github-labels
ghlabels list --repository seegno/github-labels
```

### Client
Expand All @@ -54,24 +54,20 @@ import { copyLabelsFromRepo, listLabels, updateLabels } from 'ghlabels';

// Example of copying labels from a source repo.
copyLabelsFromRepo({
owner: 'foo',
repo: 'bar',
source: 'seegno/github-labels'
target: 'foo/bar',
token: 'foobar'
});

// Example of listing all labels from a repo.
listLabels({
owner: 'seegno',
repo: 'github-labels',
repository: 'seegno/github-labels',
token: 'foobar'
});

// Example of updating all labels from a repo.
updateLabels({
sourceOwner: 'seegno',
sourceRepo: 'github-labels',
targetOwner: 'foo',
targetRepo: 'bar',
repository: 'foo/bar',
token: 'foobar'
});
```
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"dependencies": {
"bluebird": "^3.3.1",
"fs": "^0.0.2",
"github": "^9.2.0",
"github": "^11.0.0",
"inquirer": "^3.0.6",
"lodash": "^4.3.0",
"prettyjson": "^1.1.3",
Expand Down
94 changes: 53 additions & 41 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import { differenceBy, get, has } from 'lodash';
import Github from 'github';
import Promise from 'bluebird';

/**
* GitHub configuration.
Expand All @@ -19,6 +18,20 @@ const config = {
version: '3.0.0'
};

/**
* Get repository owner and name and include a validation.
*/

const getRepositoryOptions = repository => {
const [owner, repo] = repository.split('/');

if (!owner || !repo) {
throw new Error('Malformed repository option');
}

return { owner, repo };
};

/**
* Export `Client`.
*/
Expand All @@ -29,78 +42,73 @@ export default class Client {
* Constructor.
*/

constructor({ owner, repo, options }) {
constructor({ token, ...options }) {
this.github = new Github({ ...config, ...options });
this.owner = owner;
this.repo = repo;

Promise.promisifyAll(this.github.issues);
Promise.promisifyAll(this.github);
}

/**
* Authenticate.
*/

authenticate(token) {
this.github.authenticate({ token, type: 'oauth' });
}

/**
* Create a new label with given `name` and `color`.
*/

async createLabel(name, color) {
return await this.github.issues.createLabelAsync({
async createLabel(repository, name, color) {
const { owner, repo } = getRepositoryOptions(repository);

return await this.github.issues.createLabel({
color,
name,
owner: this.owner,
repo: this.repo
owner,
repo
});
}

/**
* Create or update a label with given `name`.
*/

async createOrUpdateLabel(name, color) {
async createOrUpdateLabel(repository, name, color) {
let label = false;

try {
label = await this.getLabel(name);
label = await this.getLabel(repository, name);
} catch (err) {
if (!has(err, 'code') || get(err, 'code') !== 404) {
throw err;
}
}

if (label) {
return await this.updateLabel(name, color);
return await this.updateLabel(repository, name, color);
}

return await this.createLabel(name, color);
return await this.createLabel(repository, name, color);
}

/**
* Delete label by given `name`.
*/

async deleteLabel(name) {
return await this.github.issues.deleteLabelAsync({
async deleteLabel(repository, name) {
const { owner, repo } = getRepositoryOptions(repository);

return await this.github.issues.deleteLabel({
name,
owner: this.owner,
repo: this.repo
owner,
repo
});
}

/**
* Get all repo labels.
*/

async getLabels() {
const result = await this.github.issues.getLabelsAsync({
owner: this.owner,
repo: this.repo
async getLabels(repository) {
const { owner, repo } = getRepositoryOptions(repository);

const result = await this.github.issues.getLabels({
owner,
repo
});

return result.data;
Expand All @@ -110,45 +118,49 @@ export default class Client {
* Get label by given `name`.
*/

async getLabel(name) {
return await this.github.issues.getLabelAsync({
async getLabel(repository, name) {
const { owner, repo } = getRepositoryOptions(repository);

return await this.github.issues.getLabel({
name,
owner: this.owner,
repo: this.repo
owner,
repo
});
}

/**
* Update an existing label with given `color`.
*/

async updateLabel(name, color) {
return await this.github.issues.updateLabelAsync({
async updateLabel(repository, name, color) {
const { owner, repo } = getRepositoryOptions(repository);

return await this.github.issues.updateLabel({
color,
name,
oldname: name,
owner: this.owner,
repo: this.repo
owner,
repo
});
}

/**
* Set labels.
*/

async setLabels(labels) {
const current = await this.getLabels();
async setLabels(repository, labels) {
const current = await this.getLabels(repository);

// Delete current labels that are not included in the wanted labels.
const deprecated = differenceBy(current, labels, 'name');

for (const { name } of deprecated) {
await this.deleteLabel(name);
await this.deleteLabel(repository, name);
}

// Create or update wanted labels.
for (const { color, name } of labels) {
await this.createOrUpdateLabel(name, color);
await this.createOrUpdateLabel(repository, name, color);
}
}
}
38 changes: 15 additions & 23 deletions src/commands/copy-from-repo-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@ import prettyjson from 'prettyjson';

export function copyFromRepoConfig(yargs) {
yargs
.option('sourceOwner', { demand: false, describe: 'Source repository owner', type: 'string' })
.option('sourceRepo', { demand: false, describe: 'Source repository name', type: 'string' })
.option('targetOwner', { demand: false, describe: 'Target repository owner', type: 'string' })
.option('targetRepo', { demand: false, describe: 'Target repository name', type: 'string' })
.option('source', { demand: false, describe: 'Source repository name (ex. seegno/github-labels)', type: 'string' })
.option('target', { demand: false, describe: 'Target repository name (ex. seegno/github-labels)', type: 'string' })
.option('token', { demand: true, describe: 'GitHub authentication token', type: 'string' })
.example('$0 --owner foo --repo bar --sourceOwner qux --sourceRepo corge --token foobar');
.example('$0 --source foo/bar --target qux/corge --token foobar');
}

/**
Expand All @@ -28,24 +26,14 @@ export function copyFromRepoConfig(yargs) {

export async function copyFromRepo(args) {
const questions = {
sourceOwner: {
message: 'What is the source owner name?',
name: 'sourceOwner',
source: {
message: 'What is the source repository name? (ex. seegno/github-labels)',
name: 'source',
validate: input => !!input
},
sourceRepo: {
message: 'What is the source repository name?',
name: 'sourceRepo',
validate: input => !!input
},
targetOwner: {
message: 'What is the target owner name?',
name: 'targetOwner',
validate: input => !!input
},
targetRepo: {
message: 'What is the target repository name?',
name: 'targetRepo',
target: {
message: 'What is the target repository name? (ex. seegno/github-labels)',
name: 'target',
validate: input => !!input
},
token: {
Expand All @@ -61,7 +49,11 @@ export async function copyFromRepo(args) {
console.log('Copying labels from repo...'); // eslint-disable-line no-console
console.log(prettyjson.render(pick(options, keys(pickBy(questions))))); // eslint-disable-line no-console

await copyLabelsFromRepo(options);
try {
await copyLabelsFromRepo(options);

return console.log('Copy completed!'); // eslint-disable-line no-console
console.log('Copy completed!'); // eslint-disable-line no-console
} catch (e) {
console.error(e.message); // eslint-disable-line no-console
}
}
16 changes: 5 additions & 11 deletions src/commands/list-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ import prettyjson from 'prettyjson';

export function listConfig(yargs) {
yargs
.option('owner', { demand: false, describe: 'Repository owner', type: 'string' })
.option('repo', { demand: false, describe: 'Repository name', type: 'string' })
.option('repository', { demand: false, describe: 'Repository name (ex. seegno/github-labels)', type: 'string' })
.option('token', { demand: true, describe: 'GitHub authentication token', type: 'string' })
.example('$0 --repo foo --token bar --configFile ./path/somefile');
.example('$0 --repository foo/bar --token');
}

/**
Expand All @@ -26,14 +25,9 @@ export function listConfig(yargs) {

export async function list(args) {
const questions = {
owner: {
message: 'What is the owner name?',
name: 'owner',
validate: input => !!input
},
repo: {
message: 'What is the repository name?',
name: 'repo',
repository: {
message: 'What is the repository name? (ex. seegno/github-labels)',
name: 'repository',
validate: input => !!input
},
token: {
Expand Down
Loading

0 comments on commit 651bd48

Please sign in to comment.