gplan 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/gplan +89 -0
- data/lib/github.rb +69 -0
- data/lib/planbox.rb +75 -0
- metadata +48 -0
data/bin/gplan
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This script is used to find all of the planbox story numbers from the git log
|
4
|
+
# For lesson-player it is dependent on lesson-player being in the directory name for the repo
|
5
|
+
|
6
|
+
require 'pathname'
|
7
|
+
bin_path = Pathname.new(__FILE__).realpath
|
8
|
+
$:.unshift File.expand_path('../../lib', bin_path)
|
9
|
+
require 'planbox'
|
10
|
+
require 'github'
|
11
|
+
|
12
|
+
PB_STORY_REGEX=/\[(?:fixes)? *#*([0-9]*)\]/i
|
13
|
+
GH_PR_REGEX=/Merge pull request #(\d*)/i
|
14
|
+
|
15
|
+
@gh_release_array = []
|
16
|
+
@pb_release_array = []
|
17
|
+
@combined = []
|
18
|
+
|
19
|
+
def combine_results
|
20
|
+
@pb_release_array.each do |pb_story|
|
21
|
+
@gh_release_array.each do |gh_pr|
|
22
|
+
if gh_pr['pb_id'] and gh_pr['pb_id'].to_i == pb_story["id"]
|
23
|
+
gh_pr.delete('id') # doing this so we don't overide the pb id
|
24
|
+
pb_story = pb_story.merge gh_pr
|
25
|
+
@gh_release_array.delete gh_pr
|
26
|
+
break
|
27
|
+
end
|
28
|
+
end
|
29
|
+
@combined << pb_story
|
30
|
+
end
|
31
|
+
|
32
|
+
# add the remaining unmatched PRs
|
33
|
+
@gh_release_array.each do |gh_pr|
|
34
|
+
@combined << gh_pr
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# used to pull story numbers from pull request titles
|
39
|
+
def pull_pb_numbers_from_prs
|
40
|
+
@gh_release_array.each do |gh_pr|
|
41
|
+
pb_ids = gh_pr['title'].scan(PB_STORY_REGEX).flatten.uniq
|
42
|
+
if !pb_ids.empty?
|
43
|
+
gh_pr.merge!({"pb_id" => pb_ids.first.to_i}) # making an assumption that there is only 1 pb story number
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def print
|
49
|
+
end_of_pbs = false
|
50
|
+
release_notes = "ID:STATUS:TITLE:PROJECT_NAME:PROJECT_ALIAS:PR:TITLE\n"
|
51
|
+
@combined.each do |story|
|
52
|
+
if !end_of_pbs and story['name'].nil?
|
53
|
+
end_of_pbs = true
|
54
|
+
release_notes += "\n---- Unmatched PRs ----\n\n"
|
55
|
+
release_notes += "PR:TITLE\n"
|
56
|
+
end
|
57
|
+
line = ""
|
58
|
+
line += "#{story['id']}:#{story['status']}:#{story['name']}:#{story['project_name']}:#{story['project_alias']}" unless end_of_pbs
|
59
|
+
line += ":#{story['number']}:#{story['title']}" unless story['number'].nil?
|
60
|
+
release_notes += line + "\n"
|
61
|
+
end
|
62
|
+
puts release_notes
|
63
|
+
end
|
64
|
+
|
65
|
+
def setup_repository
|
66
|
+
conf_file =Dir.pwd+"/.gplan"
|
67
|
+
if File.exists?(conf_file)
|
68
|
+
File.open(conf_file, "r") do |f|
|
69
|
+
@prod_branch = f.each_line.first.chomp
|
70
|
+
end
|
71
|
+
end
|
72
|
+
# Set the default branch if one is not set
|
73
|
+
@prod_branch = "production/master" unless @prod_branch
|
74
|
+
@repo = @prod_branch.split("/").first
|
75
|
+
end
|
76
|
+
|
77
|
+
# MAIN
|
78
|
+
|
79
|
+
setup_repository
|
80
|
+
`git fetch #{@repo}`
|
81
|
+
list= `git log #{@prod_branch}..`
|
82
|
+
|
83
|
+
pb_story_ids = list.scan(PB_STORY_REGEX).flatten.uniq
|
84
|
+
gh_pr_ids = list.scan(GH_PR_REGEX).flatten.uniq
|
85
|
+
@gh_release_array = Github.get_release_notes_array gh_pr_ids
|
86
|
+
@pb_release_array = Planbox.get_release_notes_array pb_story_ids
|
87
|
+
pull_pb_numbers_from_prs
|
88
|
+
combine_results
|
89
|
+
print
|
data/lib/github.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
GITHUB_USERNAME=ENV['GITHUB_USERNAME']
|
4
|
+
GITHUB_TOKEN=ENV['GITHUB_TOKEN']
|
5
|
+
GITHUB_BASE_URL="https://api.github.com"
|
6
|
+
|
7
|
+
module Github
|
8
|
+
include HTTParty
|
9
|
+
|
10
|
+
@repo_name
|
11
|
+
@app_name
|
12
|
+
|
13
|
+
def self.check_environment
|
14
|
+
if GITHUB_USERNAME == nil || GITHUB_TOKEN == nil
|
15
|
+
raise "environment variables not set. Please check that you have the following set...\
|
16
|
+
\nGITHUB_USERNAME\nGITHUB_TOKEN"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.set_repo_info
|
21
|
+
cmd = "git remote -v |grep origin"
|
22
|
+
repo_info = `#{cmd}`
|
23
|
+
@repo_name = repo_info.scan(/\:(.*)\//).uniq.flatten.first
|
24
|
+
@app_name = repo_info.scan(/\/(.*)\.git/).uniq.flatten.first
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.get_release_notes gh_pr_ids
|
28
|
+
stories = get_release_notes_array gh_pr_ids
|
29
|
+
result_string = format stories
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.get_release_notes_array gh_pr_ids
|
33
|
+
check_environment
|
34
|
+
get_stories gh_pr_ids
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.get_story(pr_id)
|
38
|
+
set_repo_info
|
39
|
+
story_response = self.get("#{GITHUB_BASE_URL}/repos/#{@repo_name}/#{@app_name}/pulls/#{pr_id}?access_token=#{GITHUB_TOKEN}",
|
40
|
+
{
|
41
|
+
:headers => { 'User-Agent' => GITHUB_USERNAME, 'Content-Type' => 'application/json', 'Accept' => 'application/json'}
|
42
|
+
})
|
43
|
+
return story_response.parsed_response unless story_response.parsed_response.nil? || story_response.parsed_response["code"] == "error"
|
44
|
+
{"id" => story_id, "name" => "PR not found in github"}
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.get_stories(array_of_pr_ids)
|
48
|
+
stories = []
|
49
|
+
return [] unless array_of_pr_ids
|
50
|
+
array_of_pr_ids.each do |id|
|
51
|
+
stories<< get_story(id)
|
52
|
+
end
|
53
|
+
stories
|
54
|
+
end
|
55
|
+
|
56
|
+
# formats the output of stories
|
57
|
+
def self.format(stories)
|
58
|
+
result_string = ""
|
59
|
+
stories.each do |story|
|
60
|
+
result_string += "#{story['number']}:"
|
61
|
+
result_string += "#{story['title']}"
|
62
|
+
result_string += "\n"
|
63
|
+
end
|
64
|
+
|
65
|
+
# clean up any troublesome chars
|
66
|
+
result_string.gsub!('`', ' ') || result_string
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/lib/planbox.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
PLANBOX_EMAIL=ENV['PLANBOX_EMAIL']
|
4
|
+
PLANBOX_TOKEN=ENV['PLANBOX_TOKEN']
|
5
|
+
PLANBOX_BASE_URL="https://www.planbox.com/api"
|
6
|
+
|
7
|
+
module Planbox
|
8
|
+
include HTTParty
|
9
|
+
|
10
|
+
def self.check_environment
|
11
|
+
if PLANBOX_EMAIL == nil || PLANBOX_TOKEN == nil
|
12
|
+
raise "environment variables not set. Please check that you have the following set...\
|
13
|
+
\nPLANBOX_EMAIL\nPLANBOX_TOKEN"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.get_release_notes pb_story_ids
|
18
|
+
stories = get_release_notes_array pb_story_ids
|
19
|
+
result_string = format stories
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.get_release_notes_array pb_story_ids
|
23
|
+
check_environment
|
24
|
+
stories = get_stories pb_story_ids
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.login
|
28
|
+
response = self.post("#{PLANBOX_BASE_URL}/auth", { :body => {:email => PLANBOX_EMAIL, :password => PLANBOX_TOKEN}})
|
29
|
+
self.basic_auth response['content']['access_token'], ""
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.get_story(story_id)
|
33
|
+
story_response = self.post("#{PLANBOX_BASE_URL}/get_story", { :body => { :story_id => story_id}})
|
34
|
+
|
35
|
+
if story_response.parsed_response.nil? || story_response.parsed_response["code"] == "error"
|
36
|
+
return {"id" => story_id, "name" => "story not found in planbox"}
|
37
|
+
end
|
38
|
+
|
39
|
+
story = story_response.parsed_response["content"]
|
40
|
+
project_response = self.post("#{PLANBOX_BASE_URL}/get_project", { :body => { :project_id => story['project_id'], :product_id => story['product_id']}})
|
41
|
+
project = project_response.parsed_response["content"]
|
42
|
+
project_alias = project["alias"]
|
43
|
+
project_name = project["name"]
|
44
|
+
|
45
|
+
story = story.merge({"project_name" => project_name})
|
46
|
+
story = story.merge({"project_alias" => project_alias})
|
47
|
+
|
48
|
+
story
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.get_stories(array_of_pb_ids)
|
52
|
+
login
|
53
|
+
stories = []
|
54
|
+
return [] unless array_of_pb_ids
|
55
|
+
array_of_pb_ids.each do |id|
|
56
|
+
stories<< get_story(id)
|
57
|
+
end
|
58
|
+
stories
|
59
|
+
end
|
60
|
+
|
61
|
+
# formats the output of stories
|
62
|
+
def self.format(stories)
|
63
|
+
result_string = ""
|
64
|
+
stories.each do |story|
|
65
|
+
result_string += "#{story['id']}:"
|
66
|
+
result_string += "#{story['status']}: "
|
67
|
+
result_string += "#{story['name']}"
|
68
|
+
result_string += "\n"
|
69
|
+
end
|
70
|
+
|
71
|
+
# clean up any troublesome chars
|
72
|
+
result_string.gsub!('`', ' ') || result_string
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
metadata
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gplan
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jeff Koenig
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-04-14 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Creates release notes from the git log and planbox
|
15
|
+
email: jkoenig311@gmail.com
|
16
|
+
executables:
|
17
|
+
- gplan
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- bin/gplan
|
22
|
+
- lib/github.rb
|
23
|
+
- lib/planbox.rb
|
24
|
+
homepage: https://github.com/jkoenig311/gplan
|
25
|
+
licenses: []
|
26
|
+
post_install_message:
|
27
|
+
rdoc_options: []
|
28
|
+
require_paths:
|
29
|
+
- lib
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - '>='
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
requirements: []
|
43
|
+
rubyforge_project:
|
44
|
+
rubygems_version: 1.8.28
|
45
|
+
signing_key:
|
46
|
+
specification_version: 3
|
47
|
+
summary: Creates release notes from the git log and planbox
|
48
|
+
test_files: []
|