mr_bump 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []