pairing_matrix 2.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bbe4d5bda921f70c585704c0021380570c41393f
4
- data.tar.gz: 8299d6cbc89154810b30388d8e6e424dfffa8c4b
2
+ SHA256:
3
+ metadata.gz: 3e8002ffeca17d9683c263f56e41bf754ac911570269d11b9fa8939185110385
4
+ data.tar.gz: 923fe11f8208b690223e23c4542cc2844a620853847344cd53b8a6fecaa2efba
5
5
  SHA512:
6
- metadata.gz: 5062d6a462b5802c747dde64798d89773be670618372ec1a510ecd121a2898cc2f6ad5f445a3dc78aaef5c8c5359cb8c41c9c781c3c15eb5435945b3706b715f
7
- data.tar.gz: 52363d79a8221d0df7c4405a8299c69274b8e97d53700709fec7e80b40bbd390335d591ad16ddad87e950061f835a4b078301673e4bf546ce726363d3702df65
6
+ metadata.gz: d6e1b32c0f6a5fc90d17aecca862fdbcca2afa4eeb70f50f7b3e2acea6cdfd75088a132a09be10c667526fa83daa712a98d712e198eea8c4c083c063d3251663
7
+ data.tar.gz: e6aff865e10b0b7d21d37ba2ade365b39c5db8e04b13f237be9d3d1100a0a1a90f1a81cfe34022b15e4ab5b1bfde250d53dbd9697ea144dbf1d6c74385a6beb6
@@ -0,0 +1,31 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+ branches:
9
+ - master
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ matrix:
16
+ ruby:
17
+ - 2.5
18
+ - 2.6
19
+ - 2.7
20
+ name: Ruby ${{ matrix.ruby }} test
21
+ steps:
22
+ - uses: actions/checkout@v2
23
+ - name: Set up Ruby ${{ matrix.ruby }}
24
+ uses: actions/setup-ruby@v1
25
+ with:
26
+ ruby-version: ${{ matrix.ruby }}
27
+ - name: Build and test
28
+ run: |
29
+ gem install bundler --no-document
30
+ bundle install --jobs 4 --retry 3
31
+ bundle exec rspec
data/.gitignore CHANGED
@@ -23,4 +23,4 @@ tmp
23
23
  mkmf.log
24
24
  .idea
25
25
  *.iml
26
- *.yml
26
+ pairing_matrix.yml
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
@@ -0,0 +1,46 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Examples of behavior that contributes to creating a positive environment include:
10
+
11
+ * Using welcoming and inclusive language
12
+ * Being respectful of differing viewpoints and experiences
13
+ * Gracefully accepting constructive criticism
14
+ * Focusing on what is best for the community
15
+ * Showing empathy towards other community members
16
+
17
+ Examples of unacceptable behavior by participants include:
18
+
19
+ * The use of sexualized language or imagery and unwelcome sexual attention or advances
20
+ * Trolling, insulting/derogatory comments, and personal or political attacks
21
+ * Public or private harassment
22
+ * Publishing others' private information, such as a physical or electronic address, without explicit permission
23
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
24
+
25
+ ## Our Responsibilities
26
+
27
+ Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28
+
29
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30
+
31
+ ## Scope
32
+
33
+ This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34
+
35
+ ## Enforcement
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at jeetsingh.ajit@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38
+
39
+ Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40
+
41
+ ## Attribution
42
+
43
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44
+
45
+ [homepage]: http://contributor-covenant.org
46
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile CHANGED
@@ -1,5 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'sinatra'
4
- gem 'octokit'
5
- gem 'eldritch'
3
+ gemspec
data/README.md CHANGED
@@ -1,11 +1,13 @@
1
1
  # PairingMatrix
2
2
 
3
+ [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/ajitsing/pairing_matrix/graphs/commit-activity)
3
4
  [![Gem Version](https://badge.fury.io/rb/pairing_matrix.svg)](https://badge.fury.io/rb/pairing_matrix)
5
+ [![HitCount](http://hits.dwyl.io/ajitsing/pairing_matrix.svg)](http://hits.dwyl.io/ajitsing/pairing_matrix)
4
6
  ![Gem Downloads](http://ruby-gem-downloads-badge.herokuapp.com/pairing_matrix?type=total)
5
7
  [![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=102)](https://opensource.org/licenses/MIT)
6
8
  [![Twitter Follow](https://img.shields.io/twitter/follow/Ajit5ingh.svg?style=social)](https://twitter.com/Ajit5ingh)
7
9
 
8
- <img src="https://github.com/ajitsing/ScreenShots/blob/master/pairing_matrix/pairing_mat.png" width="600" height="550" />
10
+ <img src="https://github.com/ajitsing/ScreenShots/blob/master/pairing_matrix/pairing_mat.png" width="900" height="550" />
9
11
 
10
12
  ## How to read this matrix?
11
13
  1. This matrix is purely based on commits.
@@ -43,6 +45,12 @@ github_repos:
43
45
  - github_username/my_private_repo
44
46
  ```
45
47
 
48
+ #### github_url:
49
+ Add github url if you are using github enterprise. This entry can be skipped if you are using github.com.
50
+ Mention the API endpoint.
51
+
52
+ example: http://github.mycompany.com/api/v3/
53
+
46
54
  #### authors_regex:
47
55
  This regex is used to extract dev names from the commit message. You can verify your regex in irb console using the below command. If your regex is correct it will return an array of dev names.
48
56
 
@@ -60,7 +68,7 @@ List your repos which you want to use for matrix. If you have your repos inside
60
68
 
61
69
 
62
70
  Now after installing the pairing matrix gem, simply run the ```pairing_matrix``` command in the repo where you have ```pairing_matrix.yml``` file. This command will start a web server.
63
- Then hit the url ```localhost:4567/matrix``` in the browser.
71
+ Then hit the url [localhost:4567/matrix](http://localhost:4567/matrix) or [localhost:4567](http://localhost:4567) in the browser. In case you want to use the json data, hit [http://localhost:4567/data/:days](http://localhost:4567/data/30)
64
72
 
65
73
  ## Some example of pairing_matrix.yml
66
74
  ### Here is a sample pairing_matrix.yml file
@@ -95,6 +103,23 @@ github_repos:
95
103
  - github_username/my_public_repo2
96
104
  ```
97
105
 
106
+ ### Fetching data from github enterprise
107
+
108
+ ```yml
109
+ github_url: http://git.mycompany.com/api/v3/
110
+ authors_regex: ^.*\[([\w]*)(?:\/)?([\w]*)\].*$
111
+ github_repos:
112
+ - github_username/repo1
113
+ - github_username/repo2
114
+ ```
115
+
116
+ ## Contributors
117
+
118
+ Thanks goes to these wonderful people:
119
+
120
+ [Abhishek Thakur](https://github.com/abhikur)
121
+ [Sumit Gupta](https://github.com/sumitgpt)
122
+
98
123
  ## Contributing
99
124
 
100
125
  1. Fork it ( https://github.com/ajitsing/pairing_matrix/fork )
@@ -106,7 +131,7 @@ github_repos:
106
131
 
107
132
  ## License
108
133
  ```LICENSE
109
- Copyright (c) 2017 Ajit Singh
134
+ Copyright (c) 2020 Ajit Singh
110
135
 
111
136
  MIT License
112
137
 
@@ -0,0 +1,39 @@
1
+ require 'date'
2
+
3
+ module PairingMatrix
4
+ class CommitReader
5
+ def initialize(config)
6
+ @config = config
7
+ end
8
+
9
+ def authors_with_commits(days)
10
+ date = (Date.today - days).to_s
11
+ authors = authors(date)
12
+ author_groups = authors.group_by { |n| titleize(n)}
13
+ author_groups.map do |k, v|
14
+ pair = k.split(',')
15
+ pair.unshift('') if pair.size == 1
16
+ [pair, v.size].flatten
17
+ end
18
+ end
19
+
20
+ protected
21
+ def read(since)
22
+ #to be implemented by child commit reader
23
+ end
24
+
25
+ private
26
+ def authors(since)
27
+ commits = if @config.absent? then [] else read(since) end
28
+ commits.map do |commit|
29
+ commit.scan(/#{@config.authors_regex}/).flatten.compact.reject(&:empty?).map { |name| name.gsub(' ', '') }.sort.join(',')
30
+ end.compact.reject(&:empty?)
31
+ end
32
+
33
+ def titleize(name)
34
+ name.gsub(/\w+/) do |word|
35
+ word.capitalize
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,6 +1,7 @@
1
1
  require 'octokit'
2
2
  require 'eldritch'
3
- require_relative './commit_cache'
3
+ require_relative '../cache/commit_cache'
4
+ require_relative './commit_reader'
4
5
 
5
6
  Octokit.auto_paginate = true
6
7
 
@@ -8,35 +9,40 @@ module PairingMatrix
8
9
  class GithubCommitReader < CommitReader
9
10
  def initialize(config)
10
11
  super(config)
11
- @github_client = github_client
12
12
  @cache = CommitCache.new
13
13
  end
14
14
 
15
+ protected
15
16
  def read(since)
16
17
  cache = @cache.get(since)
17
18
  return cache unless cache.nil?
18
19
 
19
20
  commits = []
20
21
  together do
21
- @config.github_repos.map do |repo|
22
+ client = github_client
23
+
24
+ @config.repositories.map do |repo|
22
25
  async do
23
- commits << fetch_commits(repo, since)
26
+ commits << fetch_commits(client, repo, since)
24
27
  end
25
28
  end
26
29
  end
30
+
27
31
  result = commits.flatten
28
32
  @cache.put(since, result)
29
33
  result
30
34
  end
31
35
 
32
36
  private
33
- def fetch_commits(repo, since)
34
- @github_client.commits_since(repo, since).map { |commit| commit.commit.message }
37
+ def fetch_commits(client, repo, since)
38
+ client.commits_since(repo, since).map { |commit| commit.commit.message }
35
39
  end
36
40
 
37
41
  def github_client
38
- if @config.has_github_access_token?
39
- Octokit::Client.new(:access_token => @config.github_access_token)
42
+ Octokit.configure {|c| c.api_endpoint = @config.url}
43
+
44
+ if @config.has_access_token?
45
+ Octokit::Client.new(:access_token => @config.access_token)
40
46
  else
41
47
  Octokit::Client.new
42
48
  end
@@ -0,0 +1,42 @@
1
+ require 'gitlab'
2
+ require 'eldritch'
3
+ require_relative '../cache/commit_cache'
4
+ require_relative './commit_reader'
5
+
6
+ module PairingMatrix
7
+ class GitlabCommitReader < CommitReader
8
+ def initialize(config)
9
+ super(config)
10
+ @cache = CommitCache.new
11
+ end
12
+
13
+ protected
14
+ def read(since)
15
+ cache = @cache.get(since)
16
+ return cache unless cache.nil?
17
+
18
+ commits = []
19
+ together do
20
+ client = gitlab_client
21
+ @config.repositories.map do |repo|
22
+ async do
23
+ commits << fetch_commits(client, repo, since)
24
+ end
25
+ end
26
+ end
27
+
28
+ result = commits.flatten
29
+ @cache.put(since, result)
30
+ result
31
+ end
32
+
33
+ private
34
+ def fetch_commits(client, repo, since)
35
+ client.commits(repo, since: since).map { |commit| commit.title }
36
+ end
37
+
38
+ def gitlab_client
39
+ Gitlab.client(endpoint: @config.url, private_token: @config.access_token)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ require 'date'
2
+ require_relative './commit_reader'
3
+
4
+ module PairingMatrix
5
+ class LocalCommitReader < CommitReader
6
+ def initialize(config)
7
+ super(config)
8
+ end
9
+
10
+ protected
11
+ def read(since)
12
+ commits = []
13
+ @config.repositories.each do |repo|
14
+ Dir.chdir repo do
15
+ commits << read_commits(since)
16
+ end
17
+ end
18
+ commits.flatten
19
+ end
20
+
21
+ private
22
+ def read_commits(since)
23
+ `git log --oneline --after=\"#{since}\"`.split("\n")
24
+ end
25
+ end
26
+ end
@@ -1,20 +1,11 @@
1
1
  module PairingMatrix
2
2
  class Config
3
- attr_reader :repos, :authors_regex, :github_access_token, :github_repos
3
+ attr_reader :authors_regex, :local, :gitlab, :github
4
4
 
5
- def initialize(repos, authors_regex, github_access_token, github_repos)
6
- @repos = repos
7
- @authors_regex = authors_regex
8
- @github_access_token = github_access_token
9
- @github_repos = github_repos
10
- end
11
-
12
- def fetch_from_github?
13
- !@github_repos.nil? && !@github_repos.empty?
14
- end
15
-
16
- def has_github_access_token?
17
- !@github_access_token.nil? && !@github_access_token.empty?
5
+ def initialize(local, gitlab, github)
6
+ @local = local
7
+ @gitlab = gitlab
8
+ @github = github
18
9
  end
19
10
  end
20
- end
11
+ end
@@ -1,5 +1,7 @@
1
1
  require 'yaml'
2
2
  require_relative 'config'
3
+ require_relative 'local_repos'
4
+ require_relative 'remote_repos'
3
5
 
4
6
  module PairingMatrix
5
7
  class ConfigReader
@@ -9,12 +11,13 @@ module PairingMatrix
9
11
 
10
12
  def config
11
13
  raw_config = YAML::load_file @config_file
14
+ author_regex = raw_config['authors_regex']
15
+
12
16
  PairingMatrix::Config.new(
13
- raw_config['repos'],
14
- raw_config['authors_regex'],
15
- raw_config['github_access_token'],
16
- raw_config['github_repos']
17
- )
17
+ PairingMatrix::LocalRepos.create_from(author_regex, raw_config['local']),
18
+ PairingMatrix::RemoteRepos.create_from(author_regex, raw_config['gitlab']),
19
+ PairingMatrix::RemoteRepos.create_from(author_regex, raw_config['github'])
20
+ )
18
21
  end
19
22
  end
20
23
  end
@@ -0,0 +1,19 @@
1
+ module PairingMatrix
2
+ class LocalRepos
3
+ attr_reader :repositories, :url, :authors_regex
4
+
5
+ def initialize(authors_regex, repos)
6
+ @repositories = repos
7
+ @authors_regex = authors_regex
8
+ end
9
+
10
+ def self.create_from(authors_regex, config)
11
+ repos = config['repositories'] rescue []
12
+ LocalRepos.new(authors_regex, repos)
13
+ end
14
+
15
+ def absent?
16
+ @repositories.empty?
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ module PairingMatrix
2
+ class RemoteRepos
3
+ attr_reader :repositories, :access_token, :url, :authors_regex
4
+
5
+ def initialize(authors_regex, repos, access_token, url)
6
+ @url = url
7
+ @repositories = repos
8
+ @authors_regex = authors_regex
9
+ @access_token = access_token
10
+ end
11
+
12
+ def self.create_from(authors_regex, config)
13
+ repos = config['repositories'] rescue []
14
+ access_token = config['access_token'] rescue nil
15
+ url = config['url'] rescue nil
16
+
17
+ RemoteRepos.new(authors_regex, repos, access_token, url)
18
+ end
19
+
20
+ def has_access_token?
21
+ !@access_token.nil? && !@access_token.empty?
22
+ end
23
+
24
+ def absent?
25
+ @repositories.empty?
26
+ end
27
+ end
28
+ end
@@ -1,14 +1,17 @@
1
1
  require 'sinatra/base'
2
+ require 'puma'
2
3
  require 'json'
3
4
  require_relative '../../pairing_matrix'
4
5
  require_relative '../config/config_reader'
5
- require_relative '../commit_reader'
6
- require_relative '../commit_cache'
7
- require_relative '../github_commit_reader'
6
+ require_relative '../cache/commit_cache'
7
+ require_relative '../commit_readers/local_commit_reader'
8
+ require_relative '../commit_readers/github_commit_reader'
9
+ require_relative '../commit_readers/gitlab_commit_reader'
8
10
 
9
11
  module PairingMatrix
10
12
  class Server < Sinatra::Base
11
13
  set :bind, '0.0.0.0'
14
+ set :server, :puma
12
15
 
13
16
  logging_file = File.new('app.log', 'a+')
14
17
  logging_file.sync = true
@@ -24,16 +27,27 @@ module PairingMatrix
24
27
  PairingMatrix.enable_caching = true
25
28
  config_reader = PairingMatrix::ConfigReader.new('pairing_matrix.yml')
26
29
  config = config_reader.config
27
- commit_reader = PairingMatrix::CommitReader.new(config)
28
- commit_reader = PairingMatrix::GithubCommitReader.new(config) if config.fetch_from_github?
30
+
31
+ local_commit_reader = PairingMatrix::LocalCommitReader.new(config.local)
32
+ github_commit_reader = PairingMatrix::GithubCommitReader.new(config.github)
33
+ gitlab_commit_reader = PairingMatrix::GitlabCommitReader.new(config.gitlab)
29
34
 
30
35
  get '/data/:days' do
31
36
  PairingMatrix.enable_caching = params[:cache_enabled] != 'false'
32
- commit_reader.authors_with_commits(params['days'].to_i).to_json
37
+
38
+ local_data = local_commit_reader.authors_with_commits(params['days'].to_i)
39
+ github_data = github_commit_reader.authors_with_commits(params['days'].to_i)
40
+ gitlab_data = gitlab_commit_reader.authors_with_commits(params['days'].to_i)
41
+
42
+ (local_data + github_data + gitlab_data).to_json
33
43
  end
34
44
 
35
45
  get '/matrix' do
36
46
  File.read(File.join(File.dirname(__FILE__), 'public/index.html'))
37
47
  end
48
+
49
+ get '/' do
50
+ redirect '/matrix'
51
+ end
38
52
  end
39
- end
53
+ end
@@ -1,3 +1,3 @@
1
1
  module PairingMatrix
2
- VERSION = '2.1'
2
+ VERSION = '3.0.0'
3
3
  end
@@ -18,8 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency 'bundler', '~> 1.6'
21
+ spec.add_development_dependency 'rspec', '~> 3.10'
22
22
  spec.add_dependency 'sinatra', '~> 1.4.8'
23
- spec.add_dependency 'octokit', '~> 4.6.2'
23
+ spec.add_dependency 'octokit', '~> 4.15.0'
24
+ spec.add_dependency 'gitlab', '~> 4.17.0'
24
25
  spec.add_dependency 'eldritch', '~> 1.1.2'
26
+ spec.add_dependency 'puma', '~> 3.12.6'
25
27
  end
@@ -0,0 +1,40 @@
1
+ require 'ostruct'
2
+ require './lib/pairing_matrix/commit_readers/github_commit_reader'
3
+
4
+ describe PairingMatrix::GithubCommitReader do
5
+ context '#authors_with_commits' do
6
+ it 'returns authors with number of commits' do
7
+ config_reader = PairingMatrix::ConfigReader.new('./spec/lib/pairing_matrix/config/sample_configurations/github_repositories.yml')
8
+ configuration = config_reader.config
9
+ github_config = configuration.github
10
+
11
+ days = 10
12
+ reader = PairingMatrix::GithubCommitReader.new(github_config)
13
+
14
+ github_client = double(:github_client)
15
+ expect(Octokit::Client).to receive(:new)
16
+ .with(access_token: github_config.access_token)
17
+ .and_return(github_client)
18
+
19
+ commits = [
20
+ OpenStruct.new(commit: OpenStruct.new(message: "[Author1/Author2] commit 1")),
21
+ OpenStruct.new(commit: OpenStruct.new(message: "[Author1/Author2] commit 2")),
22
+ OpenStruct.new(commit: OpenStruct.new(message: "[Author2/Author3] commit 3")),
23
+ OpenStruct.new(commit: OpenStruct.new(message: "[Author2/Author3] commit 4")),
24
+ OpenStruct.new(commit: OpenStruct.new(message: "[Author4/Author1] commit 5")),
25
+ ]
26
+
27
+ expect(github_client).to receive(:commits_since)
28
+ .with(github_config.repositories.first, (Date.today - days).to_s)
29
+ .and_return(commits)
30
+
31
+ expect(github_client).to receive(:commits_since)
32
+ .with(github_config.repositories.last, (Date.today - days).to_s)
33
+ .and_return(commits)
34
+
35
+ result = reader.authors_with_commits(10)
36
+
37
+ expect(result).to eql([["Author1", "Author2", 4], ["Author2", "Author3", 4], ["Author1", "Author4", 2]])
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ require 'ostruct'
2
+ require './lib/pairing_matrix/commit_readers/gitlab_commit_reader'
3
+
4
+ describe PairingMatrix::GitlabCommitReader do
5
+ context '#authors_with_commits' do
6
+ it 'returns authors with number of commits' do
7
+ config_reader = PairingMatrix::ConfigReader.new('./spec/lib/pairing_matrix/config/sample_configurations/gitlab_repositories.yml')
8
+ configuration = config_reader.config
9
+ gitlab_config = configuration.gitlab
10
+
11
+ days = 10
12
+ reader = PairingMatrix::GitlabCommitReader.new(gitlab_config)
13
+
14
+ gitlab_client = double(:gitlab_client)
15
+ expect(Gitlab).to receive(:client)
16
+ .with(private_token: gitlab_config.access_token, endpoint: gitlab_config.url)
17
+ .and_return(gitlab_client)
18
+
19
+ commits = [
20
+ OpenStruct.new(title: "[Author1/Author2] commit 1"),
21
+ OpenStruct.new(title: "[Author1/Author2] commit 2"),
22
+ OpenStruct.new(title: "[Author2/Author3] commit 3"),
23
+ OpenStruct.new(title: "[Author2/Author3] commit 4"),
24
+ OpenStruct.new(title: "[Author4/Author1] commit 5"),
25
+ ]
26
+
27
+ expect(gitlab_client).to receive(:commits)
28
+ .with(gitlab_config.repositories.first, since: (Date.today - days).to_s)
29
+ .and_return(commits)
30
+
31
+ expect(gitlab_client).to receive(:commits)
32
+ .with(gitlab_config.repositories.last, since: (Date.today - days).to_s)
33
+ .and_return(commits)
34
+
35
+ result = reader.authors_with_commits(10)
36
+
37
+ expect(result).to eql([["Author1", "Author2", 4], ["Author2", "Author3", 4], ["Author1", "Author4", 2]])
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,47 @@
1
+ require './lib/pairing_matrix/config/config'
2
+ require './lib/pairing_matrix/config/config_reader'
3
+
4
+ describe PairingMatrix::ConfigReader do
5
+ describe '#config' do
6
+ context 'Github' do
7
+ it 'should read github configuration' do
8
+ config_reader = PairingMatrix::ConfigReader.new('./spec/lib/pairing_matrix/config/sample_configurations/github_repositories.yml')
9
+ configuration = config_reader.config
10
+
11
+ expect(configuration.github.repositories.size).to eql(2)
12
+ expect(configuration.github.repositories).to eql(['github_username/my_private_repo_1', 'github_username/my_private_repo_2'])
13
+ expect(configuration.github.access_token).to eql('000324cff69wes5613f732c345hn679c0knt509c')
14
+ expect(configuration.github.url).to eq('https://api.github.com/')
15
+ expect(configuration.github.authors_regex).to eql('^.*\[([\w]*)(?:\/)?([\w]*)\].*$')
16
+ end
17
+ end
18
+
19
+ context 'Local' do
20
+ it 'read local repositories' do
21
+ config_reader = PairingMatrix::ConfigReader.new('./spec/lib/pairing_matrix/config/sample_configurations/local_repositories.yml')
22
+ configuration = config_reader.config
23
+
24
+ expect(configuration.local.repositories.size).to eql(3)
25
+ expect(configuration.local.repositories).to eql([
26
+ '/Users/Ajit/projects/project1',
27
+ '/Users/Ajit/projects/project2',
28
+ '/Users/Ajit/projects/project3'
29
+ ])
30
+ expect(configuration.local.authors_regex).to eql('^.*\[([\w]*)(?:\/)?([\w]*)\].*$')
31
+ end
32
+ end
33
+
34
+ context 'Gitlab' do
35
+ it 'should read gitlab repositories' do
36
+ config_reader = PairingMatrix::ConfigReader.new('./spec/lib/pairing_matrix/config/sample_configurations/gitlab_repositories.yml')
37
+ configuration = config_reader.config
38
+
39
+ expect(configuration.gitlab.repositories.size).to eql(2)
40
+ expect(configuration.gitlab.repositories).to eql(['gitlab_username/my_repo_1', 'gitlab_username/my_repo_2'])
41
+ expect(configuration.gitlab.access_token).to eql('Eu2ZVk8lL3P0YGw_aCFl')
42
+ expect(configuration.gitlab.url).to eql('https://gitlab.com/api/v4')
43
+ expect(configuration.gitlab.authors_regex).to eql('^.*\[([\w]*)(?:\/)?([\w]*)\].*$')
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,8 @@
1
+ authors_regex: ^.*\[([\w]*)(?:\/)?([\w]*)\].*$
2
+
3
+ github:
4
+ url: https://api.github.com/
5
+ access_token: 000324cff69wes5613f732c345hn679c0knt509c
6
+ repositories:
7
+ - github_username/my_private_repo_1
8
+ - github_username/my_private_repo_2
@@ -0,0 +1,8 @@
1
+ authors_regex: ^.*\[([\w]*)(?:\/)?([\w]*)\].*$
2
+
3
+ gitlab:
4
+ url: https://gitlab.com/api/v4
5
+ access_token: Eu2ZVk8lL3P0YGw_aCFl
6
+ repositories:
7
+ - gitlab_username/my_repo_1
8
+ - gitlab_username/my_repo_2
@@ -0,0 +1,7 @@
1
+ authors_regex: ^.*\[([\w]*)(?:\/)?([\w]*)\].*$
2
+
3
+ local:
4
+ repositories:
5
+ - /Users/Ajit/projects/project1
6
+ - /Users/Ajit/projects/project2
7
+ - /Users/Ajit/projects/project3
@@ -0,0 +1,100 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
16
+ RSpec.configure do |config|
17
+ # rspec-expectations config goes here. You can use an alternate
18
+ # assertion/expectation library such as wrong or the stdlib/minitest
19
+ # assertions if you prefer.
20
+ config.expect_with :rspec do |expectations|
21
+ # This option will default to `true` in RSpec 4. It makes the `description`
22
+ # and `failure_message` of custom matchers include text for helper methods
23
+ # defined using `chain`, e.g.:
24
+ # be_bigger_than(2).and_smaller_than(4).description
25
+ # # => "be bigger than 2 and smaller than 4"
26
+ # ...rather than:
27
+ # # => "be bigger than 2"
28
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
29
+ end
30
+
31
+ # rspec-mocks config goes here. You can use an alternate test double
32
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
33
+ config.mock_with :rspec do |mocks|
34
+ # Prevents you from mocking or stubbing a method that does not exist on
35
+ # a real object. This is generally recommended, and will default to
36
+ # `true` in RSpec 4.
37
+ mocks.verify_partial_doubles = true
38
+ end
39
+
40
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
41
+ # have no way to turn it off -- the option exists only for backwards
42
+ # compatibility in RSpec 3). It causes shared context metadata to be
43
+ # inherited by the metadata hash of host groups and examples, rather than
44
+ # triggering implicit auto-inclusion in groups with matching metadata.
45
+ config.shared_context_metadata_behavior = :apply_to_host_groups
46
+
47
+ # The settings below are suggested to provide a good initial experience
48
+ # with RSpec, but feel free to customize to your heart's content.
49
+ =begin
50
+ # This allows you to limit a spec run to individual examples or groups
51
+ # you care about by tagging them with `:focus` metadata. When nothing
52
+ # is tagged with `:focus`, all examples get run. RSpec also provides
53
+ # aliases for `it`, `describe`, and `context` that include `:focus`
54
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
55
+ config.filter_run_when_matching :focus
56
+
57
+ # Allows RSpec to persist some state between runs in order to support
58
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
59
+ # you configure your source control system to ignore this file.
60
+ config.example_status_persistence_file_path = "spec/examples.txt"
61
+
62
+ # Limits the available syntax to the non-monkey patched syntax that is
63
+ # recommended. For more details, see:
64
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
65
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
66
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
67
+ config.disable_monkey_patching!
68
+
69
+ # This setting enables warnings. It's recommended, but in some cases may
70
+ # be too noisy due to issues in dependencies.
71
+ config.warnings = true
72
+
73
+ # Many RSpec users commonly either run the entire suite or an individual
74
+ # file, and it's useful to allow more verbose output when running an
75
+ # individual spec file.
76
+ if config.files_to_run.one?
77
+ # Use the documentation formatter for detailed output,
78
+ # unless a formatter has already been configured
79
+ # (e.g. via a command-line flag).
80
+ config.default_formatter = "doc"
81
+ end
82
+
83
+ # Print the 10 slowest examples and example groups at the
84
+ # end of the spec run, to help surface which specs are running
85
+ # particularly slow.
86
+ config.profile_examples = 10
87
+
88
+ # Run specs in random order to surface order dependencies. If you find an
89
+ # order dependency and want to debug it, you can fix the order by providing
90
+ # the seed, which is printed after each run.
91
+ # --seed 1234
92
+ config.order = :random
93
+
94
+ # Seed global randomization in this process using the `--seed` CLI option.
95
+ # Setting this allows you to use `--seed` to deterministically reproduce
96
+ # test failures related to randomization by passing the same `--seed` value
97
+ # as the one that triggered the failure.
98
+ Kernel.srand config.seed
99
+ =end
100
+ end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pairing_matrix
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.1'
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ajit Singh
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-23 00:00:00.000000000 Z
11
+ date: 2021-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: rspec
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.6'
19
+ version: '3.10'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.6'
26
+ version: '3.10'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: sinatra
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +44,28 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 4.6.2
47
+ version: 4.15.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 4.6.2
54
+ version: 4.15.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: gitlab
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 4.17.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 4.17.0
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: eldritch
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +80,20 @@ dependencies:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
82
  version: 1.1.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: puma
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 3.12.6
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 3.12.6
69
97
  description: Draw pairing matrix from given repos and configurations
70
98
  email:
71
99
  - jeetsingh.ajit@gmail.com
@@ -74,18 +102,25 @@ executables:
74
102
  extensions: []
75
103
  extra_rdoc_files: []
76
104
  files:
105
+ - ".github/workflows/ruby.yml"
77
106
  - ".gitignore"
107
+ - ".rspec"
108
+ - CODE_OF_CONDUCT.md
78
109
  - Gemfile
79
110
  - LICENSE.txt
80
111
  - README.md
81
112
  - Rakefile
82
113
  - bin/pairing_matrix
83
114
  - lib/pairing_matrix.rb
84
- - lib/pairing_matrix/commit_cache.rb
85
- - lib/pairing_matrix/commit_reader.rb
115
+ - lib/pairing_matrix/cache/commit_cache.rb
116
+ - lib/pairing_matrix/commit_readers/commit_reader.rb
117
+ - lib/pairing_matrix/commit_readers/github_commit_reader.rb
118
+ - lib/pairing_matrix/commit_readers/gitlab_commit_reader.rb
119
+ - lib/pairing_matrix/commit_readers/local_commit_reader.rb
86
120
  - lib/pairing_matrix/config/config.rb
87
121
  - lib/pairing_matrix/config/config_reader.rb
88
- - lib/pairing_matrix/github_commit_reader.rb
122
+ - lib/pairing_matrix/config/local_repos.rb
123
+ - lib/pairing_matrix/config/remote_repos.rb
89
124
  - lib/pairing_matrix/server/public/index.html
90
125
  - lib/pairing_matrix/server/public/index.js
91
126
  - lib/pairing_matrix/server/public/loader.css
@@ -94,11 +129,18 @@ files:
94
129
  - lib/pairing_matrix/server/server.rb
95
130
  - lib/pairing_matrix/version.rb
96
131
  - pairing_matrix.gemspec
132
+ - spec/lib/pairing_matrix/commit_readers/github_commit_reader_spec.rb
133
+ - spec/lib/pairing_matrix/commit_readers/gitlab_commit_reader_spec.rb
134
+ - spec/lib/pairing_matrix/config/config_reader_spec.rb
135
+ - spec/lib/pairing_matrix/config/sample_configurations/github_repositories.yml
136
+ - spec/lib/pairing_matrix/config/sample_configurations/gitlab_repositories.yml
137
+ - spec/lib/pairing_matrix/config/sample_configurations/local_repositories.yml
138
+ - spec/spec_helper.rb
97
139
  homepage: https://github.com/ajitsing/pairing_matrix
98
140
  licenses:
99
141
  - MIT
100
142
  metadata: {}
101
- post_install_message:
143
+ post_install_message:
102
144
  rdoc_options: []
103
145
  require_paths:
104
146
  - lib
@@ -113,9 +155,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
155
  - !ruby/object:Gem::Version
114
156
  version: '0'
115
157
  requirements: []
116
- rubyforge_project:
117
- rubygems_version: 2.6.13
118
- signing_key:
158
+ rubygems_version: 3.0.4
159
+ signing_key:
119
160
  specification_version: 4
120
161
  summary: Draw pairing matrix from given repos and configurations
121
- test_files: []
162
+ test_files:
163
+ - spec/lib/pairing_matrix/commit_readers/github_commit_reader_spec.rb
164
+ - spec/lib/pairing_matrix/commit_readers/gitlab_commit_reader_spec.rb
165
+ - spec/lib/pairing_matrix/config/config_reader_spec.rb
166
+ - spec/lib/pairing_matrix/config/sample_configurations/github_repositories.yml
167
+ - spec/lib/pairing_matrix/config/sample_configurations/gitlab_repositories.yml
168
+ - spec/lib/pairing_matrix/config/sample_configurations/local_repositories.yml
169
+ - spec/spec_helper.rb
@@ -1,42 +0,0 @@
1
- require 'date'
2
-
3
- module PairingMatrix
4
- class CommitReader
5
- def initialize(config)
6
- @config = config
7
- end
8
-
9
- def read(since)
10
- commits = []
11
- @config.repos.each do |repo|
12
- Dir.chdir repo do
13
- commits << read_commits(since)
14
- end
15
- end
16
- commits.flatten
17
- end
18
-
19
- def authors(since)
20
- commits = read(since)
21
- commits.map do |commit|
22
- commit.scan(/#{@config.authors_regex}/).flatten.compact.reject(&:empty?).map { |name| name.gsub(' ', '') }.sort.join(',')
23
- end.compact.reject(&:empty?)
24
- end
25
-
26
- def authors_with_commits(days)
27
- date = (Date.today - days).to_s
28
- authors = authors(date)
29
- author_groups = authors.group_by { |n| n }
30
- author_groups.map do |k, v|
31
- pair = k.split(',')
32
- pair.unshift('') if pair.size == 1
33
- [pair, v.size].flatten
34
- end
35
- end
36
-
37
- private
38
- def read_commits(since)
39
- `git log --oneline --after=\"#{since}\"`.split("\n")
40
- end
41
- end
42
- end