Skip to content

Commit

Permalink
use octokit and other deps updates (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
gavinr authored Apr 18, 2020
1 parent 0d5ac4b commit 4f891b0
Show file tree
Hide file tree
Showing 8 changed files with 1,545 additions and 959 deletions.
4 changes: 2 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module.exports = {
"extends": "standard"
};
extends: ["standard", "prettier"],
};
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ jspm_packages

# Optional REPL history
.node_repl_history

.vscode
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
language: node_js

node_js:
- '6'
- node
- lts/*

install:
- npm install

before_script:
- npm test
- npm test
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

## [0.4.0] - 2020-04-18

## Changed
- Updated to `octokit/rest.js` v17
- `pathPrefix` no longer supported
- Send full URL in for `github_enterprise` (if not sent, will use `https://api.github.com` by default)
- `bottleneck` package is no longer used in favor of `@octokit/plugin-throttling`
- Supporting current and LTS versions of Node.js.

## [0.3.0] - 2017-12-22
### Changed
- Re-publishing to NPM with `LF` line endings instead of `CRLF`
Expand All @@ -27,6 +36,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Basic CSV import functionality.
- A few basic tests

[Unreleased]: https://github.com/gavinr/github-csv-tools/compare/v0.2.0...HEAD
[Unreleased]: https://github.com/gavinr/github-csv-tools/compare/v0.4.0...HEAD
[0.4.0]: https://github.com/gavinr/github-csv-tools/compare/v0.3.0...0.4.0
[0.3.0]: https://github.com/gavinr/github-csv-tools/compare/v0.2.0...0.3.0
[0.2.0]: https://github.com/gavinr/github-csv-tools/compare/v0.1.0...0.2.0
41 changes: 41 additions & 0 deletions helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const createIssue = (octokit, issueInfo, state = false) => {
return new Promise((resolve, reject) => {
octokit.issues.create(issueInfo).then(
(res) => {
// console.log("res", res);
if (res.status === 201) {
if (state === false) {
// Success creating the issue and we do not have to close the issue, so we're done.
resolve(res);
} else {
// need to close the issue!
const issueNumber = res.data.number;
octokit.issues
.update({
owner: issueInfo.owner,
repo: issueInfo.repo,
issue_number: issueNumber,
state,
})
.then(
(editRes) => {
resolve(editRes);
},
(err) => {
reject(err);
}
);
}
} else {
// error creating the issue
reject(res);
}
},
(err) => {
reject(err);
}
);
});
};

module.exports = { createIssue };
280 changes: 155 additions & 125 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,141 +1,171 @@
#!/usr/bin/env node
/* jshint esversion: 6 */

const program = require('commander')
const co = require('co')
const prompt = require('co-prompt')
const GitHubApi = require('github')
const csv = require('csv')
const fs = require('fs')
const Bottleneck = require('bottleneck')
const program = require("commander");
const co = require("co");
const prompt = require("co-prompt");
const { Octokit } = require("@octokit/rest");
const { throttling } = require("@octokit/plugin-throttling");

const { createIssue } = require("./helpers.js");

const csv = require("csv");
const fs = require("fs");

program
.version('0.3.0')
.arguments('<file>')
.option('--github_enterprise [github.my-company.com]', 'Your GitHub Enterprise URL.')
.option('--token [token]', 'The GitHub token. https://github.com/settings/tokens')
.version("0.4.0")
.arguments("<file>")
.option(
"--github_enterprise [https://api.github.my-company.com]",
"Your GitHub Enterprise URL."
)
.option(
"--token [token]",
"The GitHub token. https://github.com/settings/tokens"
)
.action(function (file, options) {
co(function * () {
var retObject = {}
retObject.githubUrl = options.github_enterprise || 'api.github.com'
if (retObject.githubUrl !== 'api.github.com') {
retObject.pathPrefix = '/api/v3'
co(function* () {
var retObject = {};
retObject.githubUrl =
options.github_enterprise || "https://api.github.com";
retObject.token = options.token || "";
if (retObject.token === "") {
retObject.token = yield prompt(
"token (get from https://github.com/settings/tokens): "
);
}
retObject.token = options.token || ''
if (retObject.token === '') {
retObject.token = yield prompt('token (get from https://' + retObject.githubUrl + '/settings/tokens): ')
};
retObject.userOrOrganization = yield prompt('user or organization: ')
retObject.repo = yield prompt('repo: ')
return retObject
}).then(function (values) {
var github = new GitHubApi({
// required
version: '3.0.0',
// optional
pathPrefix: values.pathPrefix,
debug: true,
protocol: 'https',
host: values.githubUrl,
timeout: 5000,
headers: {
'user-agent': 'My-Cool-GitHub-App' // GitHub is happy with a unique user agent
}
})

// abuse rate limits apply for concurrent content creation
// requests by a single GitHub user.
var limiter = new Bottleneck(5, 500)

// OAuth2
github.authenticate({
type: 'oauth',
token: values.token
})

fs.readFile(file, 'utf8', (err, data) => {
if (err) {
console.error('Error reading file.')
process.exit(1)
}
csv.parse(data, {
trim: true
}, (err, csvRows) => {
if (err) throw err
var cols = csvRows[0]
csvRows.shift()

// get indexes of the fields we need
var titleIndex = cols.indexOf('title')
var bodyIndex = cols.indexOf('description')
var labelsIndex = cols.indexOf('labels')
var milestoneIndex = cols.indexOf('milestone')
var assigneeIndex = cols.indexOf('assignee')
var stateIndex = cols.indexOf('state')

if (titleIndex === -1) {
console.error('Title required by GitHub, but not found in CSV.')
process.exit(1)
retObject.userOrOrganization = yield prompt("user or organization: ");
retObject.repo = yield prompt("repo: ");
return retObject;
}).then(
function (values) {
const ThrottledOctokit = Octokit.plugin(throttling);
const octokit = new ThrottledOctokit({
auth: values.token,
userAgent: "github-csv-tools",
baseUrl: values.githubUrl,
throttle: {
onRateLimit: (retryAfter, options) => {
console.warn(
`Request quota exhausted for request ${options.method} ${options.url}`
);

if (options.request.retryCount === 0) {
// only retries once
console.log(`Retrying after ${retryAfter} seconds!`);
return true;
}
},
onAbuseLimit: (retryAfter, options) => {
// does not retry, only logs a warning
console.warn(
`Abuse detected for request ${options.method} ${options.url}`
);
},
},
});

fs.readFile(file, "utf8", (err, data) => {
if (err) {
console.error("Error reading file.");
process.exit(1);
}
csvRows.forEach((row) => {
var sendObj = {
user: values.userOrOrganization,
repo: values.repo,
title: row[titleIndex]
}
csv.parse(
data,
{
trim: true,
},
(err, csvRows) => {
if (err) throw err;
var cols = csvRows[0];
csvRows.shift();

// if we have a body column, pass that.
if (bodyIndex > -1) {
sendObj.body = row[bodyIndex]
}
// get indexes of the fields we need
var titleIndex = cols.indexOf("title");
var bodyIndex = cols.indexOf("description");
var labelsIndex = cols.indexOf("labels");
var milestoneIndex = cols.indexOf("milestone");
var assigneeIndex = cols.indexOf("assignee");
var stateIndex = cols.indexOf("state");

// if we have a labels column, pass that.
if (labelsIndex > -1 && row[labelsIndex] !== '') {
sendObj.labels = row[labelsIndex].split(',')
}
if (titleIndex === -1) {
console.error(
"Title required by GitHub, but not found in CSV."
);
process.exit(1);
}
const createPromises = csvRows.map((row) => {
var sendObj = {
owner: values.userOrOrganization,
repo: values.repo,
title: row[titleIndex],
};

// if we have a milestone column, pass that.
if (milestoneIndex > -1 && row[milestoneIndex] !== '') {
sendObj.milestone = row[milestoneIndex]
}
// if we have a body column, pass that.
if (bodyIndex > -1) {
sendObj.body = row[bodyIndex];
}

// if we have an assignee column, pass that.
if (assigneeIndex > -1 && row[assigneeIndex] !== '') {
sendObj.assignee = row[assigneeIndex]
}
// if we have a labels column, pass that.
if (labelsIndex > -1 && row[labelsIndex] !== "") {
sendObj.labels = row[labelsIndex].split(",");
}

limiter.submit(github.issues.create, sendObj, function (err, res) {
// Debugging console.log(JSON.stringify(res));
if (err) { console.error('ERROR', err) } else {
console.log('===> Created issue #' + res.number)
// if we have a state column and state=closed, close the issue
if (stateIndex > -1 && row[stateIndex] === 'closed') {
console.log('===> Closing issue #' + res.number)
var updateIssue = {
user: values.userOrOrganization,
repo: values.repo,
number: res.number,
state: row[stateIndex]
}
limiter.submit(github.issues.edit, updateIssue, function (err, res) {
// Debugging console.log(JSON.stringify(res));
if (err) { console.error('ERROR', err) };
if (limiter.nbQueued() === 0 && limiter.nbRunning() === 0) {
process.exit(0)
}
})
} else {
if (limiter.nbQueued() === 0 && limiter.nbRunning() === 0) {
process.exit(0)
// if we have a milestone column, pass that.
if (milestoneIndex > -1 && row[milestoneIndex] !== "") {
sendObj.milestone = row[milestoneIndex];
}

// if we have an assignee column, pass that.
if (assigneeIndex > -1 && row[assigneeIndex] !== "") {
sendObj.assignees = row[assigneeIndex]
.replace(/ /g, "")
.split(",");
}

// console.log("sendObj", sendObj);
let state = false;
if (stateIndex > -1 && row[stateIndex] === "closed") {
state = row[stateIndex];
}
return createIssue(octokit, sendObj, state);
});

Promise.all(createPromises).then(
(res) => {
const successes = res.filter((cr) => {
return cr.status === 200 || cr.status === 201;
});
const fails = res.filter((cr) => {
return cr.status !== 200 && cr.status !== 201;
});

console.log(
`Created ${successes.length} issues, and had ${fails.length} failures.`
);
console.log(
"❤ ❗ If this project has provided you value, please ⭐ star the repo to show your support: ➡ https://github.com/gavinr/github-csv-tools"
);

if (fails.length > 0) {
console.log(fails);
}

process.exit(0);
},
(err) => {
console.error("Error");
console.error(err);
process.exit(0);
}
}
})
})
})
})
}, function (err) {
console.error('ERROR', err)
})
);
}
);
});
},
function (err) {
console.error("ERROR", err);
}
);
})
.parse(process.argv)
.parse(process.argv);
Loading

0 comments on commit 4f891b0

Please sign in to comment.