yaml config
This commit is contained in:
parent
23d0cb4001
commit
afec4bd24f
|
@ -0,0 +1,33 @@
|
|||
Server for connect to GitHub Issues API and displaying a burndown chart for a current milestone.
|
||||
|
||||
## Requirements:
|
||||
|
||||
You can install all the following dependencies by running:
|
||||
|
||||
```bash
|
||||
npm install -d
|
||||
```
|
||||
|
||||
- [CoffeeScript](http://coffeescript.org/)
|
||||
- [express](http://expressjs.com/)
|
||||
- [eco](https://github.com/sstephenson/eco)
|
||||
- [js-yaml](https://github.com/visionmedia/js-yaml)
|
||||
|
||||
## Configure:
|
||||
|
||||
The app is configured by pointing to a public GitHub user/project. Do so in `config.yml`:
|
||||
|
||||
```yaml
|
||||
github_user: ̈́'intermine'
|
||||
github_project: 'InterMine'
|
||||
project_name: 'Core InterMine Project'
|
||||
```
|
||||
|
||||
## Use:
|
||||
|
||||
1. Start a node server using `.webserver.sh`.
|
||||
2. Visit [http://0.0.0.0:3000/](http://0.0.0.0:3000/)
|
||||
|
||||
## Example:
|
||||
|
||||
![image](https://raw.github.com/radekstepan/github-burndown-chart/master/example.png)
|
84
app.coffee
84
app.coffee
|
@ -2,21 +2,41 @@ express = require 'express'
|
|||
eco = require 'eco'
|
||||
https = require 'https'
|
||||
fs = require "fs"
|
||||
yaml = require "js-yaml"
|
||||
|
||||
# Make HTTPS GET to GitHub API v3.
|
||||
apiGet = (path, type, callback) ->
|
||||
options =
|
||||
host: "api.github.com"
|
||||
method: "GET"
|
||||
path: path
|
||||
# Helper object for GitHub Issues.
|
||||
Issues =
|
||||
|
||||
https.request(options, (response) ->
|
||||
if response.statusCode is 200
|
||||
json = ""
|
||||
response.on "data", (chunk) -> json += chunk
|
||||
|
||||
response.on "end", -> callback JSON.parse(json), type
|
||||
).end()
|
||||
# Make HTTPS GET to GitHub API v3.
|
||||
get: (path, type, callback) ->
|
||||
options =
|
||||
host: "api.github.com"
|
||||
method: "GET"
|
||||
path: path
|
||||
|
||||
https.request(options, (response) ->
|
||||
if response.statusCode is 200
|
||||
json = ""
|
||||
response.on "data", (chunk) -> json += chunk
|
||||
|
||||
response.on "end", -> callback JSON.parse(json), type
|
||||
).end()
|
||||
|
||||
# URLs to API.
|
||||
getOpenIssues: (callback) -> Issues.get "/repos/#{Issues.config.github_user}/#{Issues.config.github_project}/issues?state=open", 'issues', callback
|
||||
getClosedIssues: (callback) -> Issues.get "/repos/#{Issues.config.github_user}/#{Issues.config.github_project}/issues?state=closed", 'issues', callback
|
||||
getMilestones: (callback) -> Issues.get "/repos/#{Issues.config.github_user}/#{Issues.config.github_project}/milestones", 'milestones', callback
|
||||
|
||||
# Convert GitHub ISO to JS ISO date and then time
|
||||
dateToTime: (date) -> new Date(date[0...date.length - 1] + '.000' + date.charAt date.length-1).getTime()
|
||||
|
||||
# Format issues for display in a listing.
|
||||
format: (issue) ->
|
||||
# Format the timestamps.
|
||||
if issue.created_at? then issue.created_at = new Date(Issues.dateToTime(issue.created_at)).toUTCString()
|
||||
if issue.updated_at? then issue.updated_at = new Date(Issues.dateToTime(issue.updated_at)).toUTCString()
|
||||
|
||||
issue
|
||||
|
||||
# Express.
|
||||
app = express.createServer()
|
||||
|
@ -55,10 +75,7 @@ app.get '/burndown', (req, res) ->
|
|||
when 'milestones' then store.milestones = store.milestones.concat data
|
||||
|
||||
# Are we done?
|
||||
if resources is 0
|
||||
# Convert GitHub ISO to JS ISO date and then time
|
||||
dateToTime = (date) -> new Date(date[0...date.length - 1] + '.000' + date.charAt date.length-1).getTime()
|
||||
|
||||
if resources is 0
|
||||
# Store the current milestone and its size.
|
||||
current = { 'milestone': {}, 'diff': +Infinity, 'size': 0 }
|
||||
|
||||
|
@ -67,7 +84,7 @@ app.get '/burndown', (req, res) ->
|
|||
for milestone in store.milestones
|
||||
due = milestone['due_on']
|
||||
# JS expects more accuracy.
|
||||
due = dateToTime due
|
||||
due = Issues.dateToTime due
|
||||
# Is this the 'current' one?
|
||||
diff = due - now
|
||||
if diff > 0 and diff < current.diff
|
||||
|
@ -75,7 +92,7 @@ app.get '/burndown', (req, res) ->
|
|||
|
||||
# Create n dict with all dates in the milestone span.
|
||||
days = {} ; totalDays = 0
|
||||
day = dateToTime current.milestone.created_at # TODO: shift this to the start of the day and deal with time shifts.
|
||||
day = Issues.dateToTime current.milestone.created_at # TODO: shift this to the start of the day and deal with time shifts.
|
||||
while day < current.due
|
||||
# Save the day.
|
||||
days[day] = { 'issue': {}, 'actual': 0, 'ideal': 0 }
|
||||
|
@ -100,7 +117,7 @@ app.get '/burndown', (req, res) ->
|
|||
current.size += issue.size
|
||||
# Is it closed?
|
||||
if issue.closed_at?
|
||||
closed = dateToTime issue.closed_at
|
||||
closed = Issues.dateToTime issue.closed_at
|
||||
# Find when was it closed (will be made faster)
|
||||
day = do () ->
|
||||
for day, x of days
|
||||
|
@ -124,22 +141,31 @@ app.get '/burndown', (req, res) ->
|
|||
|
||||
# Finally send to client.
|
||||
res.render 'burndown',
|
||||
'days': days
|
||||
'days': days
|
||||
'project': Issues.config.project_name
|
||||
, (html) -> res.send html, 'Content-Type': 'text/html', 200
|
||||
|
||||
|
||||
# Get Milestones, Opened and Closed Tickets.
|
||||
apiGet "/repos/intermine/InterMine/milestones", 'milestones', done
|
||||
apiGet "/repos/intermine/InterMine/issues?state=open", 'issues', done
|
||||
apiGet "/repos/intermine/InterMine/issues?state=closed", 'issues', done
|
||||
Issues.getMilestones done
|
||||
Issues.getOpenIssues done
|
||||
Issues.getClosedIssues done
|
||||
|
||||
# Show open issues.
|
||||
app.get '/issues', (req, res) ->
|
||||
apiGet "/repos/intermine/InterMine/issues?state=open", 'issues', (issues) ->
|
||||
# Vanilla render.
|
||||
Issues.getOpenIssues (issues) ->
|
||||
|
||||
# Replace the dates in issues with nice dates.
|
||||
issues = ( Issues.format(issue) for issue in issues )
|
||||
|
||||
res.render 'issues',
|
||||
'issues': issues
|
||||
'issues': issues
|
||||
'project': Issues.config.project_name
|
||||
, (html) -> res.send html, 'Content-Type': 'text/html', 200
|
||||
|
||||
app.listen 3000
|
||||
console.log "Express server listening to port 3000"
|
||||
# Fetch config and start server.
|
||||
fs.readFile "config.yml", "utf8", (err, data) ->
|
||||
Issues.config = yaml.load data
|
||||
|
||||
app.listen 3000
|
||||
console.log "Express server listening to port 3000"
|
|
@ -0,0 +1,3 @@
|
|||
github_user: 'intermine'
|
||||
github_project: 'InterMine'
|
||||
project_name: 'Core InterMine Project'
|
Binary file not shown.
After Width: | Height: | Size: 131 KiB |
|
@ -3,7 +3,8 @@
|
|||
, "version": "0.0.0"
|
||||
, "private": true
|
||||
, "dependencies": {
|
||||
"express": ">= 3.0",
|
||||
"eco": "latest"
|
||||
"express": ">= 3.0",
|
||||
"eco": "latest",
|
||||
"js-yaml": "latest"
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
<li><a><i class="icon-white icon-fire"></i> Burndown App</a></li>
|
||||
</ul>
|
||||
<ul class="nav pull-right">
|
||||
<li><a><i class="icon-white icon-book"></i> Core InterMine Project</a></li>
|
||||
<li><a><i class="icon-white icon-book"></i> <%= @project %></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<li><a><i class="icon-white icon-fire"></i> Burndown App</a></li>
|
||||
</ul>
|
||||
<ul class="nav pull-right">
|
||||
<li><a><i class="icon-white icon-book"></i> Core InterMine Project</a></li>
|
||||
<li><a><i class="icon-white icon-book"></i> <%= @project %></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue