danger-mailmap 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1a6890a42c82be33ac74ca8bc09f3c1501d5ced1826a7683fbabfac5ed4d2fad
4
+ data.tar.gz: 12e2dca8b920de1bef3877252ca9211326b1f7321ae2522e5156751117e64605
5
+ SHA512:
6
+ metadata.gz: de569e1756ca41037464fc4d5c9510bdf2cfc617c6d3f9b4edd10df5f9d76630a4311e0db56f3851299b9199e14e3a8eae1e6baa7ee87a6951c21482e41a400e
7
+ data.tar.gz: 2c9b4efb26ab04ff252be3047ac18e07f062e088b6ebf23942f252d301b88af34ddde43ed29eccd500f0271a16cf9352e17f304f576eacad5e50c19852fb572e
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DangerMailmap
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'danger'
4
+
5
+ module DangerMailmap
6
+ # Collection of refinements of classes in {Danger::RequestSources}.
7
+ module RequestSourcesRefinements
8
+ refine Danger::RequestSources::BitbucketServer do
9
+ def base_branch
10
+ pr_json[:toRef][:id].sub('refs/heads/', '')
11
+ end
12
+
13
+ def head_branch
14
+ pr_json[:fromRef][:id].sub('refs/heads/', '')
15
+ end
16
+ end
17
+
18
+ refine Danger::RequestSources::GitHub do
19
+ def base_branch
20
+ pr_json['base']['ref']
21
+ end
22
+
23
+ def head_branch
24
+ pr_json['head']['ref']
25
+ end
26
+ end
27
+
28
+ refine Danger::RequestSources::VSTS do
29
+ def base_branch
30
+ pr_json[:targetRefName].sub('refs/heads/', '')
31
+ end
32
+
33
+ def head_branch
34
+ pr_json[:sourceRefName].sub('refs/heads/', '')
35
+ end
36
+ end
37
+
38
+ refine Danger::RequestSources::GitLab do
39
+ def base_branch
40
+ mr_json.source_branch
41
+ end
42
+
43
+ def head_branch
44
+ mr_json.target_branch
45
+ end
46
+ end
47
+
48
+ refine Danger::RequestSources::BitbucketCloud do
49
+ def base_branch
50
+ pr_json[:destination][:branch][:name]
51
+ end
52
+
53
+ def head_branch
54
+ pr_json[:source][:branch][:name]
55
+ end
56
+ end
57
+
58
+ refine Danger::RequestSources::LocalOnly do
59
+ def base_branch
60
+ commit = ci_source.base_commit
61
+ scm.exec("rev-parse --quiet --verify #{commit}").empty? ? nil : commit
62
+ end
63
+
64
+ def head_branch
65
+ commit = ci_source.head_commit
66
+ scm.exec("rev-parse --quiet --verify #{commit}").empty? ? nil : commit
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+
5
+ module DangerMailmap
6
+ # A class to format suggestion to fix warnings.
7
+ class SuggestionFormatter
8
+ using ::DangerMailmap::RequestSourcesRefinements
9
+
10
+ HOW_TO_FIX_URL = 'https://github.com/manicmaniac/danger-mailmap#how-to-fix'
11
+ private_constant :HOW_TO_FIX_URL
12
+
13
+ def initialize(request_source, git_working_dir)
14
+ @request_source = request_source
15
+ @git_working_dir = git_working_dir
16
+ end
17
+
18
+ def suggestion(path, emails)
19
+ <<~MARKDOWN
20
+ <blockquote>
21
+ <details><summary>If it is the first time for you to contribute to this repository, add your name and email to mailmap.</summary>
22
+
23
+ ```sh
24
+ #{mailmap_script(path, emails)}
25
+ ```
26
+
27
+ </details>
28
+
29
+ <details><summary>If you want to use another name and email, rewrite commits and push them.</summary>
30
+
31
+ ```sh
32
+ #{filter_branch_script(emails)}
33
+ ```
34
+
35
+ </details>
36
+
37
+ <details><summary>If you did not tell your name and email to Git, configure Git.</summary>
38
+
39
+ ```sh
40
+ git config --global user.email 'correct@example.com'
41
+ git config --global user.name 'Correct Name'
42
+ ```
43
+
44
+ </details>
45
+
46
+ Visit [#{HOW_TO_FIX_URL}](#{HOW_TO_FIX_URL}) for more information.
47
+ </blockquote>
48
+ MARKDOWN
49
+ end
50
+
51
+ def mailmap_script(path, emails)
52
+ path = git_relative_path(path)
53
+ emails.map { |email| "echo 'Correct Name <#{email}>' >> #{path}" }.join("\n")
54
+ end
55
+
56
+ def filter_branch_script(emails) # rubocop:disable Metrics/MethodLength
57
+ base = @request_source.base_branch || '"${BASE_COMMIT_HERE}"'
58
+ head = @request_source.head_branch || 'HEAD'
59
+ script = +"git filter-branch --env-filter '\n"
60
+ emails.each do |email|
61
+ script << indent(4, <<~SHELL)
62
+ if [ "$GIT_AUTHOR_EMAIL" = "#{email}" ]; then
63
+ GIT_AUTHOR_EMAIL="correct@example.com"
64
+ GIT_AUTHOR_NAME="Correct Name"
65
+ fi
66
+ if [ "$GIT_COMMITTER_EMAIL" = "#{email}" ]; then
67
+ GIT_COMMITTER_EMAIL="correct@example.com"
68
+ GIT_COMMITTER_NAME="Correct Name"
69
+ fi
70
+ SHELL
71
+ end
72
+ script << "' --tag-name-filter cat #{base}...#{head}"
73
+ end
74
+
75
+ private
76
+
77
+ def git_relative_path(path)
78
+ Pathname.new(path).relative_path_from(@git_working_dir).to_s
79
+ end
80
+
81
+ def indent(size, string)
82
+ string.lines.map { |line| (' ' * size) + line }.join
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'danger_mailmap/request_sources_refinements'
4
+ require 'danger_mailmap/suggestion_formatter'
5
+ require 'mailmap'
6
+ require 'set'
7
+ require 'shellwords'
8
+
9
+ module Danger
10
+ # A Danger plugin to check if .mailmap has a canonical name of author and committer.
11
+ #
12
+ # @example Check all commits in the pull request against the top-level .mailmap.
13
+ #
14
+ # mailmap.check
15
+ #
16
+ # @example Check against mailmap file in custom location with ignoring some users.
17
+ #
18
+ # mailmap.allowed_patterns = [
19
+ # /.+@(users\.noreply\.)?github\.com/,
20
+ # 'good@example.com'
21
+ # ]
22
+ # mailmap.check '/path/to/mailmap'
23
+ #
24
+ # @see manicmaniac/danger-mailmap
25
+ # @tags git, mailmap
26
+ class DangerMailmap < Plugin
27
+ # Regular expression patterns of email where `danger-mailmap` does not warn like allow-list.
28
+ # If a string is set, it is considered as fixed pattern.
29
+ # @return [Array<String, Regexp>]
30
+ attr_accessor :allowed_patterns
31
+
32
+ # If `true`, `danger-mailmap` will add suggestion comments to a pull request (`true` by default).
33
+ # @return [Boolean]
34
+ attr_accessor :show_suggestion
35
+
36
+ def initialize(*args)
37
+ super(*args)
38
+ self.show_suggestion = true
39
+ end
40
+
41
+ # Check whether if an author of each commits has proper email.
42
+ #
43
+ # @param [String] path Path to .mailmap file (default $GIT_WORK_TREE/.mailmap).
44
+ # @return [void]
45
+ def check(path = nil)
46
+ path = path ? File.expand_path(path) : File.join(git_working_dir, '.mailmap')
47
+ mailmap = Mailmap::Map.load(path)
48
+ commits_by_emails = commits_by_unknown_emails(mailmap)
49
+ return if commits_by_emails.empty?
50
+
51
+ commits_by_emails.each { |email, commits| warn(format_warning(path, email, commits)) }
52
+ markdown(suggestion(path, commits_by_emails.keys)) if show_suggestion
53
+ end
54
+
55
+ private
56
+
57
+ def format_warning(path, email, commits)
58
+ revisions = commits.map(&:sha).join(', ')
59
+ "`#{email}` is not included in #{link_to(path)} (#{revisions})"
60
+ end
61
+
62
+ def git_working_dir
63
+ @git_working_dir ||= Dir.chdir(env.scm.folder) do
64
+ env.scm.exec('rev-parse --show-toplevel')
65
+ end
66
+ end
67
+
68
+ def git_relative_path(path)
69
+ Pathname.new(path).relative_path_from(git_working_dir).to_s
70
+ end
71
+
72
+ def link_to(path)
73
+ relative_path = git_relative_path(path)
74
+ scm_plugin = @dangerfile.respond_to?(danger.scm_provider) ? @dangerfile.public_send(danger.scm_provider) : nil
75
+ method_name = %i[markdown_link html_link].detect { |name| scm_plugin.respond_to?(name) }
76
+ method_name ? scm_plugin.public_send(method_name, relative_path, full_path: false) : relative_path
77
+ end
78
+
79
+ def commits_by_unknown_emails(mailmap)
80
+ commits_by_emails.reject { |email, _| allowed_patterns_include?(email) || mailmap.include_email?(email) }
81
+ end
82
+
83
+ def commits_by_emails
84
+ commits_by_emails = Hash.new do |hash, key|
85
+ hash[key] = Set.new
86
+ end
87
+ git.commits.each do |commit|
88
+ commits_by_emails[commit.author.email] << commit
89
+ commits_by_emails[commit.committer.email] << commit
90
+ end
91
+ commits_by_emails
92
+ end
93
+
94
+ def allowed_patterns_include?(email)
95
+ allowed_patterns&.any? do |pattern|
96
+ if pattern.is_a?(Regexp)
97
+ email =~ pattern
98
+ else
99
+ email == pattern
100
+ end
101
+ end
102
+ end
103
+
104
+ def suggestion(path, emails)
105
+ formatter = ::DangerMailmap::SuggestionFormatter.new(env.request_source, git_working_dir)
106
+ formatter.suggestion(path, emails)
107
+ end
108
+ end
109
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: danger-mailmap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ryosuke Ito
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-12-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: danger-plugin-api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mailmap
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.0
41
+ description: A Danger plugin to check if .mailmap has a canonical name of author and
42
+ committer
43
+ email:
44
+ - rito.0305@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - lib/danger_mailmap/gem_version.rb
50
+ - lib/danger_mailmap/request_sources_refinements.rb
51
+ - lib/danger_mailmap/suggestion_formatter.rb
52
+ - lib/danger_plugin.rb
53
+ homepage: https://github.com/manicmaniac/danger-mailmap
54
+ licenses:
55
+ - MIT
56
+ metadata:
57
+ rubygems_mfa_required: 'true'
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 2.6.0
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubygems_version: 3.0.3.1
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: A Danger plugin to check if .mailmap has a canonical name of author and committer
77
+ test_files: []