-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create tool for getting DCO sign off emails
This tool digs through commit messages and parses out names and email addresses from the `Signed-off-by:` tags, collects all unique email addresses and outputs a CSV of name/email pairs. Signed-off-by: Andrew Ross <[email protected]>
- Loading branch information
Showing
13 changed files
with
931 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# frozen_string_literal: true | ||
|
||
module GitHub | ||
class Commit < Item | ||
# Creates an array of Signers from all 'Signed-off-by' tags included in the | ||
# commit message | ||
def dco_signers | ||
commit.message.scan(/Signed-off-by: (.+) <([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+)>/).map do |signer| | ||
Signer.new(signer[0], signer[1]) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# frozen_string_literal: true | ||
|
||
module GitHub | ||
class Commits < Items | ||
def initialize(arr_or_options) | ||
super arr_or_options, GitHub::Commit | ||
end | ||
|
||
# Gets all unique DCO signers (by email address) from all commits | ||
def dco_signers | ||
Signers.new(each.map(&:dco_signers).flatten) | ||
end | ||
|
||
def page(options) | ||
data = $github.search_commits(query(options), per_page: 1000).items | ||
raise 'There are 1000+ commits returned from a single query, reduce --page.' if data.size >= 1000 | ||
|
||
data.reject do |commit| | ||
commit.commit.author.email.include?('[bot]') | ||
end | ||
end | ||
|
||
def query(options = {}) | ||
GitHub::Searchables.new(options).to_a.concat( | ||
[ | ||
"committer-date:#{options[:from]}..#{options[:to]}" | ||
] | ||
).compact.join(' ') | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# frozen_string_literal: true | ||
|
||
module GitHub | ||
class Signer | ||
attr_reader :email, :name | ||
|
||
def initialize(name, email) | ||
@name = name | ||
@email = email | ||
end | ||
|
||
def to_s | ||
"#{name},#{email}" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# frozen_string_literal: true | ||
|
||
module GitHub | ||
class Signers < Array | ||
def initialize(arr) | ||
# De-dupe by email address, choosing the "best" name | ||
by_email = {} | ||
arr.each do |signer| | ||
by_email[signer.email] = best_signer(by_email[signer.email], signer) | ||
end | ||
super by_email.values | ||
end | ||
|
||
# Sort all "noreply" email addresses to the bottom (for manual curation), then sort by name | ||
def sort_for_display | ||
Signers.new(sort_by { |signer| [signer.email.include?('noreply') ? 1 : 0, signer.name.downcase] }) | ||
end | ||
|
||
private | ||
|
||
def best_signer(left, right) | ||
# The "best" name is defined by the name with the most words. For example, | ||
# if both "dblock" and "Daniel (dB.) Doubrovkine" are encountered, then | ||
# "Daniel (dB.) Doubrovkine" will be chosen. | ||
if left.nil? || right.name.split.length > left.name.split.length | ||
right | ||
else | ||
left | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
696 changes: 696 additions & 0 deletions
696
spec/fixtures/search/opensearch-project/commits_2022-01-01_2022-01-31.yml
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# frozen_string_literal: true | ||
|
||
describe GitHub::Commit do | ||
subject(:commit) do | ||
message = %{Bump opencensus-contrib-http-util from 0.18.0 to 0.31.1 in /plugins/repository-gcs (#3633) | ||
* Bump opencensus-contrib-http-util in /plugins/repository-gcs | ||
Bumps [opencensus-contrib-http-util](https://github.com/census-instrumentation/opencensus-java) from 0.18.0 to 0.31.1. | ||
- [Release notes](https://github.com/census-instrumentation/opencensus-java/releases) | ||
- [Changelog](https://github.com/census-instrumentation/opencensus-java/blob/master/CHANGELOG.md) | ||
- [Commits](census-instrumentation/[email protected]) | ||
--- | ||
updated-dependencies: | ||
- dependency-name: io.opencensus:opencensus-contrib-http-util | ||
dependency-type: direct:production | ||
update-type: version-update:semver-minor | ||
... | ||
Signed-off-by: dependabot[bot] <[email protected]> | ||
* Updating SHAs | ||
Signed-off-by: dependabot[bot] <[email protected]> | ||
* Adding missing classes | ||
Signed-off-by: Vacha Shah <[email protected]> | ||
* changelog change | ||
Signed-off-by: Poojita Raj <[email protected]> | ||
Signed-off-by: dependabot[bot] <[email protected]> | ||
Signed-off-by: Vacha Shah <[email protected]> | ||
Signed-off-by: Poojita Raj <[email protected]> | ||
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> | ||
Co-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com> | ||
Co-authored-by: Vacha Shah <[email protected]> | ||
Co-authored-by: Poojita Raj <[email protected]> | ||
} | ||
resource = Sawyer::Resource.new(Sawyer::Agent.new('fake'), { commit: { message: message } }) | ||
described_class.new(resource) | ||
end | ||
|
||
it 'parses signers from a commit message' do | ||
expect(commit.dco_signers.count).to eq 7 | ||
expect(commit.dco_signers.map(&:name)).to eq ['dependabot[bot]', 'dependabot[bot]', 'Vacha Shah', 'Poojita Raj', 'dependabot[bot]', 'Vacha Shah', 'Poojita Raj'] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# frozen_string_literal: true | ||
|
||
describe GitHub::Commits do | ||
context 'with contributors' do | ||
context 'with org' do | ||
context 'with january 2022' do | ||
context 'with OpenSearch commits', vcr: { cassette_name: 'search/opensearch-project/commits_2022-01-01_2022-01-31' } do | ||
subject(:commits) do | ||
described_class.new(org: 'opensearch-project', repo: 'OpenSearch', from: Date.new(2022, 1, 1), to: Date.new(2022, 1, 31), page: 7) | ||
end | ||
|
||
it 'fetches commits between two dates' do | ||
expect(commits.count).to eq 62 | ||
expect(commits.first['sha']).to eq 'db23f72a2a5da1f21d674bde3a9d1cbe4fb74b19' | ||
end | ||
|
||
it 'collects DCO signers from commits' do | ||
expect(commits.dco_signers.count).to eq 25 | ||
expect(commits.dco_signers.first.name).to eq 'Tianli Feng' | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# frozen_string_literal: true | ||
|
||
describe GitHub::Signers do | ||
context 'with duplicate emails' do | ||
subject(:signers) do | ||
described_class.new([ | ||
GitHub::Signer.new('dev', '[email protected]'), | ||
GitHub::Signer.new('Dev Eloper', '[email protected]'), | ||
GitHub::Signer.new('Dev Eloper, Esq.', '[email protected]') | ||
]) | ||
end | ||
|
||
it 'chooses the best name' do | ||
expect(signers.size).to eq(1) | ||
expect(signers.first.name).to eq('Dev Eloper, Esq.') | ||
end | ||
end | ||
|
||
context 'with noreply email addresses' do | ||
subject(:signers) do | ||
described_class.new([ | ||
GitHub::Signer.new('Mis Configurer', '[email protected]'), | ||
GitHub::Signer.new('dev', '[email protected]') | ||
]) | ||
end | ||
|
||
it 'sorts noreply email addresses to the end' do | ||
expect(signers.size).to eq(2) | ||
expect(signers.sort_for_display.first.email).to eq('[email protected]') | ||
expect(signers.sort_for_display.last.email).to eq('[email protected]') | ||
end | ||
end | ||
end |