Skip to content

Commit 3288596

Browse files
committed
Add commit formatting (optional oneline and gitio reduction)
Also add a few GitHub API wrappers, to mirror gh.branches. To distinguish between the API wrappers and the formatter, we use the presence of a callback in the initial call. So: gh.commits(repo, commit, cb) takes a repo name, commit hash, and callback; fetches a commit from GitHub; and calls the callback on the returned commit. On the other hand, gh.commits().format(commit, cb) takes a commit object (as returned from GitHub) and callback, and calls the callback on the formatted commit. The options formatting depends on two options, as discussed in the Readme: * gitio (set from HUBOT_GITIO) toggles git.io URL shortening * oneline (set from HUBOT_COMMIT_ONELINE) toggles message reduction to just the summary line. The bulk of the logic was ported from hubot-scripts [1,2], but I've adjusted the URL munging. When it's set [3], I leave commit.html_url alone. For the other endpoints [4,5], I try to parse the API URL and convert it in a single pass. I don't have access to an enterprise instance for testing [6], but I'm assuming the API URLs look like: :apiRoot/api/:apiVersion/repos/:owner/:repo/commits/:sha https://yourdomain.com/api/v3/repos/:owner/:repo/commits/:sha and the HTML URLs looks like: :apiRoot/repos/:owner/:repo/commit/:sha https://yourdomain.com/repos/:owner/:repo/commit/:sha [1]: https://github.com/github/hubot-scripts/blob/v2.5.14/src/scripts/github-commit-link.coffee [2]: https://github.com/github/hubot-scripts/blob/v2.5.14/src/scripts/github-commits.coffee [3]: https://developer.github.com/v3/repos/commits/#get-a-single-commit [4]: https://developer.github.com/v3/git/commits/#get-a-commit [5]: https://developer.github.com/v3/activity/events/types/#pushevent [6]: https://developer.github.com/v3/#schema
1 parent 63bf7f8 commit 3288596

File tree

6 files changed

+198
-1
lines changed

6 files changed

+198
-1
lines changed

Readme.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ in increasing order of precedence:
129129
* `concurrentRequests`/`process.env.HUBOT_CONCURRENT_REQUESTS`:
130130
Limits the allowed number of concurrent requests to the GitHub API. Defaults to 20.
131131

132+
* `gitio`/`process.env.HUBOT_GITIO`:
133+
If truthy, use [Git.io][] to shorten commit links when formatting.
134+
135+
* `oneline`/`process.env.HUBOT_COMMIT_ONELINE`:
136+
If truthy, truncate commit messages to the first line when
137+
formatting.
138+
132139
## Bespoke API access ##
133140

134141
Mostly a work in progress, but here's a taste of what I have in mind:
@@ -180,6 +187,66 @@ gh.branches( "foo/bar" ).delete "my_radical_feature", ->
180187
console.log "Deleted my branch!"
181188
```
182189

190+
### Commits ###
191+
192+
#### Get commit details ####
193+
194+
```coffeescript
195+
gh.commits "iangreenleaf/githubot", "63bf7f86c67066158a2ee24d0fcf41177e54a21d", (commit) ->
196+
console.log commit
197+
```
198+
199+
GitHub's commit objects vary depending on the endpoint. This one is
200+
just a wrapper around [GET
201+
/repos/:owner/:repo/commits/:sha][get-commit].
202+
203+
#### Format commit objects ####
204+
205+
Besides retrieving commit messages with `commits`, you can call
206+
`commits` without arguments to access the data-massaging `formatter`
207+
method. This is useful for pretty-printing commit messages, and you
208+
can use the default output:
209+
210+
```coffeescript
211+
gh.commits "iangreenleaf/githubot", "63bf7f86c67066158a2ee24d0fcf41177e54a21d", (commit) ->
212+
gh.commits().format commit, (commit) ->
213+
console.log "#{commit.message} (#{commit.html_url})"
214+
```
215+
216+
```
217+
Better paths to package in tests
218+
219+
Fixes test errors in 0.6.x (https://github.com/iangreenleaf/githubot/commit/63bf7f86c67066158a2ee24d0fcf41177e54a21d)
220+
```
221+
222+
Or You can also use the `gitio` and `oneline` [options](#options) to
223+
adjust the `message` and `html_url` attributes:
224+
225+
```coffeescript
226+
gh.commits "iangreenleaf/githubot", "63bf7f86c67066158a2ee24d0fcf41177e54a21d", (commit) ->
227+
gh.withOptions(
228+
gitio: true
229+
oneline: true
230+
)
231+
.commits().format commit, (commit) ->
232+
console.log "#{commit.message} (#{commit.html_url})"
233+
```
234+
235+
```
236+
Better paths to package in tests (http://git.io/l5mwmQ)
237+
```
238+
239+
The formatter can take input commit objects from the following
240+
endpoints:
241+
242+
* [GET /repos/:owner/:repo/commits/:sha][get-commit]
243+
* [GET /repos/:owner/:repo/git/commits/:sha][get-commit]
244+
* The [push event][push-event]
245+
246+
Which all store data in slightly different ways. In any case, the
247+
object passed to the `format` callback will have `commit.message` and
248+
`commit.html_url`.
249+
183250
### Deployments ###
184251

185252
*Note*: These methods are smart and automatically use the
@@ -231,3 +298,7 @@ ask and I can probably point you in the right direction.
231298

232299

233300
[Build Status]: https://travis-ci.org/iangreenleaf/githubot.png?branch=master
301+
[Git.io]: http://git.io/
302+
[get-commit]: https://developer.github.com/v3/repos/commits/#get-a-single-commit
303+
[get-git-commit]: https://developer.github.com/v3/git/commits/#get-a-commit
304+
[push-event]: https://developer.github.com/v3/activity/events/types/#pushevent

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
},
1919
"dependencies": {
2020
"scoped-http-client": ">= 0.9.8",
21-
"async": "0.2.x"
21+
"async": "0.2.x",
22+
"gitio2": ">= 2.0.0"
2223
},
2324
"devDependencies": {
2425
"mocha": "1.x",

src/commits.coffee

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
gitio = require "gitio2"
2+
3+
module.exports = (repo, commit, cb) ->
4+
if cb?
5+
if commit?
6+
@get "repos/#{@qualified_repo repo}/commits/#{commit}", cb
7+
else
8+
@get "repos/#{@qualified_repo repo}/commits", cb
9+
else
10+
format: (commit, cb) =>
11+
if @_opt "oneline"
12+
if commit.message?
13+
commit.message = commit.message.split("\n")[0]
14+
else if commit.commit? and commit.commit.message?
15+
commit.message = commit.commit.message.split("\n")[0]
16+
else if commit.commit? and commit.commit.message? and not commit.message?
17+
commit.message = commit.commit.message
18+
if not commit.html_url?
19+
regex = new RegExp "^#{@_opt "apiRoot"}/(api/#{@_opt "apiVersion"}/)?repos/([^/]+)/([^/]+)/(?:git/)?commits/([a-f0-9]+)$"
20+
match = commit.url.match regex
21+
if match?
22+
api = match[1]
23+
owner = match[2]
24+
repo = match[3]
25+
sha = match[4]
26+
if api?
27+
base_url = @_opt "apiRoot"
28+
else
29+
base_url = "https://github.com"
30+
commit.html_url = "#{base_url}/#{owner}/#{repo}/commit/#{sha}"
31+
else
32+
console.log "Unmatched commit URL: #{commit.url}"
33+
commit.html_url = commit.url
34+
if @_opt "gitio"
35+
gitio commit.html_url, (err, data) ->
36+
if not err
37+
commit.html_url = data
38+
cb commit
39+
else
40+
cb commit

src/githubot.coffee

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ class Github
101101

102102
branches: require './branches'
103103

104+
commits: require './commits'
105+
104106
deployments: require './deployments'
105107

106108
_opt: (optName) ->
@@ -120,6 +122,10 @@ class Github
120122
process.env.HUBOT_GITHUB_API ? "https://api.github.com"
121123
when "apiVersion"
122124
process.env.HUBOT_GITHUB_API_VERSION ? "v3"
125+
when "gitio"
126+
process.env.HUBOT_GITIO
127+
when "oneline"
128+
process.env.HUBOT_COMMIT_ONELINE
123129
else null
124130

125131
module.exports = github = (robot, options = {}) ->

test/commits.coffee

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
[ gh, assert, nock, mock_robot ] = require "./test_helper"
2+
3+
describe "commit utilities", ->
4+
describe "formatting", ->
5+
summary = "message summary"
6+
commit =
7+
sha: "abcdeg"
8+
url: "https://github.com/foo/bar/commit/abcdeg"
9+
message: summary + "\n\nmessage body"
10+
gitio_short = "yyy"
11+
gitio_url = "http://git.io/" + gitio_short
12+
network = null
13+
success = (done) ->
14+
network.done()
15+
done()
16+
it "formats commits with gitio", (done) ->
17+
network = nock("http://git.io")
18+
.post("/create")
19+
.reply(201, gitio_short)
20+
gh.withOptions(
21+
gitio: true
22+
)
23+
.commits().format commit, (commit) ->
24+
assert.deepEqual commit.html_url, gitio_url
25+
success done
26+
it "formats commits without gitio", (done) ->
27+
original_url = commit.html_url
28+
gh.commits().format commit, (commit) ->
29+
assert.deepEqual commit.html_url, original_url
30+
done()
31+
it "formats commits with oneline", (done) ->
32+
gh.withOptions(
33+
oneline: true
34+
)
35+
.commits().format commit, (commit) ->
36+
assert.deepEqual commit.message, summary
37+
done()
38+
it "formats commits without oneline", (done) ->
39+
original_message = commit.message
40+
gh.commits().format commit, (commit) ->
41+
assert.deepEqual commit.message, original_message
42+
done()

test/repo.coffee

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,40 @@ describe "repo api", ->
228228
gh.deployments("foo/bar").status @statusId, (status) ->
229229
network.done()
230230
done()
231+
232+
describe "commits", ->
233+
response = [ { sha: "abcdeg", url: "xxx" } ]
234+
network = null
235+
success = (done) ->
236+
(body) ->
237+
network.done()
238+
done()
239+
beforeEach ->
240+
network = nock("https://api.github.com")
241+
.get("/repos/foo/bar/commits")
242+
.reply(200, response)
243+
it "accepts a full repo with a commit hash", (done) ->
244+
network = nock("https://api.github.com")
245+
.get("/repos/foo/bar/commits/abcdeg")
246+
.reply(200, response)
247+
gh.commits "foo/bar", "abcdeg", success done
248+
it "accepts a full repo without a commit hash", (done) ->
249+
gh.commits "foo/bar", null, success done
250+
it "accepts an unqualified repo", (done) ->
251+
process.env.HUBOT_GITHUB_USER = "foo"
252+
gh.commits "bar", null, success done
253+
delete process.env.HUBOT_GITHUB_USER
254+
it "returns json", (done) ->
255+
gh.commits "foo/bar", null, (data) ->
256+
assert.deepEqual response, data
257+
done()
258+
it "allows per-request overrides", (done) ->
259+
network = nock("https://special.api.dev")
260+
.get("/repos/bar/baz/commits")
261+
.reply(200, response)
262+
gh.withOptions(
263+
apiRoot: "https://special.api.dev"
264+
defaultUser: "bar"
265+
defaultRepo: "baz"
266+
)
267+
.commits null, null, success done

0 commit comments

Comments
 (0)