gitmarshal 1.0.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 351dad1ba766260604fdb167d697a209b9d2b4ad45782f7bf3b738520541ce31
4
- data.tar.gz: 1980015eef8a3cc130ec2eb6b20d56736b78c8a2ab5e3e85c01281de239a205c
3
+ metadata.gz: 9d1136a825070f9c33c0a3288175c2d1df3bc56c861a2c4612d1e91728b54eff
4
+ data.tar.gz: 27de3ae232d1d9e8694cb3433f3a3f74853a67a1a5b34987ff9995a872e96b53
5
5
  SHA512:
6
- metadata.gz: 594847b1f1427ec8bdc359475090cb71faa23e27224f9032c16341c9bb6d58b6b66ee39b278226f78cc9844a090875f04c7de700792d1759425edd55d1aba6de
7
- data.tar.gz: 50404ba54d11d352929f646c40e77f19eaf2af86a399bf4bf7d0b1ba3c74306fb07b6617b1ff5bb8e7d20c39903f9ad0966f6f25cd1b764bab37c59ce5f43614
6
+ metadata.gz: d223482bd2ff8d5b20d62bb98402f974073ab02ca98f845df36b0dea27ab5d2c8c863d90d61c450b5d21430e3ff3e906006a117056cf26bfd1aabcec0dbd9cab
7
+ data.tar.gz: 967f16553443e6ba49828f2cbabfb8b267784e3b02279540b8c420fc41be227e7eec5d6a79682b798c5990025df8e24c1d0a135b41aebf900bd0a6d7a327ae6f
data/README.md CHANGED
@@ -1,17 +1,21 @@
1
1
  # GitMarshal
2
- [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Maintainability](https://api.codeclimate.com/v1/badges/a9c81f4f449374df1e0c/maintainability)](https://codeclimate.com/github/nagstler/gitmarshal/maintainability)
2
+ [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Maintainability](https://api.codeclimate.com/v1/badges/a9c81f4f449374df1e0c/maintainability)](https://codeclimate.com/github/nagstler/gitmarshal/maintainability) [![CI Build](https://github.com/nagstler/gitmarshal/actions/workflows/gem-push.yml/badge.svg?branch=main)](https://github.com/nagstler/gitmarshal/actions/workflows/gem-push.yml)
3
3
 
4
4
  GitMarshal is a command-line interface (CLI) to extract and display various statistics about GitHub repositories. The metrics it retrieves include the number of commits, pull requests, issues, stars, and contributors.
5
5
 
6
6
  Whether you're a developer interested in the activity of a repository or a manager tracking the progress of your project, GitMarshal provides an easy way to fetch this data directly from your command line.
7
7
 
8
- ## Features
8
+ ## :sparkles: Features
9
9
 
10
- - Fetch and display a summary of your GitHub repositories.
11
- - Fetch and display detailed metrics for a specific repository, including number of commits, pull requests, issues, stars, and contributors.
12
- - Easy-to-use command-line interface.
13
- - Configurable through environment variables.
14
- - Available as a Ruby gem for easy installation.
10
+ :octocat: Fetch and display a summary of your GitHub repositories.
11
+
12
+ :bar_chart: Fetch and display detailed metrics for a specific repository, including number of commits, pull requests, issues, stars, and contributors.
13
+
14
+ :computer: Easy-to-use command-line interface.
15
+
16
+ :wrench: Configurable through environment variables.
17
+
18
+ :gem: Available as a Ruby gem for easy installation.
15
19
 
16
20
 
17
21
  ## Table of Contents
@@ -61,6 +65,7 @@ export GITHUB_TOKEN=your_github_token_here
61
65
  Be sure to replace `your_github_token_here` with the token you generated in the Prerequisites step.
62
66
 
63
67
  ## Usage
68
+
64
69
  Once installed and configured, GitMarshal can be used directly from the command-line as follows:
65
70
 
66
71
  ### List All Repositories
@@ -75,13 +80,33 @@ This will provide you with a comprehensive list of your repositories and will sh
75
80
 
76
81
  ### Fetch Metrics for a Specific Repository
77
82
 
78
- To fetch and display metrics for a specific repository, use:
83
+ To fetch and display overall metrics for a specific repository, use:
79
84
 
80
85
  ```bash
81
86
  gitmarshal repo-name
82
87
  ```
83
88
 
84
- Replace `repo_name` with the name of the repository for which you wish to fetch metrics.
89
+ Replace `repo-name` with the name of the repository for which you wish to fetch metrics.
90
+
91
+ ### Fetch Today's Metrics for a Specific Repository
92
+
93
+ To fetch and display metrics for a specific repository for today only, use:
94
+
95
+ ```bash
96
+ gitmarshal repo-name --today
97
+ ```
98
+
99
+ Replace `repo-name` with the name of the repository for which you wish to fetch today's metrics.
100
+
101
+ ### Help Command
102
+
103
+ If you need help with the commands or if you are unsure about the functionality of GitMarshal, use the help command:
104
+
105
+ ```bash
106
+ gitmarshal help
107
+ ```
108
+
109
+ This will display a helpful guide on how to use GitMarshal, its options, and commands.
85
110
 
86
111
  ## Development
87
112
 
@@ -93,8 +118,6 @@ cd gitmarshal
93
118
  bundle install
94
119
  ```
95
120
 
96
-
97
-
98
121
  You can then run the tests with:
99
122
 
100
123
  ```bash
@@ -1,5 +1,5 @@
1
- require 'json'
2
- require 'net/http'
1
+ require "json"
2
+ require "net/http"
3
3
 
4
4
  class BaseFetcher
5
5
  GITHUB_API_BASE_URL = "https://api.github.com"
@@ -7,16 +7,15 @@ class BaseFetcher
7
7
  protected
8
8
 
9
9
  def execute_http_request(req)
10
- Net::HTTP.start(req.uri.hostname, req.uri.port, :use_ssl => req.uri.scheme == 'https') do |http|
10
+ Net::HTTP.start(req.uri.hostname, req.uri.port, :use_ssl => req.uri.scheme == "https") do |http|
11
11
  http.request(req)
12
12
  end
13
13
  end
14
14
 
15
15
  def create_request(uri)
16
16
  Net::HTTP::Get.new(uri,
17
- "Content-Type" => "application/json",
18
- "Authorization" => "Bearer #{ENV['GITHUB_TOKEN']}"
19
- )
17
+ "Content-Type" => "application/json",
18
+ "Authorization" => "Bearer #{ENV["GITHUB_TOKEN"]}")
20
19
  end
21
20
 
22
21
  def parse_response(response)
@@ -1,110 +1,140 @@
1
- require 'thor'
2
- require 'terminal-table'
3
- require 'colorize'
4
- require_relative 'github_fetcher'
1
+ require "thor"
2
+ require "terminal-table"
3
+ require "colorize"
4
+ require_relative "github_fetcher"
5
5
 
6
6
  module GitMarshal
7
7
  class CLI < Thor
8
- class_option :help, type: :boolean, aliases: '-h', desc: 'Display usage information'
8
+ class_option :help, type: :boolean, aliases: "-h", desc: "Display usage information"
9
+ class_option :today, type: :boolean, aliases: "-t", desc: 'Display today\'s repository metrics instead of overall metrics'
9
10
 
10
11
  desc "repos", "Prints a summary of the authenticated user's GitHub repositories"
12
+
11
13
  def repos
12
14
  begin
13
15
  fetcher = GithubFetcher.new
14
16
  user = fetcher.fetch_user
15
17
  repos = fetcher.fetch_repos
16
-
18
+
17
19
  puts "GitHub Repositories for #{user}".colorize(:blue).bold
18
-
20
+
19
21
  rows = repos.map do |repo|
20
22
  [
21
- repo['name'],
22
- repo['issues'],
23
- repo['stargazers'],
24
- repo['forks']
23
+ repo["name"],
24
+ repo["issues"],
25
+ repo["stargazers"],
26
+ repo["forks"],
25
27
  ]
26
28
  end
27
-
29
+
28
30
  table = Terminal::Table.new :title => "Repositories".colorize(:green).bold,
29
- :headings => ['Name', 'Issues', 'Stargazers', 'Forks'].map { |i| i.colorize(:magenta).bold },
31
+ :headings => ["Name", "Issues", "Stargazers", "Forks"].map { |i| i.colorize(:magenta).bold },
30
32
  :rows => rows
31
-
33
+
32
34
  table.style = { :border_x => "=", :border_i => "x", :alignment => :center }
33
35
  puts table
34
36
  rescue StandardError => e
35
37
  puts "An error occurred: #{e.message}"
36
38
  end
37
39
  end
38
-
39
40
 
40
41
  def help(*)
41
- puts "You can either call ./bin/gitmarshal to list all repositories or ./bin/gitmarshal repo-name to show the metrics of the given repository."
42
+ rows = []
43
+ rows << ["gitmarshal", "List all repositories of the authenticated user"]
44
+ rows << ["gitmarshal repo-name", "Show the overall metrics of the given repository"]
45
+ rows << ["gitmarshal repo-name --today", "Show today's metrics of the given repository"]
46
+
47
+ table = Terminal::Table.new :rows => rows
48
+ table.title = "GitMarshal Commands".colorize(:green).bold
49
+ table.headings = ['Command', 'Description'].map { |i| i.colorize(:magenta).bold }
50
+ table.style = { :border_x => "=", :border_i => "x", :alignment => :left }
51
+ puts table
42
52
  end
43
53
 
44
54
  private
45
55
 
46
- def metrics(repo_name)
56
+ def metrics(repo_name, today_option = false)
47
57
  fetcher = GithubFetcher.new
48
58
  user = fetcher.fetch_user
49
-
50
- repo = fetcher.fetch_repo_metrics(user, repo_name)
51
-
52
- # Print repository name and other details as introduction
53
- puts "GitHub Repository: #{repo['name']}".colorize(:blue).bold
54
- puts "Description: #{repo['description']}"
55
- puts "Default Branch: #{repo['default_branch']}"
56
- puts "Last Updated At: #{repo['last_updated_at']}"
57
-
58
- puts "x======================================x"
59
-
60
- # Display latest commit
61
- latest_commit = fetcher.fetch_latest_commit(user, repo_name)
62
- if latest_commit
63
- puts "Latest Commit:".colorize(:blue).bold
64
- puts "Commit Date: #{latest_commit['commit']['committer']['date']}"
65
- puts "Commit Message: #{latest_commit['commit']['message']}"
59
+
60
+ repo = today_option ? fetcher.fetch_today_repo_metrics(user, repo_name) : fetcher.fetch_repo_metrics(user, repo_name)
61
+
62
+ if today_option
63
+ rows = prepare_table_rows_for_today(repo)
64
+ # Display latest commit
65
+ latest_commit = fetcher.fetch_latest_commit(user, repo_name)
66
+ if latest_commit
67
+ rows << ["Latest Commit Date", latest_commit["commit"]["committer"]["date"]]
68
+ rows << ["Latest Commit Message", wrap_text(latest_commit["commit"]["message"])]
69
+ end
70
+ # Display today's metrics in a table
71
+ display_table("Today's Repository Metrics", rows)
72
+ else
73
+ rows = prepare_table_rows(repo)
74
+ # Display latest commit
75
+ latest_commit = fetcher.fetch_latest_commit(user, repo_name)
76
+ if latest_commit
77
+ rows << ["Latest Commit Date", latest_commit["commit"]["committer"]["date"]]
78
+ rows << ["Latest Commit Message", wrap_text(latest_commit["commit"]["message"])]
79
+ end
80
+ # Display overall metrics in a table
81
+ display_table("Repository Metrics", rows)
66
82
  end
67
-
68
- # Display repository metrics in a table
69
- rows = [
70
- ['Total Commits', repo['commits_count']],
71
- ['Pull Requests', repo['pull_requests_count']],
72
- ['Forks', repo['forks_count']],
73
- ['Watchers', repo['watchers_count']],
74
- ['Issues', repo['issues_count']],
75
- ['Open Issues', repo['open_issues_count']],
76
- ['Closed Issues', repo['closed_issues_count']],
77
- ['Open Pull Requests', repo['open_pull_requests_count']],
78
- ['Closed Pull Requests', repo['closed_pull_requests_count']],
79
- ['Contributors', repo['contributors_count']],
80
- ['Stargazers', repo['stargazers_count']]
83
+ end
84
+
85
+ private
86
+
87
+ def wrap_text(text, max_width = 50)
88
+ text.gsub(/(.{1,#{max_width}})(\s+|\Z)/, "\\1\n")
89
+ end
90
+
91
+ def prepare_table_rows_for_today(repo)
92
+ [
93
+ ["Repository Name", repo["name"]],
94
+ ["Total Commits", repo["commits_count"].to_s],
95
+ ["Pull Requests", repo["pull_requests_count"].to_s],
96
+ ["Forks", repo["forks_count"].to_s],
97
+ ["Issues", repo["issues_count"].to_s],
98
+ ["Open Issues", repo["open_issues_count"].to_s],
99
+ ["Closed Issues", repo["closed_issues_count"].to_s],
100
+ ["Open Pull Requests", repo["open_pull_requests_count"].to_s],
101
+ ["Closed Pull Requests", repo["closed_pull_requests_count"].to_s],
81
102
  ]
82
-
83
- table = Terminal::Table.new :title => "Repository Metrics".colorize(:blue).bold, :headings => ['Metric', 'Count'].map { |i| i.colorize(:magenta).bold }, :rows => rows
103
+ end
104
+
105
+ def prepare_table_rows(repo)
106
+ [
107
+ ["Repository Name", repo["name"]],
108
+ ["Default Branch", repo["default_branch"]],
109
+ ["Last Updated At", repo["last_updated_at"]],
110
+ ["Total Commits", repo["commits_count"].to_s],
111
+ ["Pull Requests", repo["pull_requests_count"].to_s],
112
+ ["Forks", repo["forks_count"].to_s],
113
+ ["Watchers", repo["watchers_count"].to_s],
114
+ ["Issues", repo["issues_count"].to_s],
115
+ ["Open Issues", repo["open_issues_count"].to_s],
116
+ ["Closed Issues", repo["closed_issues_count"].to_s],
117
+ ["Open Pull Requests", repo["open_pull_requests_count"].to_s],
118
+ ["Closed Pull Requests", repo["closed_pull_requests_count"].to_s],
119
+ ["Contributors", repo["contributors_count"].to_s],
120
+ ["Stargazers", repo["stargazers_count"].to_s],
121
+ ]
122
+ end
123
+
124
+ def display_table(title, rows)
125
+ table = Terminal::Table.new :title => title.colorize(:blue).bold,
126
+ :headings => ["Metric", "Data"].map { |i| i.colorize(:magenta).bold },
127
+ :rows => rows
128
+
84
129
  table.style = { :border_x => "=", :border_i => "x", :alignment => :center }
85
- puts table
86
130
 
87
- # # Display today's repository metrics in a table
88
- # today_rows = [
89
- # ['Today\'s Total Commits', fetcher.fetch_today_commits_count(user, repo_name)],
90
- # ['Today\'s Pull Requests', fetcher.fetch_today_pull_requests_count(user, repo_name)],
91
- # ['Today\'s Closed Pull Requests', fetcher.fetch_today_closed_pull_requests_count(user, repo_name)],
92
- # ['Today\'s Open Pull Requests', fetcher.fetch_today_open_pull_requests_count(user, repo_name)],
93
- # ['Today\'s Issues', fetcher.fetch_today_issues_count(user, repo_name)],
94
- # ['Today\'s Closed Issues', fetcher.fetch_today_closed_issues_count(user, repo_name)],
95
- # ['Today\'s Open Issues', fetcher.fetch_today_open_issues_count(user, repo_name)]
96
- # ]
97
-
98
- # today_table = Terminal::Table.new :title => "Today's Repository Metrics".colorize(:green).bold, :headings => ['Metric', 'Count'].map { |i| i.colorize(:magenta).bold }, :rows => today_rows
99
- # today_table.style = { :border_x => "=", :border_i => "x", :alignment => :center }
100
- # puts today_table
131
+ puts table
101
132
  end
102
-
103
-
104
-
105
- def method_missing(method, *_args, &_block)
133
+
134
+ def method_missing(method, *args, &_block)
106
135
  if method =~ /[-a-zA-Z0-9_.]+/
107
- metrics(method.to_s)
136
+ today_option = args.include?("--today")
137
+ metrics(method.to_s, today_option)
108
138
  else
109
139
  super
110
140
  end
@@ -1,10 +1,10 @@
1
- require_relative 'metric_fetcher'
2
- require 'octokit'
1
+ require_relative "metric_fetcher"
2
+ require "octokit"
3
3
 
4
4
  class GithubFetcher
5
5
  def initialize
6
6
  Octokit.configure do |config|
7
- config.access_token = ENV['GITHUB_TOKEN']
7
+ config.access_token = ENV["GITHUB_TOKEN"]
8
8
  end
9
9
  end
10
10
 
@@ -15,32 +15,51 @@ class GithubFetcher
15
15
  def fetch_repos
16
16
  Octokit.repositories.map do |repo|
17
17
  {
18
- 'name' => repo.name,
19
- 'issues' => repo.open_issues_count,
20
- 'stargazers' => repo.stargazers_count,
21
- 'forks' => repo.forks_count
18
+ "name" => repo.name,
19
+ "issues" => repo.open_issues_count,
20
+ "stargazers" => repo.stargazers_count,
21
+ "forks" => repo.forks_count,
22
22
  }
23
23
  end
24
24
  end
25
25
 
26
+ def fetch_today_repo_metrics(user, repo_name)
27
+ {
28
+ "name" => repo_name,
29
+ "forks_count" => fetch_today_forks_count(user, repo_name),
30
+ "open_issues_count" => fetch_today_open_issues_count(user, repo_name),
31
+ "commits_count" => fetch_today_commits_count(user, repo_name),
32
+ "pull_requests_count" => fetch_today_pull_requests_count(user, repo_name),
33
+ "closed_pull_requests_count" => fetch_today_closed_pull_requests_count(user, repo_name),
34
+ "open_pull_requests_count" => fetch_today_open_pull_requests_count(user, repo_name),
35
+ "issues_count" => fetch_today_issues_count(user, repo_name),
36
+ "closed_issues_count" => fetch_today_closed_issues_count(user, repo_name),
37
+ }
38
+ end
39
+
26
40
  def fetch_repo_metrics(user, repo_name)
27
- repo = Octokit.repository("#{user}/#{repo_name}")
41
+ begin
42
+ repo = Octokit.repository("#{user}/#{repo_name}")
43
+ rescue Octokit::NotFound
44
+ puts "The repository #{user}/#{repo_name} was not found. Please check the repository name and try again."
45
+ exit
46
+ end
28
47
  {
29
- 'name' => repo.name,
30
- 'description' => repo.description,
31
- 'default_branch' => repo.default_branch,
32
- 'last_updated_at' => repo.updated_at,
33
- 'watchers_count' => repo.watchers_count,
34
- 'forks_count' => repo.forks_count,
35
- 'open_issues_count' => repo.open_issues_count,
36
- 'commits_count' => Octokit.commits("#{user}/#{repo_name}").count,
37
- 'pull_requests_count' => Octokit.pull_requests("#{user}/#{repo_name}").count,
38
- 'closed_pull_requests_count' => Octokit.pull_requests("#{user}/#{repo_name}", state: 'closed').count,
39
- 'open_pull_requests_count' => Octokit.pull_requests("#{user}/#{repo_name}", state: 'open').count,
40
- 'issues_count' => Octokit.issues("#{user}/#{repo_name}").count,
41
- 'closed_issues_count' => Octokit.issues("#{user}/#{repo_name}", state: 'closed').count,
42
- 'stargazers_count' => repo.stargazers_count,
43
- 'contributors_count' => Octokit.contributors("#{user}/#{repo_name}").count
48
+ "name" => repo.name,
49
+ "description" => repo.description,
50
+ "default_branch" => repo.default_branch,
51
+ "last_updated_at" => repo.updated_at,
52
+ "watchers_count" => repo.watchers_count,
53
+ "forks_count" => repo.forks_count,
54
+ "open_issues_count" => repo.open_issues_count,
55
+ "commits_count" => Octokit.commits("#{user}/#{repo_name}").count,
56
+ "pull_requests_count" => Octokit.pull_requests("#{user}/#{repo_name}").count,
57
+ "closed_pull_requests_count" => Octokit.pull_requests("#{user}/#{repo_name}", state: "closed").count,
58
+ "open_pull_requests_count" => Octokit.pull_requests("#{user}/#{repo_name}", state: "open").count,
59
+ "issues_count" => Octokit.issues("#{user}/#{repo_name}").count,
60
+ "closed_issues_count" => Octokit.issues("#{user}/#{repo_name}", state: "closed").count,
61
+ "stargazers_count" => repo.stargazers_count,
62
+ "contributors_count" => Octokit.contributors("#{user}/#{repo_name}").count,
44
63
  }
45
64
  end
46
65
 
@@ -61,13 +80,13 @@ class GithubFetcher
61
80
  end
62
81
 
63
82
  def fetch_today_closed_pull_requests_count(user, repo_name)
64
- Octokit.pull_requests("#{user}/#{repo_name}", state: 'closed').count do |pr|
83
+ Octokit.pull_requests("#{user}/#{repo_name}", state: "closed").count do |pr|
65
84
  pr.closed_at.to_date == Date.today
66
85
  end
67
86
  end
68
87
 
69
88
  def fetch_today_open_pull_requests_count(user, repo_name)
70
- Octokit.pull_requests("#{user}/#{repo_name}", state: 'open').count do |pr|
89
+ Octokit.pull_requests("#{user}/#{repo_name}", state: "open").count do |pr|
71
90
  pr.created_at.to_date == Date.today
72
91
  end
73
92
  end
@@ -79,14 +98,20 @@ class GithubFetcher
79
98
  end
80
99
 
81
100
  def fetch_today_closed_issues_count(user, repo_name)
82
- Octokit.issues("#{user}/#{repo_name}", state: 'closed').count do |issue|
101
+ Octokit.issues("#{user}/#{repo_name}", state: "closed").count do |issue|
83
102
  issue.closed_at.to_date == Date.today
84
103
  end
85
104
  end
86
105
 
87
106
  def fetch_today_open_issues_count(user, repo_name)
88
- Octokit.issues("#{user}/#{repo_name}", state: 'open').count do |issue|
107
+ Octokit.issues("#{user}/#{repo_name}", state: "open").count do |issue|
89
108
  issue.created_at.to_date == Date.today
90
109
  end
91
110
  end
111
+
112
+ def fetch_today_forks_count(user, repo_name)
113
+ Octokit.forks("#{user}/#{repo_name}").count do |fork|
114
+ fork.created_at.to_date == Date.today
115
+ end
116
+ end
92
117
  end
@@ -1,4 +1,4 @@
1
- require_relative 'base_fetcher'
1
+ require_relative "base_fetcher"
2
2
 
3
3
  class MetricFetcher < BaseFetcher
4
4
  def fetch_today_commits_count(owner, repo_name)
@@ -43,6 +43,6 @@ class MetricFetcher < BaseFetcher
43
43
  response = execute_http_request(req)
44
44
  star_data = parse_response(response)
45
45
 
46
- star_data['stargazers_count']
46
+ star_data["stargazers_count"]
47
47
  end
48
48
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gitmarshal
4
- VERSION = "1.0.0"
4
+ VERSION = "1.1.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitmarshal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nagendra Dhanakeerthi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-09 00:00:00.000000000 Z
11
+ date: 2023-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json