Skip to content

Commit

Permalink
Merge branch 'master' into frontend-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmelnikow authored Dec 10, 2018
2 parents 7b2eaeb + 0a98bd3 commit ca1581a
Show file tree
Hide file tree
Showing 19 changed files with 379 additions and 289 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ jobs:
name: Prepare service tests
command: |
mkdir private
echo "{\"gh_token\":\"$GITHUB_TOKEN\"}" > private/secret.json
echo "{\"gh_token\":\"$GITHUB_TOKEN\", \"wheelmap_token\":\"$WHEELMAP_TOKEN\"}" > private/secret.json
- restore_cache:
key: v2-dependencies-{{ checksum "package.json" }}
Expand Down
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
web: node server
web: npm run heroku-start && node server
4 changes: 4 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
"NPM_CONFIG_PRODUCTION": {
"description": "Configure whether devDependencies are installed (they are needed for the build).",
"value": "false"
},
"WHEELMAP_TOKEN": {
"description": "Configure the token to be used for the Wheelmap service.",
"required": false
}
},
"formation": {
Expand Down
8 changes: 6 additions & 2 deletions doc/self-hosting.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,15 @@ When a `gh_token` is specified, it is used in place of the Shields token
rotation logic.

You can also give your self-hosted Shields installation access to private npm
packages by [generating an npm token] and using that for the `npm_token` value.
packages by [generating an npm token][npm token] and using that for the `npm_token` value.

To integrate with Wheelmap.org, you can [sign into your account][wheelmap token] and use
the _Authentication Token_ displayed on your profile page for the `wheelmap_token` value.

[github rate limit]: https://developer.github.com/v3/#rate-limiting
[personal access tokens]: https://github.com/settings/tokens
[generating an npm token]: https://docs.npmjs.com/getting-started/working_with_tokens
[npm token]: https://docs.npmjs.com/getting-started/working_with_tokens
[wheelmap token]: http://classic.wheelmap.org/en/users/sign_in

Separate frontend hosting
-------------------------
Expand Down
20 changes: 20 additions & 0 deletions frontend/components/donate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react'

export default class DonateBox extends React.Component {
render() {
return (
<div>
<div id="donate">
Love Shields? Please consider{' '}
<a href="https://opencollective.com/shields">donating</a> to sustain
our activities
</div>
<style jsx>{`
#donate {
padding: 25px 50px;
}
`}</style>
</div>
)
}
}
11 changes: 2 additions & 9 deletions frontend/components/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
import Meta from './meta'
import Header from './header'
import SuggestionAndSearch from './suggestion-and-search'
import DonateBox from './donate'
import MarkupModal from './markup-modal'
import Usage from './usage'
import Footer from './footer'
Expand Down Expand Up @@ -155,19 +156,11 @@ export default class Main extends React.Component {
baseUrl={baseUrl}
longCache={longCache}
/>
<a className="donate" href="https://opencollective.com/shields">
donate
</a>
<DonateBox />
</section>
{this.renderMain()}
<Usage baseUrl={baseUrl} longCache={longCache} />
<Footer baseUrl={baseUrl} />
<style jsx>{`
.donate {
text-decoration: none;
color: rgba(0, 0, 0, 0.1);
}
`}</style>
</div>
)
}
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
"defs": "node scripts/export-service-definitions-cli.js > service-definitions.yml",
"build": "npm run defs && npm run features && BABEL_ENV=dev-prod next build && BABEL_ENV=dev-prod next export -o build/",
"heroku-postbuild": "npm run build",
"heroku-start": "node scripts/export-heroku-secrets-cli.js",
"analyze": "ANALYZE=true LONG_CACHE=false BASE_URL=https://img.shields.io npm run build",
"start:server": "HANDLE_INTERNAL_ERRORS=false RATE_LIMIT=false node server 8080 ::",
"now-start": "node server",
Expand Down Expand Up @@ -120,7 +121,7 @@
"chainsmoker": "^0.1.0",
"child-process-promise": "^2.2.1",
"concurrently": "^4.1.0",
"danger": "^6.1.9",
"danger": "^6.1.11",
"danger-plugin-no-test-shortcuts": "^2.0.0",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16": "^1.7.0",
Expand Down
19 changes: 19 additions & 0 deletions scripts/export-heroku-secrets-cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict'

const fs = require('fs')
const path = require('path')

const secretsPath = path.join(__dirname, '..', 'private', 'secret.json')

if (fs.existsSync(secretsPath)) {
console.log('Found existing private/secret.json, not overwriting.')
} else {
console.log('private/secret.json does not exist, creating.')
const privatePath = path.dirname(secretsPath)
if (!fs.existsSync(privatePath)) {
fs.mkdirSync(privatePath)
}
const secrets = { wheelmap_token: process.env.WHEELMAP_TOKEN }
const secretsString = JSON.stringify(secrets)
fs.writeFileSync(secretsPath, secretsString)
}
15 changes: 8 additions & 7 deletions secret.tpl.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"gh_client_id": "${GH_CLIENT_ID}",
"gh_client_secret": "${GH_CLIENT_SECRET}",
"shieldsIps": [ "${SHIELDS_IP}" ],
"gh_token": "${GH_TOKEN}",
"npm_token": "${NPM_TOKEN}"
}
{
"gh_client_id": "${GH_CLIENT_ID}",
"gh_client_secret": "${GH_CLIENT_SECRET}",
"shieldsIps": [ "${SHIELDS_IP}" ],
"gh_token": "${GH_TOKEN}",
"npm_token": "${NPM_TOKEN}",
"wheelmap_token": "${WHEELMAP_TOKEN}"
}
78 changes: 36 additions & 42 deletions services/bountysource/bountysource.service.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,58 @@
'use strict'

const LegacyService = require('../legacy-service')
const { makeBadgeData: getBadgeData } = require('../../lib/badge-data')
const BaseJsonService = require('../base-json')
const Joi = require('joi')
const { nonNegativeInteger } = require('../validators')
const { metric } = require('../../lib/text-formatters')

const schema = Joi.object({ activity_total: nonNegativeInteger })

module.exports = class Bountysource extends BaseJsonService {
async fetch({ team }) {
const url = `https://api.bountysource.com/teams/${team}`
return this._requestJson({
schema,
url,
options: {
headers: { Accept: 'application/vnd.bountysource+json; version=2' },
},
})
}

module.exports = class Bountysource extends LegacyService {
static get category() {
return 'funding'
}

static get defaultBadgeData() {
return { label: 'bounties' }
}

static get route() {
return {
base: 'bountysource',
base: 'bountysource/team',
pattern: ':team/activity',
}
}

static get examples() {
return [
{
title: 'Bountysource',
previewUrl: 'team/mozilla-core/activity',
namedParams: { team: 'mozilla-core' },
staticExample: this.render({ total: 53000 }),
},
]
}

static registerLegacyRouteHandler({ camp, cache }) {
camp.route(
/^\/bountysource\/team\/([^/]+)\/activity\.(svg|png|gif|jpg|json)$/,
cache((data, match, sendBadge, request) => {
const team = match[1] // eg, `mozilla-core`.
const format = match[2]
const url = `https://api.bountysource.com/teams/${team}`
const options = {
headers: { Accept: 'application/vnd.bountysource+json; version=2' },
}
const badgeData = getBadgeData('bounties', data)
request(url, options, (err, res, buffer) => {
if (err != null) {
badgeData.text[1] = 'inaccessible'
sendBadge(format, badgeData)
return
}
try {
if (res.statusCode !== 200) {
throw Error('Bad response.')
}
const parsedData = JSON.parse(buffer)
const activity = parsedData.activity_total
badgeData.colorscheme = 'brightgreen'
badgeData.text[1] = activity
sendBadge(format, badgeData)
} catch (e) {
if (res.statusCode === 404) {
badgeData.text[1] = 'not found'
} else {
badgeData.text[1] = 'invalid'
}
sendBadge(format, badgeData)
}
})
})
)
static render({ total }) {
return {
message: metric(total),
color: 'brightgreen',
}
}

async handle({ team }) {
const json = await this.fetch({ team })
return this.constructor.render({ total: json.activity_total })
}
}
32 changes: 2 additions & 30 deletions services/bountysource/bountysource.tester.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const Joi = require('joi')
const ServiceTester = require('../service-tester')
const { invalidJSON } = require('../response-fixtures')
const { isMetric } = require('../test-validators')

const t = (module.exports = new ServiceTester({
id: 'bountysource',
Expand All @@ -14,9 +14,7 @@ t.create('bounties (valid)')
.expectJSONTypes(
Joi.object().keys({
name: 'bounties',
value: Joi.number()
.integer()
.positive(),
value: isMetric,
})
)

Expand All @@ -26,29 +24,3 @@ t.create('bounties (invalid team)')
name: 'bounties',
value: 'not found',
})

t.create('bounties (connection error)')
.get('/team/mozilla-core/activity.json')
.networkOff()
.expectJSON({ name: 'bounties', value: 'inaccessible' })

t.create('bounties (unexpected response)')
.get('/team/mozilla-core/activity.json')
.intercept(nock =>
nock('https://api.bountysource.com')
.get('/teams/mozilla-core')
.reply(invalidJSON)
)
.expectJSON({ name: 'bounties', value: 'invalid' })

t.create('bounties (error response)')
.get('/team/mozilla-core/activity.json')
.intercept(nock =>
nock('https://api.bountysource.com')
.get('/teams/mozilla-core')
.reply(500, '{"error":"oh noes!!"}')
)
.expectJSON({
name: 'bounties',
value: 'invalid',
})
2 changes: 1 addition & 1 deletion services/codetally/codetally.tester.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ t.create('Empty')
currency_abbreviation: 'CAD',
})
)
.expectJSON({ name: 'codetally', value: ' $0.00 ' })
.expectJSON({ name: 'codetally', value: '$0.00' })
Loading

0 comments on commit ca1581a

Please sign in to comment.