Skip to content

Commit

Permalink
feat: support Github Enterprise (#97)
Browse files Browse the repository at this point in the history
* add isEnterprise config option and add function to change hostname if on enterprise

* add hipstersmoothie as contributor

* infer enterprise API

* handle enterprise authentication

* add tylerkrupicka as a contributor

Co-authored-by: Tyler Krupicka <[email protected]>
Co-authored-by: Maximilian Berkmann <[email protected]>
  • Loading branch information
3 people committed Jan 17, 2020
1 parent 4f40750 commit 0965095
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 22 deletions.
10 changes: 10 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,16 @@
"code"
]
},
{
"login": "tylerkrupicka",
"name": "Tyler Krupicka",
"avatar_url": "https://avatars1.githubusercontent.com/u/5761061?s=460&v=4",
"profile": "https://github.com/tylerkrupicka",
"contributions": [
"code",
"test"
]
},
{
"login": "smoia",
"name": "Stefano Moia",
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

- [ all-contributors-cli ](#all-contributors-cli)
- [The problem](#the-problem)
- [This solution](#this-solution)
- [Using the all-contributors-cli](#using-the-all-contributors-cli)
- [Contributors ✨](#contributors-)
- [LICENSE](#license)
- [The problem](#the-problem)
- [This solution](#this-solution)
- [Using the all-contributors-cli](#using-the-all-contributors-cli)
- [Contributors ✨](#contributors-%e2%9c%a8)
- [LICENSE](#license)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Expand Down Expand Up @@ -130,6 +129,7 @@ Thanks goes to these wonderful people
<td align="center"><a href="https://www.destro.me"><img src="https://avatars1.githubusercontent.com/u/7031675?v=4" width="100px;" alt=""/><br /><sub><b>Fabrizio</b></sub></a><br /><a href="https://github.com/all-contributors/all-contributors-cli/issues?q=author%3Adexpota" title="Bug reports">🐛</a> <a href="https://github.com/all-contributors/all-contributors-cli/commits?author=dexpota" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/marceloalves"><img src="https://avatars1.githubusercontent.com/u/216782?v=4" width="100px;" alt=""/><br /><sub><b>Marcelo Alves</b></sub></a><br /><a href="https://github.com/all-contributors/all-contributors-cli/commits?author=MarceloAlves" title="Code">💻</a></td>
<td align="center"><a href="https://phacks.dev/"><img src="https://avatars1.githubusercontent.com/u/2587348?v=4" width="100px;" alt=""/><br /><sub><b>Nicolas Goutay</b></sub></a><br /><a href="https://github.com/all-contributors/all-contributors-cli/commits?author=phacks" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/tylerkrupicka"><img src="https://avatars1.githubusercontent.com/u/5761061?s=460&v=4" width="100px;" alt=""/><br /><sub><b>Tyler Krupicka</b></sub></a><br /><a href="https://github.com/all-contributors/all-contributors-cli/commits?author=tylerkrupicka" title="Code">💻</a> <a href="https://github.com/all-contributors/all-contributors-cli/commits?author=tylerkrupicka" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/smoia"><img src="https://avatars3.githubusercontent.com/u/35300580?v=4" width="100px;" alt=""/><br /><sub><b>Stefano Moia</b></sub></a><br /><a href="https://github.com/all-contributors/all-contributors-cli/commits?author=smoia" title="Code">💻</a></td>
</tr>
</table>
Expand Down
17 changes: 16 additions & 1 deletion src/repo/__tests__/github.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,21 @@ test('Throw error when non existent username is provided', async () => {
)
})

test('Throw error when missing enterprise authentication', async () => {
const username = 'notauthenticated'
nock('http://github.myhost.com:3000/api/v3')
.get(`/users/${username}`)
.reply(401, {
message: 'Must authenticate to access this API.',
documentation_url: 'https://developer.github.com/enterprise/2.17/v3',
})
await expect(
getUserInfo(username, 'http://github.myhost.com:3000'),
).rejects.toThrow(
`Missing authentication for GitHub API. Did you set PRIVATE_TOKEN?`,
)
})

test('handle github errors', async () => {
nock('https://api.github.com')
.get('/users/nodisplayname')
Expand Down Expand Up @@ -174,7 +189,7 @@ test('append http when no absolute link is provided', async () => {
})

test('retrieve user from a different github registry', async () => {
nock('http://api.github.myhost.com:3000')
nock('http://github.myhost.com:3000/api/v3')
.get('/users/nodisplayname')
.reply(200, {
login: 'nodisplayname',
Expand Down
52 changes: 37 additions & 15 deletions src/repo/github.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
const url = require('url')
const pify = require('pify')
const request = pify(require('request'))

/**
* Get the host based on public or enterprise GitHub.
* https://developer.github.com/enterprise/2.17/v3/#current-version
*
* @param {String} hostname - Hostname from config.
* @returns {String} - Host for GitHub API.
*/
function getApiHost(hostname) {
if (!hostname) {
hostname = 'https://github.com'
}

if (hostname !== 'https://github.com') {
// Assume Github Enterprise
return url.resolve(hostname, '/api/v3')
}

return hostname.replace(/:\/\//, '://api.')
}

function getRequestHeaders(optionalPrivateToken = '') {
const requestHeaders = {
'User-Agent': 'request',
Expand All @@ -27,10 +48,10 @@ function getNextLink(link) {
return nextLink.split(';')[0].slice(1, -1)
}

function getContributorsPage(url, optionalPrivateToken) {
function getContributorsPage(githubUrl, optionalPrivateToken) {
return request
.get({
url,
url: githubUrl,
headers: getRequestHeaders(optionalPrivateToken),
})
.then(res => {
Expand All @@ -55,18 +76,13 @@ function getContributorsPage(url, optionalPrivateToken) {
}

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

if (!username) {
throw new Error(
`No login when adding a contributor. Please specify a username.`,
)
}

const root = hostname.replace(/:\/\//, '://api.')
const root = getApiHost(hostname)
return request
.get({
url: `${root}/users/${username}`,
Expand All @@ -77,6 +93,16 @@ const getUserInfo = function(username, hostname, optionalPrivateToken) {

let profile = body.blog || body.html_url

// Check for authentication required
if (
(!profile && body.message.includes('Must authenticate')) ||
res.statusCode === 401
) {
throw new Error(
`Missing authentication for GitHub API. Did you set PRIVATE_TOKEN?`,
)
}

// Github throwing specific errors as 200...
if (!profile && body.message) {
throw new Error(
Expand All @@ -96,13 +122,9 @@ const getUserInfo = function(username, hostname, optionalPrivateToken) {
}

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

const root = hostname.replace(/:\/\//, '://api.')
const url = `${root}/repos/${owner}/${name}/contributors?per_page=100`
return getContributorsPage(url, optionalPrivateToken)
const root = getApiHost(hostname)
const contributorsUrl = `${root}/repos/${owner}/${name}/contributors?per_page=100`
return getContributorsPage(contributorsUrl, optionalPrivateToken)
}

module.exports = {
Expand Down

0 comments on commit 0965095

Please sign in to comment.