-
-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use octokit and other deps updates (#12)
- Loading branch information
Showing
8 changed files
with
1,545 additions
and
959 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
module.exports = { | ||
"extends": "standard" | ||
}; | ||
extends: ["standard", "prettier"], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,3 +35,5 @@ jspm_packages | |
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |
Oops, something went wrong.