Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bitbucket]: Pull Requests: Support Bitbucket Server #2598

Merged
merged 21 commits into from
Jan 12, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
687f897
New Service: Bitbucket Server: Pull Request Count
Dec 27, 2018
4840fa2
[Bitbucket]: Pull Requests: Add Support for bitbucket-server
Dec 28, 2018
50f6ca0
Update examples to use namedParams instead of exampleUrl
Dec 28, 2018
68049c9
Simplify cloud vs server check
Dec 28, 2018
eaa91de
[Bitbucket]: Add support for bitbucket cloud private repos
Dec 28, 2018
7415736
Merge branch 'master' into feat/GH-1757-Bitbucket-Server
calebcartwright Dec 28, 2018
c308d5e
Add additional tests for bitbucket server
Dec 28, 2018
1987a9d
[Bitbucket]: Add tests for basic auth
Dec 28, 2018
0474a22
[Bitbucket] Format secrets according to style guides
Dec 31, 2018
b728dc9
[Bitbucket] Add link to server REST documentation
Dec 31, 2018
c7860eb
Merge branch 'master' into feat/GH-1757-Bitbucket-Server
paulmelnikow Jan 1, 2019
e7bc227
Punt adding VSCode debug task to separate PR
Jan 7, 2019
3237255
[Bitbucket] Remove extra truthy check on serverSecrets
Jan 7, 2019
bb2aca0
[Bitbucket] Fix credentials after rename
Jan 7, 2019
d43f080
[Bitbucket] Use query parameters for Bitbucket Server support
Jan 7, 2019
5a39a7a
Fix bitbucket creds in secret template
Jan 7, 2019
59fd4c0
Merge branch 'master' into feat/GH-1757-Bitbucket-Server
Jan 7, 2019
250d9b9
[Bitbucket] staticExample -> staticPreview
Jan 7, 2019
c37e35c
Merge branch 'master' into feat/GH-1757-Bitbucket-Server
calebcartwright Jan 12, 2019
79c14da
Remove VSCode specific gitignore entries
nlowe Jan 12, 2019
1327bce
[Bitbucket] Normalize pluralization of PullReqeust(s) to match file name
nlowe Jan 12, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ node_modules/
shields.env
.git/
.gitignore
.vscode/
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Project-specific files
/.vscode
/Verdana.ttf
/analytics.json
/coverage.html
Expand Down
30 changes: 9 additions & 21 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
"heroku-postbuild": "run-s --silent build",
"analyze": "cross-env ANALYZE=true LONG_CACHE=false BASE_URL=https://img.shields.io npm run build",
"start:server": "cross-env HANDLE_INTERNAL_ERRORS=false RATE_LIMIT=false node server 8080 ::",
"start:server:debug": "cross-env ALLOWED_ORIGIN=http://localhost:3000 HANDLE_INTERNAL_ERRORS=false RATE_LIMIT=false node --nolazy --inspect=9229 server 8080 ::",
"now-start": "node server",
"heroku-start": "node scripts/export-heroku-secrets-cli.js && node server",
"prestart": "run-s --silent depcheck defs features",
Expand Down
20 changes: 12 additions & 8 deletions secret.tpl.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{
"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}"
}
{
"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}",
"bitbucket_username": "${BITBUCKET_USERNAME}",
"bitbucket_password": "${BITBUCKET_PASSWORD}",
"bitbucket_server_username": "${BITBUCKET_SERVER_USERNAME}",
"bitbucket_server_password": "${BITBUCKET_SERVER_PASSWORD}"
}
89 changes: 77 additions & 12 deletions services/bitbucket/bitbucket-pull-request.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const Joi = require('joi')
const BaseJsonService = require('../base-json')
const serverSecrets = require('../../lib/server-secrets')
const { metric } = require('../../lib/text-formatters')
const { nonNegativeInteger } = require('../validators')

Expand All @@ -14,14 +15,64 @@ function pullRequestClassGenerator(raw) {
const badgeSuffix = raw ? '' : ' open'

return class BitbucketPullRequests extends BaseJsonService {
async fetch({ user, repo }) {
const url = `https://bitbucket.org/api/2.0/repositories/${user}/${repo}/pullrequests/`
return this._requestJson({
url,
async fetchCloud({ args, user, repo }) {
args.url = `https://bitbucket.org/api/2.0/repositories/${user}/${repo}/pullrequests/`
args.options = { qs: { state: 'OPEN', limit: 0 } }

if (
serverSecrets &&
serverSecrets.bitbucket_username &&
serverSecrets.bitbucket_password
) {
args.options.auth = {
user: serverSecrets.bitbucket_username,
pass: serverSecrets.bitbucket_password,
}
}

return this._requestJson(args)
}

async fetchServer({ args, proto, hostAndPath, user, repo }) {
args.url = `${proto}://${hostAndPath}/rest/api/1.0/projects/${user}/repos/${repo}/pull-requests`
args.options = {
qs: {
state: 'OPEN',
limit: 100,
withProperties: false,
withAttributes: false,
},
}

if (
serverSecrets &&
serverSecrets.bitbucket_server_username &&
serverSecrets.bitbucket_server_password
) {
args.options.auth = {
user: serverSecrets.bitbucket_server_username,
pass: serverSecrets.bitbucket_server_password,
}
}

return this._requestJson(args)
}

async fetch({ proto, hostAndPath, user, repo }) {
const args = {
schema: bitbucketPullRequestsSchema,
options: { qs: { state: 'OPEN', limit: 0 } },
errorMessages: { 403: 'private repo' },
})
errorMessages: {
401: 'invalid credentials',
403: 'private repo',
404: 'not found',
},
}

if (hostAndPath !== undefined) {
return this.fetchServer({ args, proto, hostAndPath, user, repo })
} else {
return this.fetchCloud({ args, user, repo })
}
}

static render({ prs }) {
Expand All @@ -31,8 +82,8 @@ function pullRequestClassGenerator(raw) {
}
}

async handle({ user, repo }) {
const data = await this.fetch({ user, repo })
async handle({ proto, hostAndPath, user, repo }) {
const data = await this.fetch({ proto, hostAndPath, user, repo })
return this.constructor.render({ prs: data.size })
}

Expand All @@ -47,19 +98,33 @@ function pullRequestClassGenerator(raw) {
static get route() {
return {
base: `bitbucket/${routePrefix}`,
format: '([^/]+)/([^/]+)',
capture: ['user', 'repo'],
format: `(?:(http|https)/(.+)/)?([^/]+)/([^/]+)`,
capture: ['proto', 'hostAndPath', 'user', 'repo'],
}
}

static get examples() {
return [
{
title: 'Bitbucket open pull requests',
exampleUrl: 'atlassian/python-bitbucket',
namedParams: {
user: 'atlassian',
repo: 'python-bitbucket',
},
pattern: ':user/:repo',
staticExample: this.render({ prs: 22 }),
},
{
title: 'Bitbucket Server open pull requests',
namedParams: {
proto: 'https',
hostAndPath: 'bitbucket.mydomain.net',
user: 'foo',
repo: 'bar',
},
pattern: ':proto/:hostAndPath/:user/:repo',
staticExample: this.render({ prs: 42 }),
},
]
}
}
Expand Down
20 changes: 20 additions & 0 deletions services/bitbucket/bitbucket.tester.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,26 @@ t.create('pr (private repo)')
.get('/pr/chris48s/example-private-repo.json')
.expectJSON({ name: 'pull requests', value: 'private repo' })

t.create('pr (server)')
.get('/pr/https/bitbucket.mydomain.net/project/repo.json')
.intercept(nock =>
nock('https://bitbucket.mydomain.net/rest/api/1.0/projects')
.get('/project/repos/repo/pull-requests')
.query({
state: 'OPEN',
limit: 100,
withProperties: false,
withAttributes: false,
})
.reply(200, { size: 42 })
)
.expectJSONTypes(
Joi.object().keys({
name: 'pull requests',
value: isMetricOpenIssues,
})
)

// tests for Bitbucket Pipelines

function bitbucketApiResponse(status) {
Expand Down