danger-mailmap 0.1.0

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,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: []