nya_pr 0.4.0 → 0.5.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: 29ee2a7a39ef6c0643bf8fd4c29e75ace604a36112958a08d5a2ad21f7dd6d51
4
- data.tar.gz: 8390d9f7533c7c1d9abd9f2588548152d520d9e624c62ec841a9e57181b2a88c
3
+ metadata.gz: 733e769aa9751489e6a8e219de2804dc33d40a1cc7aef589bffd002c83e47f19
4
+ data.tar.gz: e9327003b3b327834904206c9b9fd402ef09ee5143afccc846dacad5899ce4e8
5
5
  SHA512:
6
- metadata.gz: 3b290bc4f56e97ab8770f044aed6dc7c90a2ac8125f7899e43b53e31a481fc58b6fcbe60308ffb8087c07746456412fc6d5add5bbffbb2fd1ff5a04660d8c05b
7
- data.tar.gz: a99c47b8e324b2f5b005b93fe1f7a657e07ce6e88bc1e1bd9566aa15e33009131129a375c52f7c22358f609b3029be6f4c1c2a9fa2c1c4913809b4657470dd36
6
+ metadata.gz: 9f27db9b27067f525f3b50b87c61f849c0cffbb71d2c7f2622dd2aba9bd56d1741559766b8eb3261a97b7d4f6192df082970daf6b0fe3f5103d91fd9b74b5e07
7
+ data.tar.gz: 7dc96cd1812762b1b437955536eb1725de85888d2a5a28bfe461cd262afa597237a540e339d9d93a2c5cce7e8495e10ab939cd72d924977c41258861cf38f2d4
data/README.md CHANGED
@@ -304,6 +304,7 @@ Logs are written to `stderr`, while actual pull request output goes to `stdout`.
304
304
  --skip-drafts Ignore draft pull requests
305
305
  --[no-]progress Show or hide progress bars
306
306
  --exclude-repos Repositories to exclude, in owner/name format
307
+ --save-pull-requests Save pull requests to CSV
307
308
  --log-level LEVEL Logging level
308
309
  -w, --workers Number of repository scan workers
309
310
  -v, --version Show NyaPr version
data/exe/nya-pr CHANGED
@@ -5,7 +5,7 @@ require 'nya_pr'
5
5
 
6
6
  begin
7
7
  NyaPr.run
8
- rescue OptionParser::ParseError, NyaPr::Error => e
8
+ rescue NyaPr::Error => e
9
9
  warn "nya-pr: #{e.message}"
10
10
  exit 1
11
11
  rescue Interrupt
@@ -49,12 +49,16 @@ module NyaPr
49
49
  type: :array,
50
50
  desc: 'Repositories to exclude, in owner/name format'
51
51
 
52
+ option :save_pull_requests,
53
+ type: :boolean,
54
+ desc: 'Save pull requests to CSV'
55
+
52
56
  option :progress,
53
57
  type: :boolean,
54
58
  desc: 'Show progress bars'
55
59
 
56
60
  option :log_level,
57
- values: Config::Global::LOG_LEVELS.keys,
61
+ values: Config::Builder::LOG_LEVELS.keys,
58
62
  desc: 'Log level'
59
63
 
60
64
  option :workers,
@@ -74,12 +78,14 @@ module NyaPr
74
78
 
75
79
  file_options = Config::Loader.load(config)
76
80
 
77
- Runner.new(
78
- Config::Global.from_options(
79
- options,
80
- file_options: file_options
81
- )
82
- ).run
81
+ app_config = Config::Builder.build(
82
+ options,
83
+ file_options: file_options
84
+ )
85
+
86
+ NyaPr.logger.level = app_config.log_level
87
+
88
+ RunnerFactory.build(app_config).run
83
89
  end
84
90
  end
85
91
  end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NyaPr
4
+ module Config
5
+ class Builder
6
+ LOG_LEVELS = {
7
+ 'debug' => Logger::DEBUG,
8
+ 'info' => Logger::INFO,
9
+ 'warn' => Logger::WARN,
10
+ 'error' => Logger::ERROR,
11
+ 'fatal' => Logger::FATAL
12
+ }.freeze
13
+
14
+ BOOLEAN_KEYS = %i[
15
+ refresh
16
+ skip_archived
17
+ skip_drafts
18
+ progress
19
+ save_pull_requests
20
+ ].freeze
21
+
22
+ def self.build(options, file_options: {})
23
+ new(options, file_options).build
24
+ end
25
+
26
+ def initialize(options, file_options)
27
+ @options = options
28
+ @file_options = file_options
29
+ end
30
+
31
+ def build
32
+ validate_keys!
33
+
34
+ Global.new(
35
+ **normalize(
36
+ Defaults::OPTIONS.
37
+ merge(file_options).
38
+ merge(options.compact)
39
+ )
40
+ )
41
+ end
42
+
43
+ private
44
+
45
+ attr_reader :options, :file_options
46
+
47
+ def normalize(attributes)
48
+ attributes.merge(
49
+ username: normalize_username(attributes[:username]),
50
+ owners: normalize_list(attributes[:owners]),
51
+ exclude_repositories: normalize_repositories(
52
+ attributes[:exclude_repositories]
53
+ ),
54
+ limit: normalize_positive_integer(attributes[:limit], :limit),
55
+ workers: normalize_positive_integer(attributes[:workers], :workers),
56
+ log_level: normalize_log_level(attributes[:log_level]),
57
+ **normalize_booleans(attributes)
58
+ )
59
+ end
60
+
61
+ def normalize_username(value)
62
+ username = value.to_s.strip
63
+
64
+ return username unless username.empty?
65
+
66
+ raise NyaPr::Error, 'GitHub username is required'
67
+ end
68
+
69
+ def normalize_list(values)
70
+ Array(values).
71
+ flat_map { |value| value.to_s.split(',') }.
72
+ map(&:strip).
73
+ reject(&:empty?)
74
+ end
75
+
76
+ def normalize_repositories(values)
77
+ normalize_list(values).
78
+ map(&:downcase).
79
+ uniq
80
+ end
81
+
82
+ def normalize_booleans(attributes)
83
+ BOOLEAN_KEYS.to_h do |key|
84
+ [key, normalize_boolean(attributes[key], key)]
85
+ end
86
+ end
87
+
88
+ def normalize_positive_integer(value, name)
89
+ number = Integer(value)
90
+
91
+ return number if number.positive?
92
+
93
+ raise NyaPr::Error, "#{name} must be greater than 0"
94
+ rescue ArgumentError, TypeError
95
+ raise NyaPr::Error, "#{name} must be a positive integer"
96
+ end
97
+
98
+ def normalize_boolean(value, name)
99
+ return value if [true, false].include?(value)
100
+
101
+ raise NyaPr::Error, "#{name} must be true or false"
102
+ end
103
+
104
+ def normalize_log_level(value)
105
+ LOG_LEVELS.fetch(value.to_s) do
106
+ raise NyaPr::Error, "Invalid log level: #{value}"
107
+ end
108
+ end
109
+
110
+ def validate_keys!
111
+ unknown = file_options.keys - Global.members
112
+
113
+ return if unknown.empty?
114
+
115
+ raise NyaPr::Error,
116
+ "Unknown config option(s): #{unknown.join(', ')}"
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NyaPr
4
+ module Config
5
+ module Defaults
6
+ LIMIT = 100
7
+ WORKERS = 10
8
+
9
+ OPTIONS = {
10
+ owners: [],
11
+ token: nil,
12
+ repositories_csv: nil,
13
+ pull_requests_dir: nil,
14
+ limit: LIMIT,
15
+ refresh: false,
16
+ skip_archived: false,
17
+ skip_drafts: false,
18
+ exclude_repositories: [],
19
+ save_pull_requests: true,
20
+ progress: true,
21
+ log_level: 'info',
22
+ workers: WORKERS
23
+ }.freeze
24
+ end
25
+ end
26
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module NyaPr
4
4
  module Config
5
- class Global < Data.define(
5
+ Global = Data.define(
6
6
  :username,
7
7
  :owners,
8
8
  :token,
@@ -13,137 +13,10 @@ module NyaPr
13
13
  :skip_archived,
14
14
  :skip_drafts,
15
15
  :exclude_repositories,
16
+ :save_pull_requests,
16
17
  :progress,
17
18
  :log_level,
18
19
  :workers
19
20
  )
20
- LOG_LEVELS = {
21
- 'debug' => Logger::DEBUG,
22
- 'info' => Logger::INFO,
23
- 'warn' => Logger::WARN,
24
- 'error' => Logger::ERROR,
25
- 'fatal' => Logger::FATAL
26
- }.freeze
27
-
28
- DEFAULTS = {
29
- owners: [],
30
- token: nil,
31
- repositories_csv: nil,
32
- pull_requests_dir: nil,
33
- limit: PullRequest::Config::DEFAULT_LIMIT,
34
- refresh: false,
35
- skip_archived: false,
36
- skip_drafts: false,
37
- progress: true,
38
- log_level: 'info',
39
- workers: Repository::Config::DEFAULT_WORKERS,
40
- exclude_repositories: []
41
- }.freeze
42
-
43
- BOOLEAN_KEYS = %i[
44
- refresh
45
- skip_archived
46
- skip_drafts
47
- progress
48
- ].freeze
49
-
50
- class << self
51
- def from_options(options, file_options: {})
52
- validate_keys!(file_options)
53
-
54
- attributes = DEFAULTS.
55
- merge(file_options).
56
- merge(options.compact)
57
-
58
- build(attributes)
59
- end
60
-
61
- private
62
-
63
- def build(attributes)
64
- normalized = attributes.merge(
65
- username: normalize_username(attributes[:username]),
66
- owners: normalize_owners(attributes[:owners]),
67
- limit: normalize_positive_integer(attributes[:limit], :limit),
68
- workers: normalize_positive_integer(attributes[:workers], :workers),
69
- log_level: normalize_log_level(attributes[:log_level]),
70
- exclude_repositories: normalize_repositories(
71
- attributes[:exclude_repositories]
72
- ),
73
- **normalize_booleans(attributes)
74
- )
75
-
76
- new(**normalized)
77
- end
78
-
79
- def normalize_username(value)
80
- username = value.to_s.strip
81
-
82
- validate_username!(username)
83
-
84
- username
85
- end
86
-
87
- def normalize_repositories(repositories)
88
- Array(repositories).
89
- flat_map { |repository| repository.to_s.split(',') }.
90
- map(&:strip).
91
- reject(&:empty?).
92
- map(&:downcase).
93
- uniq
94
- end
95
-
96
- def normalize_booleans(attributes)
97
- BOOLEAN_KEYS.to_h do |key|
98
- [key, normalize_boolean(attributes[key], key)]
99
- end
100
- end
101
-
102
- def validate_keys!(options)
103
- unknown = options.keys - members
104
-
105
- return if unknown.empty?
106
-
107
- raise NyaPr::Error,
108
- "Unknown config option(s): #{unknown.join(', ')}"
109
- end
110
-
111
- def normalize_owners(owners)
112
- Array(owners).
113
- flat_map { |owner| owner.to_s.split(',') }.
114
- map(&:strip).
115
- reject(&:empty?)
116
- end
117
-
118
- def normalize_positive_integer(value, name)
119
- number = Integer(value)
120
-
121
- return number if number.positive?
122
-
123
- raise NyaPr::Error, "#{name} must be greater than 0"
124
- rescue ArgumentError, TypeError
125
- raise NyaPr::Error, "#{name} must be a positive integer"
126
- end
127
-
128
- def normalize_boolean(value, name)
129
- return value if [true, false].include?(value)
130
-
131
- raise NyaPr::Error, "#{name} must be true or false"
132
- end
133
-
134
- def normalize_log_level(value)
135
- LOG_LEVELS.fetch(value.to_s) do
136
- raise NyaPr::Error,
137
- "Invalid log level: #{value}"
138
- end
139
- end
140
-
141
- def validate_username!(username)
142
- return unless username.empty?
143
-
144
- raise NyaPr::Error, 'GitHub username is required'
145
- end
146
- end
147
- end
148
21
  end
149
22
  end
@@ -2,14 +2,12 @@
2
2
 
3
3
  module NyaPr
4
4
  module PullRequest
5
- class Config < Data.define(
5
+ Config = Data.define(
6
6
  :limit,
7
7
  :skip_drafts,
8
8
  :progress_enabled,
9
9
  :pull_requests_dir
10
- )
11
- DEFAULT_LIMIT = 100
12
-
10
+ ) do
13
11
  def self.from_app(config)
14
12
  new(
15
13
  limit: config.limit,
@@ -8,25 +8,27 @@ module NyaPr
8
8
  MAX_PER_PAGE = 100
9
9
 
10
10
  attr_reader :client,
11
- :repositories,
12
11
  :config,
13
12
  :filter
14
13
 
15
- def initialize(client, repositories, config, filter: nil)
14
+ def initialize(client, config, filter: nil)
16
15
  @client = client
17
- @repositories = repositories
18
16
  @config = config
19
17
  @filter = filter || Filter.new(config)
20
18
  end
21
19
 
22
- def find
20
+ def find(repositories)
23
21
  NyaPr.logger.info(
24
22
  "Searching for up to #{config.limit} open pull requests " \
25
23
  "in #{repositories.size} repositories"
26
24
  )
27
25
 
28
- progress_bar = build_progress
29
- pull_requests = collect_pull_requests(progress_bar)
26
+ progress_bar = build_progress(repositories.size)
27
+
28
+ pull_requests = collect_pull_requests(
29
+ repositories,
30
+ progress_bar
31
+ )
30
32
 
31
33
  progress_bar.finish
32
34
 
@@ -39,7 +41,7 @@ module NyaPr
39
41
 
40
42
  private
41
43
 
42
- def collect_pull_requests(progress_bar)
44
+ def collect_pull_requests(repositories, progress_bar)
43
45
  pull_requests = []
44
46
 
45
47
  repositories.each do |repository|
@@ -134,10 +136,10 @@ module NyaPr
134
136
  )
135
137
  end
136
138
 
137
- def build_progress
139
+ def build_progress(total)
138
140
  Progress.new(
139
141
  '🐾 Checking pull requests',
140
- total: repositories.size,
142
+ total: total,
141
143
  enabled: config.progress_enabled && $stderr.tty?
142
144
  )
143
145
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module NyaPr
4
4
  module Repository
5
- class Config < Data.define(
5
+ Config = Data.define(
6
6
  :username,
7
7
  :owners,
8
8
  :refresh,
@@ -11,9 +11,7 @@ module NyaPr
11
11
  :workers,
12
12
  :repositories_csv,
13
13
  :exclude_repositories
14
- )
15
- DEFAULT_WORKERS = 10
16
-
14
+ ) do
17
15
  def self.from_app(config)
18
16
  new(
19
17
  username: config.username,
data/lib/nya_pr/runner.rb CHANGED
@@ -1,20 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dotenv'
4
-
5
3
  module NyaPr
6
4
  class Runner
7
- attr_reader :config
8
-
9
- def initialize(config)
10
- @config = config
5
+ attr_reader :repository_collector,
6
+ :pull_request_finder,
7
+ :pull_request_printer,
8
+ :pull_request_store
9
+
10
+ def initialize(
11
+ repository_collector:,
12
+ pull_request_finder:,
13
+ pull_request_printer:,
14
+ pull_request_store:
15
+ )
16
+ @repository_collector = repository_collector
17
+ @pull_request_finder = pull_request_finder
18
+ @pull_request_printer = pull_request_printer
19
+ @pull_request_store = pull_request_store
11
20
  end
12
21
 
13
22
  def run
14
- Dotenv.load
15
- configure_logger
16
-
17
- pull_requests = find_pull_requests
23
+ repositories = repository_collector.collect
24
+ pull_requests = pull_request_finder.find(repositories)
18
25
 
19
26
  pull_request_printer.print(pull_requests)
20
27
  save_pull_requests(pull_requests)
@@ -22,85 +29,14 @@ module NyaPr
22
29
 
23
30
  private
24
31
 
25
- def configure_logger
26
- NyaPr.logger.level = config.log_level
27
- end
28
-
29
- def target_repositories
30
- repository_collector.collect
31
- end
32
-
33
- def repository_config
34
- @repository_config ||= Repository::Config.from_app(config)
35
- end
36
-
37
- def pull_request_config
38
- @pull_request_config ||= PullRequest::Config.from_app(config)
39
- end
40
-
41
- def repository_paths
42
- @repository_paths ||= Repository::Paths.new(
43
- repository_config
44
- )
45
- end
46
-
47
- def pull_request_paths
48
- @pull_request_paths ||= PullRequest::Paths.new(
49
- pull_request_config
50
- )
51
- end
52
-
53
- def repository_store
54
- @repository_store ||= Repository::CsvStore.new(
55
- repository_paths.csv
56
- )
57
- end
58
-
59
- def pull_request_store
60
- @pull_request_store ||= PullRequest::CsvStore.new(
61
- pull_request_paths.csv
62
- )
63
- end
64
-
65
- def repository_collector
66
- @repository_collector ||= Repository::Collector.new(
67
- client,
68
- repository_store,
69
- repository_config
70
- )
71
- end
72
-
73
- def find_pull_requests
74
- PullRequest::Finder.
75
- new(
76
- client,
77
- target_repositories,
78
- pull_request_config
79
- ).
80
- find
81
- end
82
-
83
32
  def save_pull_requests(pull_requests)
33
+ return unless pull_request_store
34
+
84
35
  pull_request_store.write(pull_requests)
85
36
 
86
37
  NyaPr.logger.info(
87
38
  "Saved #{pull_requests.size} pull requests to #{pull_request_store.path}"
88
39
  )
89
40
  end
90
-
91
- def pull_request_printer
92
- @pull_request_printer ||= PullRequest::Printer.new
93
- end
94
-
95
- def client
96
- @client ||= Github::Client.new(token)
97
- end
98
-
99
- def token
100
- config.token || ENV.fetch('GITHUB_TOKEN') do
101
- raise NyaPr::Error,
102
- 'GitHub token is required (--token or GITHUB_TOKEN)'
103
- end
104
- end
105
41
  end
106
42
  end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NyaPr
4
+ class RunnerFactory
5
+ def self.build(config)
6
+ new(config).build
7
+ end
8
+
9
+ def initialize(config)
10
+ @config = config
11
+ end
12
+
13
+ def build
14
+ Runner.new(
15
+ repository_collector: repository_collector,
16
+ pull_request_finder: pull_request_finder,
17
+ pull_request_printer: PullRequest::Printer.new,
18
+ pull_request_store: pull_request_store
19
+ )
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :config
25
+
26
+ def repository_config
27
+ @repository_config ||= Repository::Config.from_app(config)
28
+ end
29
+
30
+ def pull_request_config
31
+ @pull_request_config ||= PullRequest::Config.from_app(config)
32
+ end
33
+
34
+ def repository_store
35
+ @repository_store ||= Repository::CsvStore.new(
36
+ Repository::Paths.new(repository_config).csv
37
+ )
38
+ end
39
+
40
+ def repository_collector
41
+ @repository_collector ||= Repository::Collector.new(
42
+ client,
43
+ repository_store,
44
+ repository_config
45
+ )
46
+ end
47
+
48
+ def pull_request_finder
49
+ @pull_request_finder ||= PullRequest::Finder.new(
50
+ client,
51
+ pull_request_config
52
+ )
53
+ end
54
+
55
+ def pull_request_store
56
+ return unless config.save_pull_requests
57
+
58
+ @pull_request_store ||= PullRequest::CsvStore.new(
59
+ PullRequest::Paths.new(pull_request_config).csv
60
+ )
61
+ end
62
+
63
+ def client
64
+ @client ||= Github::Client.new(token)
65
+ end
66
+
67
+ def token
68
+ config.token || ENV.fetch('GITHUB_TOKEN') do
69
+ raise NyaPr::Error,
70
+ 'GitHub token is required (--token or GITHUB_TOKEN)'
71
+ end
72
+ end
73
+ end
74
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NyaPr
4
- VERSION = '0.4.0'
4
+ VERSION = '0.5.0'
5
5
  end
data/lib/nya_pr.rb CHANGED
@@ -4,6 +4,7 @@ require 'zeitwerk'
4
4
  require 'logger'
5
5
  require 'csv'
6
6
  require 'dry/cli'
7
+ require 'dotenv'
7
8
 
8
9
  loader = Zeitwerk::Loader.for_gem
9
10
  loader.setup
@@ -11,6 +12,8 @@ loader.setup
11
12
  module NyaPr
12
13
  class << self
13
14
  def run(argv = ARGV)
15
+ Dotenv.load
16
+
14
17
  Dry::CLI.new(Cli::Command).call(arguments: argv)
15
18
  end
16
19
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nya_pr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elijah S. Krukowski
@@ -122,6 +122,8 @@ files:
122
122
  - exe/nya-pr
123
123
  - lib/nya_pr.rb
124
124
  - lib/nya_pr/cli/command.rb
125
+ - lib/nya_pr/config/builder.rb
126
+ - lib/nya_pr/config/defaults.rb
125
127
  - lib/nya_pr/config/global.rb
126
128
  - lib/nya_pr/config/loader.rb
127
129
  - lib/nya_pr/error.rb
@@ -142,6 +144,7 @@ files:
142
144
  - lib/nya_pr/repository/finder.rb
143
145
  - lib/nya_pr/repository/paths.rb
144
146
  - lib/nya_pr/runner.rb
147
+ - lib/nya_pr/runner_factory.rb
145
148
  - lib/nya_pr/version.rb
146
149
  homepage: https://github.com/bodrovis/nya_pr
147
150
  licenses: