Skip to content

Commit af94d50

Browse files
committed
feat: initial commit
0 parents  commit af94d50

File tree

13 files changed

+6741
-0
lines changed

13 files changed

+6741
-0
lines changed

.editorconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[*]
2+
insert_final_newline = true
3+
end_of_line = lf
4+
charset = utf-8
5+
trim_trailing_whitespace = true
6+
indent_style = space
7+
indent_size = 4
8+
9+
[*.{json,js,yml}]
10+
indent_size = 2
11+
12+
[*.md]
13+
trim_trailing_whitespace = false

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
dist/
2+
node_modules/
3+
coverage/
4+
.cache/

.prettierignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package.json
2+
package-lock.json
3+
dist/
4+
.cache/

.travis.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
language: node_js
2+
node_js: '10'
3+
cache:
4+
directories:
5+
- ~/.npm
6+
env:
7+
global:
8+
- FORCE_COLOR=1
9+
jobs:
10+
include:
11+
- stage: test
12+
script:
13+
- npm run prettier
14+
- npm run tslint
15+
- npm run build
16+
- npm test
17+
- npm run cover
18+
- nyc report --reporter json
19+
- 'bash <(curl -s https://codecov.io/bash)'
20+
stages:
21+
- test
22+
branches:
23+
only:
24+
- master

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Sourcegraph
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# sourcegraph-github-extras
2+
3+
[![build](https://travis-ci.org/sourcegraph/sourcegraph-github-extras.svg?branch=master)](https://travis-ci.org/sourcegraph/sourcegraph-github-extras)
4+
[![codecov](https://codecov.io/gh/sourcegraph/sourcegraph-github-extras/branch/master/graph/badge.svg?token=c3KpMf1MaY)](https://codecov.io/gh/sourcegraph/sourcegraph-github-extras)
5+
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
6+
7+
A [Sourcegraph extension](https://github.com/sourcegraph/sourcegraph-extension-api) that adds more GitHub integration features to [Sourcegraph](https://sourcegraph.com).
8+
9+
- **GitHub: Pull requests**: see a table of GitHub pull requests for the current repository
10+
11+
[**🗃️ Source code**](https://github.com/sourcegraph/sourcegraph-github-extras)
12+
13+
[**➕ Add to Sourcegraph**](https://sourcegraph.com/extensions/sourcegraph/github-extras)
14+
15+
## Known issues
16+
17+
This extension is experimental.
18+
19+
- The GitHub API request is sent each time the page loads. This is likely to cause you to hit the GitHub API rate limit (for unauthenticated users, it's 60 requests per minute).
20+
- When you navigate to a different repository, the pull requests panel still shows the list from the first repository you viewed. Reload your browser to refresh the list.

mocha.opts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
--recursive
2+
--watch-extensions ts
3+
--timeout 200
4+
src/**/*.test.ts

package.json

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
{
2+
"name": "github-extras",
3+
"publisher": "sourcegraph",
4+
"title": "GitHub extras",
5+
"description": "WIP: Adds more GitHub integration features to Sourcegraph.",
6+
"activationEvents": [
7+
"*"
8+
],
9+
"contributes": {
10+
"actions": [
11+
{
12+
"id": "github.openPanel",
13+
"command": "openPanel",
14+
"commandArguments": [
15+
"github.pullRequests"
16+
],
17+
"category": "GitHub",
18+
"title": "Pull requests",
19+
"actionItem": {
20+
"label": "Pull requests",
21+
"description": "Show GitHub pull requests"
22+
}
23+
}
24+
],
25+
"menus": {
26+
"directory/page": [
27+
{
28+
"action": "github.openPanel",
29+
"when": "resource"
30+
}
31+
],
32+
"commandPalette": [
33+
{
34+
"action": "github.openPanel",
35+
"when": "resource"
36+
}
37+
]
38+
},
39+
"configuration": {
40+
"title": "GitHub extras",
41+
"properties": {
42+
"github.explore.repositories": {
43+
"description": "A list of repositories (in `owner/name` format) to display in the Explore area.",
44+
"type": "array",
45+
"items": {
46+
"type": "string",
47+
"pattern": "^[^/]+/[^/]+$"
48+
},
49+
"default":["sourcegraph/sourcegraph"],
50+
"examples": [
51+
[
52+
"facebook/react",
53+
"twbs/bootstrap",
54+
"sourcegraph/sourcegraph"
55+
]
56+
]
57+
}
58+
}
59+
}
60+
},
61+
"version": "0.0.0-DEVELOPMENT",
62+
"license": "MIT",
63+
"repository": {
64+
"type": "git",
65+
"url": "https://github.com/sourcegraph/sourcegraph-github-extras.git"
66+
},
67+
"files": [
68+
"dist"
69+
],
70+
"main": "dist/sourcegraph-github-extras.js",
71+
"scripts": {
72+
"prettier": "prettier '**/{*.{js?(on),ts?(x),scss},.*.js?(on)}' --write --list-different",
73+
"tslint": "tslint -c tslint.json -p tsconfig.json './src/*.ts?(x)' './*.ts?(x)'",
74+
"test": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' mocha --require ts-node/register --require source-map-support/register --opts mocha.opts",
75+
"cover": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --require ts-node/register --require source-map-support/register --all mocha --opts mocha.opts --timeout 10000",
76+
"build": "parcel build --no-minify --out-file sourcegraph-github-extras.js src/extension.ts",
77+
"serve": "parcel serve --no-hmr --out-file sourcegraph-github-extras.js src/extension.ts",
78+
"sourcegraph:prepublish": "yarn run build"
79+
},
80+
"commitlint": {
81+
"extends": [
82+
"@commitlint/config-conventional"
83+
]
84+
},
85+
"nyc": {
86+
"include": [
87+
"src/**/*.ts?(x)"
88+
],
89+
"exclude": [
90+
"**/*.test.ts?(x)"
91+
],
92+
"extension": [
93+
".tsx",
94+
".ts"
95+
]
96+
},
97+
"browserslist": [
98+
"last 1 Chrome versions",
99+
"last 1 Firefox versions",
100+
"last 1 Edge versions",
101+
"last 1 Safari versions"
102+
],
103+
"devDependencies": {
104+
"@commitlint/cli": "^7.0.0",
105+
"@commitlint/config-conventional": "^7.0.1",
106+
"@sourcegraph/prettierrc": "^2.2.0",
107+
"@sourcegraph/tsconfig": "^3.0.0",
108+
"@sourcegraph/tslint-config": "^12.0.0",
109+
"@types/mocha": "^5.2.5",
110+
"@types/node": "^10.7.1",
111+
"husky": "^1.1.2",
112+
"mocha": "^5.2.0",
113+
"nyc": "^13.1.0",
114+
"parcel-bundler": "^1.9.7",
115+
"prettier": "^1.14.2",
116+
"source-map-support": "^0.5.9",
117+
"sourcegraph": "^18.4.0",
118+
"ts-node": "^7.0.1",
119+
"tslint": "^5.11.0",
120+
"typescript": "^3.0.1"
121+
},
122+
"dependencies": {
123+
"date-fns": "^2.0.0-alpha.25",
124+
"rxjs": "^6.3.2"
125+
},
126+
"husky": {
127+
"hooks": {
128+
"commit-msg": "commitlint -e $HUSKY_GIT_PARAMS"
129+
}
130+
}
131+
}

prettier.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('@sourcegraph/prettierrc')

src/extension.ts

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import formatDistanceStrict from 'date-fns/formatDistanceStrict'
2+
import * as sourcegraph from 'sourcegraph'
3+
4+
interface Settings {
5+
['github.explore.repositories']: string[]
6+
}
7+
8+
interface PullRequest {
9+
number: number
10+
title: string
11+
html_url: string
12+
updated_at: string
13+
base: {
14+
ref: string
15+
repo: {
16+
id: string
17+
full_name: string
18+
html_url: string
19+
default_branch: string
20+
}
21+
}
22+
head: {
23+
ref: string
24+
repo: { id: string }
25+
}
26+
user: {
27+
login: string
28+
}
29+
}
30+
31+
export async function activate(): Promise<void> {
32+
// HACK: work around bug where configuration is not synchronously available
33+
await new Promise(resolve => setTimeout(resolve, 0))
34+
35+
// TODO(sqs): does not refresh as you switch repos
36+
37+
let repos: string[]
38+
let inFile = false
39+
if (
40+
sourcegraph.workspace.textDocuments.length > 0 &&
41+
sourcegraph.workspace.textDocuments[0].uri.startsWith('git://github.com/')
42+
) {
43+
// Use currently open repository.
44+
//
45+
// pathname is not actually the URI path because non-https?: URIs are treated specially.
46+
const { pathname } = new URL(sourcegraph.workspace.textDocuments[0].uri)
47+
repos = [pathname.replace('//github.com/', '')] // TODO(sqs): assumes host == 'github.com'
48+
inFile = true
49+
} else {
50+
// Otherwise, assume we are on the Explore page because there is no repository shown.
51+
repos = sourcegraph.configuration.get<Settings>().get('github.explore.repositories') || [
52+
'sourcegraph/sourcegraph',
53+
]
54+
}
55+
56+
const data = await Promise.all(
57+
repos.map(async repo => {
58+
const resp = await fetch(`https://api.github.com/repos/${repo}/pulls?status=open`, {
59+
headers: {
60+
Accept: 'application/json',
61+
'Content-Type': 'application/json',
62+
},
63+
})
64+
if (resp.status !== 200) {
65+
throw new Error(await resp.text())
66+
}
67+
return { repo, pullRequests: (await resp.json()) as PullRequest[] }
68+
})
69+
)
70+
71+
const view = sourcegraph.app.createPanelView('github.pullRequests')
72+
view.title = 'GitHub'
73+
view.content = data.map(({ repo, pullRequests }) => renderRepository(repo, pullRequests, inFile)).join('\n\n')
74+
}
75+
76+
function renderRepository(repo: string, pulls: PullRequest[], inFile: boolean): string {
77+
if (pulls.length === 0) {
78+
return ''
79+
}
80+
// TODO(sqs): un-hardcode github.com
81+
return (
82+
(inFile
83+
? `[Pull requests in ${repo}](${pulls[0].base.repo.html_url}/pulls):`
84+
: `### [${repo}](${pulls[0].base.repo.html_url}/pulls)` +
85+
'\n\n' +
86+
`[View repository](/github.com/${repo}) — [Search in this repository](/search?q=repo:${repo})`) +
87+
'\n\n' +
88+
'| Pull request | Author | Updated | Compare |\n' +
89+
'| --- | --- | --- | --- |\n' +
90+
pulls.map(renderPullRequest).join('\n') +
91+
'\n\n'
92+
)
93+
}
94+
95+
function renderPullRequest(pull: PullRequest): string {
96+
// TODO(sqs): un-hardcode github.com
97+
return `| [#${pull.number} ${truncate(pull.title, 64)}](${pull.html_url}) | @${
98+
pull.user.login
99+
} | ${formatDistanceStrict(pull.updated_at, Date.now(), { addSuffix: true })} | [${backtick(
100+
truncate(
101+
pull.base.ref === pull.base.repo.default_branch ? pull.head.ref : `${pull.base.ref}...${pull.head.ref}`,
102+
32
103+
)
104+
)}](/github.com/${pull.base.repo.full_name}/-/compare/${pull.base.ref}...${
105+
pull.head.repo.id === pull.base.repo.id ? pull.head.ref : `refs/pull/${pull.number}/head`
106+
}) |`
107+
}
108+
109+
function backtick(s: string): string {
110+
return '`' + s + '`'
111+
}
112+
113+
function truncate(s: string, max: number, omission = '…'): string {
114+
if (s.length <= max) {
115+
return s
116+
}
117+
return `${s.slice(0, max)}${omission}`
118+
}

0 commit comments

Comments
 (0)