diff --git a/doc/self-hosting.md b/doc/self-hosting.md index 01c9ab09071d0..a49513aa7db7e 100644 --- a/doc/self-hosting.md +++ b/doc/self-hosting.md @@ -102,3 +102,11 @@ then you will need to replace `localhost` with the IP address of that virtual machine. [shields.example.env]: ../shields.example.env + + +Server secrets +-------------- + +You can add your own server secrets in `private/secret.json`. If you specify a +`gh_token` for Github, it will be used in place of the Shields token rotation +logic. diff --git a/lib/github-auth.js b/lib/github-auth.js index a553f3c795ca8..6a1d23252d324 100644 --- a/lib/github-auth.js +++ b/lib/github-auth.js @@ -4,13 +4,7 @@ const log = require('./log'); const queryString = require('query-string'); const request = require('request'); const autosave = require('json-autosave'); -let serverSecrets; -const baseUrl = process.env.BASE_URL || 'https://img.shields.io'; -try { - // Everything that cannot be checked in but is useful server-side - // is stored in this JSON data. - serverSecrets = require('../private/secret.json'); -} catch(e) {} +const serverSecrets = require('./server-secrets'); // This is an initial value which makes the code work while the initial data // is loaded. In the then() callback of scheduleAutosaving(), it's reassigned @@ -44,6 +38,8 @@ function cancelAutosaving() { } function setRoutes(server) { + const baseUrl = process.env.BASE_URL || 'https://shields.io'; + server.route(/^\/github-auth$/, function(data, match, end, ask) { if (!(serverSecrets && serverSecrets.gh_client_id)) { return end('This server is missing GitHub client secrets.'); @@ -229,6 +225,13 @@ function rmGithubToken(token) { } } +// When a global gh_token is configured, use that in place of our shields.io +// token-cycling logic. This produces more predictable behavior when a token +// is provided, and more predictable failures if that token is exhausted. +// +// You can manage your personal GitHub token at https://github.com/settings/tokens +const globalToken = (serverSecrets || {}).gh_token; + // Act like request(), but tweak headers and query to avoid hitting a rate // limit. function githubRequest(request, url, query, cb) { @@ -239,7 +242,8 @@ function githubRequest(request, url, query, cb) { 'User-Agent': 'Shields.io', 'Accept': 'application/vnd.github.v3+json', }; - const githubToken = getReqRemainingToken(); + + const githubToken = globalToken === null ? getReqRemainingToken() : globalToken; if (githubToken != null) { // Typically, GitHub user tokens grants us 12500 req/hour. @@ -253,8 +257,9 @@ function githubRequest(request, url, query, cb) { const qs = queryString.stringify(query); if (qs) { url += '?' + qs; } + request(url, {headers: headers}, function(err, res, buffer) { - if (githubToken != null && err === null) { + if (globalToken !== null && githubToken !== null && err === null) { if (res.statusCode === 401) { // Unauthorized. rmGithubToken(githubToken); } else {