Skip to content

Commit

Permalink
feat: support Gitlab self hosted instance(#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
xuchaoying committed Jun 1, 2018
1 parent c4a0484 commit 99d6e1d
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 77 deletions.
12 changes: 11 additions & 1 deletion .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,16 @@
"doc",
"ideas"
]
},
{
"login": "xuchaoying",
"name": "C.Y.Xu",
"avatar_url": "https://avatars2.githubusercontent.com/u/8073251?v=4",
"profile": "https://github.com/xuchaoying",
"contributions": [
"code"
]
}
]
],
"repoType": "github"
}
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
[![version][version-badge]][package] [![downloads][downloads-badge]][downloads]
[![MIT License][license-badge]][license]

[![All Contributors](https://img.shields.io/badge/all_contributors-21-orange.svg?style=flat-square)](#contributors)
[![All Contributors](https://img.shields.io/badge/all_contributors-22-orange.svg?style=flat-square)](#contributors)
[![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc]
[![Watch on GitHub][github-watch-badge]][github-watch]
[![Star on GitHub][github-star-badge]][github-star]
Expand Down Expand Up @@ -158,6 +158,7 @@ These are the keys you can specify:
--> `all-contributors-cli`. Mandatory.
* `repoType`: Type of repository. Must be either `github` or `gitlab`. Default: `github`.
* `repoHost`: Points to the repository hostname. Change it if you use a self hosted repository. Default: `https://github.com` if `repoType` is `github`, and `https://gitlab.com` if `repoType` is `gitlab`.
* `private_token`: The personal access token to to authenticate with the GitLab API. Offer it if you use a self hosted repository. Default: `''`.
* `types`: Specify custom symbols or link templates for contribution types. Can
override the documented types.
* `imageSize`: Size (in px) of the user's avatar. Default: `100`.
Expand All @@ -178,7 +179,7 @@ Thanks goes to these wonderful people
| :---: | :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars3.githubusercontent.com/u/8212?v=3" width="100px;"/><br /><sub><b>Jerod Santo</b></sub>](https://jerodsanto.net)<br />[💻](https://github.com/jfmengels/all-contributors-cli/commits?author=jerodsanto "Code") | [<img src="https://avatars1.githubusercontent.com/u/574871?v=3" width="100px;"/><br /><sub><b>Kevin Jalbert</b></sub>](https://github.com/kevinjalbert)<br />[💻](https://github.com/jfmengels/all-contributors-cli/commits?author=kevinjalbert "Code") | [<img src="https://avatars3.githubusercontent.com/u/5038030?v=4" width="100px;"/><br /><sub><b>tunnckoCore</b></sub>](https://i.am.charlike.online)<br />[🔧](#tool-charlike "Tools") | [<img src="https://avatars2.githubusercontent.com/u/304450?v=4" width="100px;"/><br /><sub><b>Mehdi Achour</b></sub>](https://machour.idk.tn/)<br />[💻](https://github.com/jfmengels/all-contributors-cli/commits?author=machour "Code") | [<img src="https://avatars1.githubusercontent.com/u/8344688?v=4" width="100px;"/><br /><sub><b>Roy Revelt</b></sub>](https://codsen.com)<br />[🐛](https://github.com/jfmengels/all-contributors-cli/issues?q=author%3Arevelt "Bug reports") | [<img src="https://avatars1.githubusercontent.com/u/422331?v=4" width="100px;"/><br /><sub><b>Chris Vickery</b></sub>](https://github.com/chrisinajar)<br />[💻](https://github.com/jfmengels/all-contributors-cli/commits?author=chrisinajar "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/1026002?v=4" width="100px;"/><br /><sub><b>Bryce Reynolds</b></sub>](https://github.com/brycereynolds)<br />[💻](https://github.com/jfmengels/all-contributors-cli/commits?author=brycereynolds "Code") | [<img src="https://avatars3.githubusercontent.com/u/2322305?v=4" width="100px;"/><br /><sub><b>James, please</b></sub>](http://www.jmeas.com)<br />[🤔](#ideas-jmeas "Ideas, Planning, & Feedback") [💻](https://github.com/jfmengels/all-contributors-cli/commits?author=jmeas "Code") | [<img src="https://avatars3.githubusercontent.com/u/1057324?v=4" width="100px;"/><br /><sub><b>Spyros Ioakeimidis</b></sub>](http://www.spyros.io)<br />[💻](https://github.com/jfmengels/all-contributors-cli/commits?author=spirosikmd "Code") | [<img src="https://avatars3.githubusercontent.com/u/12335761?v=4" width="100px;"/><br /><sub><b>Fernando Costa</b></sub>](https://github.com/fadc80)<br />[💻](https://github.com/jfmengels/all-contributors-cli/commits?author=fadc80 "Code") | [<img src="https://avatars0.githubusercontent.com/u/197404?v=4" width="100px;"/><br /><sub><b>snipe</b></sub>](https://snipe.net)<br />[📖](https://github.com/jfmengels/all-contributors-cli/commits?author=snipe "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/997157?v=4" width="100px;"/><br /><sub><b>Gant Laborde</b></sub>](http://gantlaborde.com/)<br />[💻](https://github.com/jfmengels/all-contributors-cli/commits?author=GantMan "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/17708702?v=4" width="100px;"/><br /><sub><b>Md Zubair Ahmed</b></sub>](https://in.linkedin.com/in/mzubairahmed)<br />[📖](https://github.com/jfmengels/all-contributors-cli/commits?author=M-ZubairAhmed "Documentation") [🐛](https://github.com/jfmengels/all-contributors-cli/issues?q=author%3AM-ZubairAhmed "Bug reports") | [<img src="https://avatars3.githubusercontent.com/u/6177621?v=4" width="100px;"/><br /><sub><b>Divjot Singh</b></sub>](http://bogas04.github.io)<br />[📖](https://github.com/jfmengels/all-contributors-cli/commits?author=bogas04 "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/15315098?v=4" width="100px;"/><br /><sub><b>João Marques</b></sub>](https://github.com/tigermarques)<br />[💻](https://github.com/jfmengels/all-contributors-cli/commits?author=tigermarques "Code") [📖](https://github.com/jfmengels/all-contributors-cli/commits?author=tigermarques "Documentation") [🤔](#ideas-tigermarques "Ideas, Planning, & Feedback") |
| [<img src="https://avatars2.githubusercontent.com/u/17708702?v=4" width="100px;"/><br /><sub><b>Md Zubair Ahmed</b></sub>](https://in.linkedin.com/in/mzubairahmed)<br />[📖](https://github.com/jfmengels/all-contributors-cli/commits?author=M-ZubairAhmed "Documentation") [🐛](https://github.com/jfmengels/all-contributors-cli/issues?q=author%3AM-ZubairAhmed "Bug reports") [💻](https://github.com/jfmengels/all-contributors-cli/commits?author=M-ZubairAhmed "Code") [⚠️](https://github.com/jfmengels/all-contributors-cli/commits?author=M-ZubairAhmed "Tests") | [<img src="https://avatars3.githubusercontent.com/u/6177621?v=4" width="100px;"/><br /><sub><b>Divjot Singh</b></sub>](http://bogas04.github.io)<br />[📖](https://github.com/jfmengels/all-contributors-cli/commits?author=bogas04 "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/15315098?v=4" width="100px;"/><br /><sub><b>João Marques</b></sub>](https://github.com/tigermarques)<br />[💻](https://github.com/jfmengels/all-contributors-cli/commits?author=tigermarques "Code") [📖](https://github.com/jfmengels/all-contributors-cli/commits?author=tigermarques "Documentation") [🤔](#ideas-tigermarques "Ideas, Planning, & Feedback") | [<img src="https://avatars2.githubusercontent.com/u/8073251?v=4" width="100px;"/><br /><sub><b>C.Y.Xu</b></sub>](https://github.com/xuchaoying)<br />[💻](https://github.com/jfmengels/all-contributors-cli/commits?author=xuchaoying "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the
Expand Down
31 changes: 19 additions & 12 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,13 @@ function checkContributors(argv) {
const configData = util.configFile.readConfig(argv.config)

return repo
.getContributors(configData.projectOwner, configData.projectName, configData.repoType, configData.repoHost)
.getContributors(
configData.projectOwner,
configData.projectName,
configData.repoType,
configData.repoHost,
configData.private_token,
)
.then(repoContributors => {
const checkKey = repo.getCheckKey(configData.repoType)
const knownContributions = configData.contributors.reduce((obj, item) => {
Expand Down Expand Up @@ -138,7 +144,8 @@ function promptForCommand(argv) {
value: 'generate',
},
{
name: 'Compare contributors from the repository with the credited ones',
name:
'Compare contributors from the repository with the credited ones',
value: 'check',
},
],
Expand All @@ -155,16 +162,16 @@ function promptForCommand(argv) {
promptForCommand(yargv)
.then(command => {
switch (command) {
case 'init':
return init()
case 'generate':
return startGeneration(yargv)
case 'add':
return addContribution(yargv)
case 'check':
return checkContributors(yargv)
default:
throw new Error(`Unknown command ${command}`)
case 'init':
return init()
case 'generate':
return startGeneration(yargv)
case 'add':
return addContribution(yargv)
case 'check':
return checkContributors(yargv)
default:
throw new Error(`Unknown command ${command}`)
}
})
.catch(onError)
7 changes: 6 additions & 1 deletion src/contributors/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@ function updateExistingContributor(options, username, contributions) {
}

function addNewContributor(options, username, contributions, infoFetcher) {
return infoFetcher(username, options.repoType, options.repoHost).then(userData => {
return infoFetcher(
username,
options.repoType,
options.repoHost,
options.private_token,
).then(userData => {
const contributor = _.assign(userData, {
contributions: formatContributions(options, [], contributions),
})
Expand Down
13 changes: 12 additions & 1 deletion src/init/prompt.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ const questions = [
}
},
},
{
type: 'input',
name: 'private_token',
message:
'What is the personal access token? (If you use a self hosted repository)',
default: '',
},
{
type: 'input',
name: 'contributorFile',
Expand Down Expand Up @@ -79,7 +86,10 @@ const questions = [
},
]

const uniqueFiles = _.flow(_.compact, _.uniq)
const uniqueFiles = _.flow(
_.compact,
_.uniq,
)

module.exports = function prompt() {
return git
Expand All @@ -98,6 +108,7 @@ module.exports = function prompt() {
projectOwner: answers.projectOwner,
repoType: answers.repoType,
repoHost: answers.repoHost,
private_token: answers.private_token,
files: uniqueFiles([answers.contributorFile, answers.badgeFile]),
imageSize: answers.imageSize,
commit: answers.commit,
Expand Down
113 changes: 81 additions & 32 deletions src/repo/__tests__/gitlab.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@ test('handle errors', async () => {
test('fill in the name when it is returned', async () => {
nock('https://gitlab.com')
.get('/api/v4/users?username=nodisplayname')
.reply(200, [{
username: 'nodisplayname',
name: 'No Display Name',
avatar_url: 'http://www.gravatar.com/avatar/3186450a99d1641bf75a44baa23f0826?s=80\u0026d=identicon',
web_url: 'https://gitlab.com/nodisplayname',
}])
.reply(200, [
{
username: 'nodisplayname',
name: 'No Display Name',
avatar_url:
'http://www.gravatar.com/avatar/3186450a99d1641bf75a44baa23f0826?s=80\u0026d=identicon',
web_url: 'https://gitlab.com/nodisplayname',
},
])

const info = await getUserInfo('nodisplayname')
expect(info.name).toBe('No Display Name')
Expand All @@ -33,12 +36,15 @@ test('fill in the name when it is returned', async () => {
test('fill in the name when null is returned', async () => {
nock('https://gitlab.com')
.get('/api/v4/users?username=nodisplayname')
.reply(200, [{
username: 'nodisplayname',
name: null,
avatar_url: 'http://www.gravatar.com/avatar/3186450a99d1641bf75a44baa23f0826?s=80\u0026d=identicon',
web_url: 'https://gitlab.com/nodisplayname',
}])
.reply(200, [
{
username: 'nodisplayname',
name: null,
avatar_url:
'http://www.gravatar.com/avatar/3186450a99d1641bf75a44baa23f0826?s=80\u0026d=identicon',
web_url: 'https://gitlab.com/nodisplayname',
},
])

const info = await getUserInfo('nodisplayname')
expect(info.name).toBe('nodisplayname')
Expand All @@ -47,12 +53,15 @@ test('fill in the name when null is returned', async () => {
test('fill in the name when an empty string is returned', async () => {
nock('https://gitlab.com')
.get('/api/v4/users?username=nodisplayname')
.reply(200, [{
username: 'nodisplayname',
name: '',
avatar_url: 'http://www.gravatar.com/avatar/3186450a99d1641bf75a44baa23f0826?s=80\u0026d=identicon',
web_url: 'https://gitlab.com/nodisplayname',
}])
.reply(200, [
{
username: 'nodisplayname',
name: '',
avatar_url:
'http://www.gravatar.com/avatar/3186450a99d1641bf75a44baa23f0826?s=80\u0026d=identicon',
web_url: 'https://gitlab.com/nodisplayname',
},
])

const info = await getUserInfo('nodisplayname')
expect(info.name).toBe('nodisplayname')
Expand All @@ -61,12 +70,15 @@ test('fill in the name when an empty string is returned', async () => {
test('append http when no absolute link is provided', async () => {
nock('https://gitlab.com')
.get('/api/v4/users?username=nodisplayname')
.reply(200, [{
username: 'nodisplayname',
name: 'No Display Name',
avatar_url: 'http://www.gravatar.com/avatar/3186450a99d1641bf75a44baa23f0826?s=80\u0026d=identicon',
web_url: 'www.gitlab.com/nodisplayname',
}])
.reply(200, [
{
username: 'nodisplayname',
name: 'No Display Name',
avatar_url:
'http://www.gravatar.com/avatar/3186450a99d1641bf75a44baa23f0826?s=80\u0026d=identicon',
web_url: 'www.gitlab.com/nodisplayname',
},
])

const info = await getUserInfo('nodisplayname')
expect(info.profile).toBe('http://www.gitlab.com/nodisplayname')
Expand All @@ -75,13 +87,50 @@ test('append http when no absolute link is provided', async () => {
test('retrieve user from a different gitlab registry', async () => {
nock('http://gitlab.myhost.com:3000')
.get('/api/v4/users?username=nodisplayname')
.reply(200, [{
username: 'nodisplayname',
name: 'No Display Name',
avatar_url: 'http://www.gravatar.com/avatar/3186450a99d1641bf75a44baa23f0826?s=80\u0026d=identicon',
web_url: 'https://gitlab.com/nodisplayname',
}])

const info = await getUserInfo('nodisplayname', 'http://gitlab.myhost.com:3000')
.reply(200, [
{
username: 'nodisplayname',
name: 'No Display Name',
avatar_url:
'http://www.gravatar.com/avatar/3186450a99d1641bf75a44baa23f0826?s=80\u0026d=identicon',
web_url: 'https://gitlab.com/nodisplayname',
},
])

const info = await getUserInfo(
'nodisplayname',
'http://gitlab.myhost.com:3000',
)
expect(info.name).toBe('No Display Name')
})

test('retrieve user from a gitlab registry that needs a token', async () => {
nock('http://gitlab.needtoken.com:3000')
.get('/api/v4/users?username=nodisplayname&private_token=faketoken')
.reply(200, [
{
username: 'nodisplayname',
name: 'No Display Name',
avatar_url:
'http://www.gravatar.com/avatar/3186450a99d1641bf75a44baa23f0826?s=80\u0026d=identicon',
web_url: 'https://gitlab.com/nodisplayname',
},
])

const info = await getUserInfo(
'nodisplayname',
'http://gitlab.needtoken.com:3000',
'faketoken',
)
expect(info.name).toBe('No Display Name')
})

test('handle error when no token is offered', async () => {
nock('http://gitlab.needtoken.com:3000')
.get('/api/v4/users?username=nodisplayname')
.reply(200, [])

await rejects(
getUserInfo('nodisplayname', 'http://gitlab.needtoken.com:3000', ''),
)
})
39 changes: 29 additions & 10 deletions src/repo/gitlab.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
const pify = require('pify')
const request = pify(require('request'))

const getUserInfo = function(username, hostname) {
const addPrivateToken = (url, private_token = '') => {
if (private_token === '') return url

return `${url}&private_token=${private_token}`
.replace(/\?/g, '&')
.replace('&', '?')
}

const getUserInfo = function(username, hostname, private_token = '') {
/* eslint-disable complexity */
if (!hostname) {
hostname = 'https://gitlab.com';
hostname = 'https://gitlab.com'
}

return request
.get({
url: `${hostname}/api/v4/users?username=${username}`,
url: addPrivateToken(
`${hostname}/api/v4/users?username=${username}`,
private_token,
),
headers: {
'User-Agent': 'request',
},
Expand All @@ -28,19 +39,24 @@ const getUserInfo = function(username, hostname) {
login: user.username,
name: user.name || username,
avatar_url: user.avatar_url,
profile: user.web_url.startsWith('http') ? user.web_url : `http://${user.web_url}`,
profile: user.web_url.startsWith('http')
? user.web_url
: `http://${user.web_url}`,
}
})
}

const getContributors = function(owner, name, hostname) {
const getContributors = function(owner, name, hostname, private_token = '') {
if (!hostname) {
hostname = 'https://gitlab.com';
hostname = 'https://gitlab.com'
}

return request
.get({
url: `${hostname}/api/v4/projects?search=${name}`,
url: addPrivateToken(
`${hostname}/api/v4/projects?search=${name}`,
private_token,
),
headers: {
'User-Agent': 'request',
},
Expand All @@ -57,7 +73,7 @@ const getContributors = function(owner, name, hostname) {
for (let i = 0; i < projects.length; i++) {
if (projects[i].path_with_namespace === `${owner}/${name}`) {
project = projects[i]
break;
break
}
}

Expand All @@ -67,7 +83,10 @@ const getContributors = function(owner, name, hostname) {

return request
.get({
url: `${hostname}/api/v4/projects/${project.id}/repository/contributors`,
url: addPrivateToken(
`${hostname}/api/v4/projects/${project.id}/repository/contributors`,
private_token,
),
headers: {
'User-Agent': 'request',
},
Expand All @@ -87,5 +106,5 @@ const getContributors = function(owner, name, hostname) {

module.exports = {
getUserInfo,
getContributors
getContributors,
}
Loading

0 comments on commit 99d6e1d

Please sign in to comment.