mr_bump 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZjQ1NzQ4YzlkMWI2MDJkZmYwYTY0MWRjNGFlOTY3NjUyMTgwZTc0YQ==
5
+ data.tar.gz: !binary |-
6
+ YWMwNTc5MjFlODY3ZDhjY2QwMmRjNTQyZDg1OGU0YjY5NGU3YTA4MQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NzI5ZGJmNmY4NDhmZmYxNTgxZWMxODU5ZmVkMTM5NDYzYjNmYTc1ZmM0ZmU2
10
+ OGMwNjhhOWY4YTU3MWNjY2ZkNGI3NjUxMmI0ODg0NDg2ZmFkNGY0YjcxZmY1
11
+ NWVhZTQ1YmZmNWQwMTFiZGQyZjBlYzljNzhmMzIxYjVhNTdkMmE=
12
+ data.tar.gz: !binary |-
13
+ YjM0OGVmOWJkNDViNzdlZDFjZjAwNjYzMzg5ZjExMDM3Yzc3ZmQ2MjFhNmU2
14
+ NmFmNjRjOWU2Mjg1ZmI2YzBkOTRkNTgxYzQ5MGU4MTZiYTYzZjU2YzI1YTNh
15
+ MWM4YTQ3M2FmZjAyMGI1ZWE5NDZmNjIwODk4YzBhZTQyYWQ2NDM=
data/bin/mr_bump ADDED
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env ruby
2
+ # Small script to tag releases and update changelogs
3
+ require 'mr_bump'
4
+
5
+ release = !MrBump.current_branch[/^release/].nil?
6
+ master = !MrBump.current_branch[/^master$/].nil?
7
+
8
+ unless release || master
9
+ puts 'Need to be on either release or master branch'
10
+ exit 1
11
+ end
12
+
13
+ unless system('git remote update > /dev/null 2>&1')
14
+ puts 'Failed to update remotes. (Connectivity problems?)'
15
+ exit 1
16
+ end
17
+
18
+ unless `git rev-parse @` == `git rev-parse @{u}`
19
+ puts 'Not up to date with origin! Please run git pull'
20
+ exit 1
21
+ end
22
+
23
+ unless File.file?('CHANGELOG.md')
24
+ puts "Couldn't find CHANGELOG.md. ensure you are in the root of the git checkout"
25
+ exit 1
26
+ end
27
+
28
+ if release
29
+ last_release = MrBump.current_uat
30
+ current_uat_major = MrBump.current_uat_major
31
+ changes = MrBump.change_log_items_for_range(last_release, "release/#{current_uat_major}")
32
+ else
33
+ last_release = MrBump.current_master
34
+ changes = MrBump.change_log_items_for_range(last_release, 'master')
35
+ end
36
+
37
+ new_release = last_release.bump_patch
38
+ changes = changes.join('')
39
+ md_changes = "# #{new_release}#{changes}\n\n"
40
+
41
+ puts 'Changelog additions'
42
+ puts '----------'
43
+ puts md_changes
44
+ puts '----------'
45
+
46
+ loop do
47
+ print '[A]ccept these changes / Manually [E]dit / [C]ancel Release : '
48
+ choice = gets.chomp.upcase
49
+
50
+ case choice
51
+ when 'A'
52
+ MrBump.file_prepend('CHANGELOG.md', md_changes)
53
+ break
54
+ when 'E'
55
+ MrBump.file_prepend('CHANGELOG.md', md_changes)
56
+ system 'nano CHANGELOG.md'
57
+ loop do
58
+ log = File.open('CHANGELOG.md', 'r').read
59
+ md_changes = log.split("\n\n").first.split("\n").drop(1)
60
+ puts 'Modified Changelog additions'
61
+ puts '----------'
62
+ puts md_changes
63
+ puts '----------'
64
+ print '[A]ccept modified changes / [C]ancel Release : '
65
+ choice2 = gets.chomp.upcase
66
+ if choice2 == 'C'
67
+ exit 1
68
+ elsif choice2 == 'A'
69
+ break
70
+ else
71
+ puts "I'm sorry Dave; I'm afraid I can't do that."
72
+ end
73
+ end
74
+ break
75
+ when 'C'
76
+ exit 1
77
+ else
78
+ puts "I'm sorry Dave; I'm afraid I can't do that."
79
+ end
80
+ end
81
+
82
+ `git commit -m 'Bump version to #{new_release}' CHANGELOG.md`
83
+ `git tag #{new_release}`
84
+ `git push && git push --tags`
85
+
86
+ MrBump.slack_notifier(new_release, md_changes.join("\n"))
87
+
88
+ config_file = MrBump.config_file()
89
+ branch_type = release ? "release" : 'master'
90
+ bump_cmd_exists = config_file.key?('post_bump') &&
91
+ config_file['post_bump'].key?(branch_type)
92
+ if bump_cmd_exists
93
+ loop do
94
+ puts 'Would you like to execute post bump commands? '
95
+ print '[Y]es execute / [N]o Im done : '
96
+ choice = gets.chomp.upcase
97
+
98
+ case choice
99
+ when 'Y'
100
+ post_command = config_file['post_bump'][branch_type]
101
+ system post_command
102
+ break
103
+ when 'N'
104
+ break
105
+ else
106
+ puts "I'm sorry Dave; I'm afraid I can't do that."
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,25 @@
1
+ require 'yaml'
2
+
3
+ module MrBump
4
+ # This class sets up access to the config file
5
+ class Config
6
+ attr_reader :config_file
7
+
8
+ def initialize(config_file = nil)
9
+ @config_file = config_file || default_file
10
+ end
11
+
12
+ def config
13
+ @config ||= if File.exist?(@config_file)
14
+ YAML.load_file(@config_file) || {}
15
+ else
16
+ {}
17
+ end
18
+ end
19
+
20
+ def default_file
21
+ File.join(".mr_bump")
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,110 @@
1
+ require 'slack-notifier'
2
+ module MrBump
3
+ # This class uses a slack webhook to push notifications to slack
4
+ class Slack
5
+
6
+ def initialize(opts)
7
+ raise ArgumentError, 'No Slack webhook found.' unless opts["webhook_url"]
8
+ @webhook = opts["webhook_url"]
9
+ @username = opts["username"] || 'Mr Bump'
10
+ if opts['jira_url']
11
+ @jira_url = opts['jira_url']
12
+ else
13
+ @jira_url = nil
14
+ end
15
+ if opts['icon']
16
+ @icon = (opts['icon'].is_a? Array) ? opts['icon'].sample : opts['icon']
17
+ end
18
+ end
19
+
20
+ def bump(version, changes)
21
+ options = {}
22
+ options[:icon_url] = @icon if @icon
23
+ options[:attachments] = [attatchment(version, changes)]
24
+ notifier.ping 'There is a new version bump!', options
25
+ end
26
+
27
+ def notifier
28
+ @notifier ||= ::Slack::Notifier.new(@webhook, username: @username)
29
+ end
30
+
31
+ def user
32
+ `git config user.name`.gsub(/\n/, '')
33
+ end
34
+
35
+ def git_url
36
+ @git_url ||= `git remote get-url origin`
37
+ end
38
+
39
+ def git_user
40
+ git_url[/[^@]+/].partition('//').last
41
+ end
42
+
43
+ def git_icon
44
+ 'https://avatars.githubusercontent.com/' + git_user
45
+ end
46
+
47
+ def git_link
48
+ 'https://github.com/' + git_user
49
+ end
50
+
51
+ def repo_name
52
+ `git config --get remote.origin.url`[/[\w\.]+(?=\.git$)/]
53
+ end
54
+
55
+ def jira_ids(changes)
56
+ changes.split('* ').map { |i| i.split(' - ',3)[1]}.compact
57
+ end
58
+
59
+ def jira_urls(changes)
60
+ jira_ids(changes).map do |ticket|
61
+ if ticket!= 'UNKNOWN'
62
+ '<' + @jira_url + '/browse/' + ticket + '|Jira link - ' + ticket + ">\n"
63
+ end
64
+ end.join
65
+ end
66
+
67
+ def jira_field(changes)
68
+ if @jira_url && !@jira_url.empty?
69
+ {value: jira_urls(changes), short: true, unfurl_links: false}
70
+ end
71
+ end
72
+
73
+ def get_sha(id)
74
+ `git log --grep=#{id} --merges --format=format:%H`.split("\n").first
75
+ end
76
+
77
+ def git_repo_url
78
+ 'https://' + git_url.partition('@').last.gsub(".git\n", '')
79
+ end
80
+
81
+ def git_shas(changes)
82
+ jira_ids(changes).map do |ticket|
83
+ if ticket!= 'UNKNOWN' && !get_sha(ticket).nil?
84
+ '<' + git_repo_url + '/commit/' + get_sha(ticket) + '|Git merge link - ' + ticket + ">\n"
85
+ end
86
+ end.join
87
+ end
88
+
89
+
90
+ def attatchment(version, changes)
91
+ {
92
+ fallback: changes,
93
+ color: "#009de4",
94
+ author_name: user,
95
+ author_icon: git_icon,
96
+ author_link: git_link,
97
+ fields: [
98
+ {title: 'Version', value: version, short: true},
99
+ {title: 'Repository', value: repo_name, short: true},
100
+ {title: 'Change Log', value: changes, short: false},
101
+ jira_field(changes),
102
+ {value: git_shas(changes), short: true}
103
+ ],
104
+ mrkdwn_in: ["text", "title", "fallback", "fields"]
105
+ }
106
+ end
107
+
108
+
109
+ end
110
+ end
@@ -0,0 +1,55 @@
1
+ module MrBump
2
+ # This class enables comparison and bumping of sementic versions and
3
+ # conversion to and from strings
4
+ class Version
5
+ include Comparable
6
+ attr_reader :major, :minor, :patch
7
+ def initialize(version_str)
8
+ regex = Regexp.new('^([0-9]+)(\.([0-9]+)(\.([0-9]*))?)?')
9
+ numbers = version_str.match(regex).captures
10
+ @major = numbers[0].to_i
11
+ @minor = (numbers.size > 2) ? numbers[2].to_i : 0
12
+ @patch = (numbers.size > 4) ? numbers[4].to_i : 0
13
+ end
14
+
15
+ def <=>(other)
16
+ major_com = major <=> other.major
17
+ minor_com = (major_com == 0) ? minor <=> other.minor : major_com
18
+ (minor_com == 0) ? patch <=> other.patch : minor_com
19
+ end
20
+
21
+ def to_s
22
+ "#{major}.#{minor}.#{patch}"
23
+ end
24
+
25
+ def bump_major
26
+ dup.bump_major!
27
+ end
28
+
29
+ def bump_major!
30
+ @major += 1
31
+ @minor = 0
32
+ @patch = 0
33
+ self
34
+ end
35
+
36
+ def bump_minor
37
+ dup.bump_minor!
38
+ end
39
+
40
+ def bump_minor!
41
+ @minor += 1
42
+ @patch = 0
43
+ self
44
+ end
45
+
46
+ def bump_patch
47
+ dup.bump_patch!
48
+ end
49
+
50
+ def bump_patch!
51
+ @patch += 1
52
+ self
53
+ end
54
+ end
55
+ end
data/lib/mr_bump.rb ADDED
@@ -0,0 +1,98 @@
1
+ require 'mr_bump/version'
2
+ require 'mr_bump/slack'
3
+ require 'mr_bump/config'
4
+
5
+ module MrBump
6
+ def self.current_branch
7
+ @current_branch ||= `git rev-parse --abbrev-ref HEAD`
8
+ @current_branch.strip
9
+ end
10
+
11
+ def self.current_uat_major
12
+ prefix = 'origin/release/'
13
+ vers = `git branch -r`
14
+ regex = Regexp.new("^#{prefix}(\\d+\\.\\d+\\.0)$")
15
+ vers = vers.each_line.map do |branch|
16
+ branch = branch.strip
17
+ MrBump::Version.new(branch.gsub(regex, '\1')) if branch[regex]
18
+ end.compact
19
+ vers.max
20
+ end
21
+
22
+ def self.current_uat
23
+ uat = current_uat_major
24
+ vers = `git tag -l`
25
+ vers = vers.each_line.map do |branch|
26
+ MrBump::Version.new(branch) rescue nil
27
+ end.compact
28
+ vers.select { |ver| ver.major == uat.major && ver.minor == uat.minor }.max
29
+ end
30
+
31
+ def self.current_master
32
+ uat = current_uat_major
33
+ vers = `git tag -l`
34
+ vers = vers.each_line.map do |branch|
35
+ MrBump::Version.new(branch) rescue nil
36
+ end.compact
37
+ vers.select { |ver| ver < uat }.max
38
+ end
39
+
40
+ def self.story_information(merge_str)
41
+ branch_fmt = '(?<fix_type>bugfix|feature|hotfix)/(?<dev_id>\w+[-_]?\d+)?'
42
+ merge_pr_fmt = "^Merge pull request #(?<pr_number>\\d+) from \\w+/#{branch_fmt}"
43
+ merge_manual_fmt = "^Merge branch '#{branch_fmt}'"
44
+ matches = Regexp.new(merge_pr_fmt + '|' + merge_manual_fmt).match(merge_str)
45
+ if matches
46
+ type = matches['fix_type'].capitalize
47
+ dev_id = (matches['dev_id'].nil? ? 'UNKNOWN' : matches['dev_id'])
48
+ "#{type} - #{dev_id} - "
49
+ end
50
+ end
51
+
52
+ def self.merge_logs(rev, head)
53
+ git_cmd = "git log --pretty='format:%B' --grep '(^Merge pull request | into #{current_branch}$)' --merges -E"
54
+ log = `#{git_cmd} #{rev}..#{head}`
55
+ log.each_line.map(&:strip).select { |str| !(str.nil? || str == '' || str[0] == '#') }
56
+ end
57
+
58
+ def self.ignored_merges_regex
59
+ @ignored_merges_regex ||= begin
60
+ ignored_branch = '(release|master|develop)'
61
+ regex_pr = "^Merge pull request #\\d+ from Intellection/#{ignored_branch}"
62
+ regex_manual = "^Merge branch '?#{ignored_branch}"
63
+ Regexp.new("#{regex_pr}|#{regex_manual}")
64
+ end
65
+ end
66
+
67
+ def self.change_log_items_for_range(rev, head)
68
+ chunked_log = merge_logs(rev, head).chunk { |change| change[/^Merge/].nil? }
69
+ chunked_log.each_slice(2).map do |merge_str, comment|
70
+ merge_str = merge_str[1][0]
71
+ unless merge_str[ignored_merges_regex]
72
+ "\n* #{story_information(merge_str)}" + comment[1].join("\n ")
73
+ end
74
+ end.compact
75
+ end
76
+
77
+ def self.file_prepend(file, str)
78
+ new_contents = ''
79
+ File.open(file, 'r') do |fd|
80
+ contents = fd.read
81
+ new_contents = str + contents
82
+ end
83
+ File.open(file, 'w') do |fd|
84
+ fd.write(new_contents)
85
+ end
86
+
87
+ def self.config_file
88
+ MrBump::Config.new().config
89
+ end
90
+
91
+ def self.slack_notifier(version, changelog)
92
+ if config_file.key? 'slack'
93
+ MrBump::Slack.new(config_file["slack"]).bump(version, changelog)
94
+ end
95
+ end
96
+
97
+ end
98
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mr_bump
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ platform: ruby
6
+ authors:
7
+ - Richard Fitzgerald
8
+ - Josh Bryant
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-08-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: slack-notifier
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: '1.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: '1.0'
28
+ description: Bump versions
29
+ email: richard.fitzgerald36@gmail.com
30
+ executables:
31
+ - mr_bump
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - bin/mr_bump
36
+ - lib/mr_bump.rb
37
+ - lib/mr_bump/config.rb
38
+ - lib/mr_bump/slack.rb
39
+ - lib/mr_bump/version.rb
40
+ homepage: https://github.com/xulaus/mr_bump
41
+ licenses: []
42
+ metadata: {}
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.4.8
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: BUMP!
63
+ test_files: []