newsman 0.1.14 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -1
- data/lib/newsman/assistant.rb +83 -96
- data/lib/newsman/github.rb +80 -0
- data/lib/newsman/html_output.rb +42 -17
- data/lib/newsman/issues.rb +92 -15
- data/lib/newsman/pull_request.rb +32 -1
- data/lib/newsman/report.rb +49 -13
- data/lib/newsman/stdout_output.rb +22 -0
- data/lib/newsman/txt_output.rb +21 -0
- data/lib/newsman.rb +64 -100
- data/test/test_assistant.rb +8 -3
- data/test/test_htmlout.rb +1 -1
- data/test/test_issue.rb +62 -0
- data/test/test_pdd_issue.rb +35 -5
- data/test/test_pull_request.rb +39 -0
- data/test/test_report.rb +32 -24
- data/test/test_week_before.rb +1 -1
- metadata +21 -4
data/lib/newsman/report.rb
CHANGED
@@ -1,8 +1,29 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in all
|
14
|
+
# copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
|
24
|
+
# This class builds entire report based on issues and pull requests passed.
|
4
25
|
class Report
|
5
|
-
def initialize(user, position, title, additional: ReportItems.new([],[]))
|
26
|
+
def initialize(user, position, title, additional: ReportItems.new([], []))
|
6
27
|
@user = user
|
7
28
|
@position = position
|
8
29
|
@title = title
|
@@ -10,14 +31,30 @@ class Report
|
|
10
31
|
end
|
11
32
|
|
12
33
|
def build(achievements, plans, risks, date)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
34
|
+
<<~TEMPLATE
|
35
|
+
From: #{@user}
|
36
|
+
Subject: #{week_of_a_year(@title, date)}
|
37
|
+
|
38
|
+
Hi all,
|
39
|
+
|
40
|
+
Last week achievements:
|
41
|
+
#{achievements}
|
42
|
+
|
43
|
+
Next week plans:
|
44
|
+
#{plans}
|
45
|
+
|
46
|
+
Risks:
|
47
|
+
#{risks}
|
48
|
+
|
49
|
+
Best regards,
|
50
|
+
#{@user}
|
51
|
+
#{@position}
|
52
|
+
#{date}
|
53
|
+
TEMPLATE
|
54
|
+
end
|
55
|
+
|
56
|
+
def append_additional(report)
|
57
|
+
"#{report}\n#{"------\n#{@additional}" unless @additional.empty?}"
|
21
58
|
end
|
22
59
|
end
|
23
60
|
|
@@ -26,9 +63,8 @@ def week_of_a_year(project, today)
|
|
26
63
|
"WEEK #{number} #{project}"
|
27
64
|
end
|
28
65
|
|
29
|
-
|
66
|
+
# Report items inner class.
|
30
67
|
class ReportItems
|
31
|
-
|
32
68
|
def initialize(prs, issues)
|
33
69
|
@prs = prs || []
|
34
70
|
@issues = issues || []
|
@@ -41,7 +77,7 @@ class ReportItems
|
|
41
77
|
|
42
78
|
def to_s
|
43
79
|
prs_list = @prs.map(&:detailed_title).map { |obj| " - #{obj}\n" }.join
|
44
|
-
issues_list = @issues.map(&:detailed_title).map { |obj| " - #{obj}\n" }.join
|
45
|
-
|
80
|
+
issues_list = @issues.map(&:detailed_title).map { |obj| " - #{obj}\n" }.join
|
81
|
+
"Closed Pull Requests:\n#{prs_list}\nOpen Issues:\n#{issues_list}"
|
46
82
|
end
|
47
83
|
end
|
@@ -1,5 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
#
|
4
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in all
|
14
|
+
# copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
|
24
|
+
# This class prints report to a console.
|
3
25
|
class Stdout
|
4
26
|
def print(report)
|
5
27
|
puts 'Print a report to stdout'
|
data/lib/newsman/txt_output.rb
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
# This class knows how to print a report to a separate file.
|
3
24
|
class Txtout
|
4
25
|
def initialize(root = '.')
|
5
26
|
@root = root
|
data/lib/newsman.rb
CHANGED
@@ -1,6 +1,27 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
#
|
5
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
|
4
25
|
require 'octokit'
|
5
26
|
require 'openai'
|
6
27
|
require 'dotenv'
|
@@ -12,7 +33,9 @@ require_relative 'newsman/txt_output'
|
|
12
33
|
require_relative 'newsman/html_output'
|
13
34
|
require_relative 'newsman/report'
|
14
35
|
require_relative 'newsman/assistant'
|
36
|
+
require_relative 'newsman/github'
|
15
37
|
|
38
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
16
39
|
def generate
|
17
40
|
# Load all options required
|
18
41
|
# Pay attention that some of them have default values.
|
@@ -26,7 +49,9 @@ def generate
|
|
26
49
|
options[:username] = u
|
27
50
|
end
|
28
51
|
opts.on('-r', '--repository REPOSITORIES',
|
29
|
-
|
52
|
+
'Specify which repositories to include in a report.'\
|
53
|
+
'You can specify several repositories using a comma separator,'\
|
54
|
+
"for example: '-r objectionary/jeo-maven-plugin,objectionary/opeo-maven-plugin'") do |r|
|
30
55
|
options[:repositories] = r
|
31
56
|
end
|
32
57
|
opts.on('-p', '--position POSITION',
|
@@ -34,7 +59,8 @@ def generate
|
|
34
59
|
options[:position] = p
|
35
60
|
end
|
36
61
|
opts.on('-o', '--output OUTPUT',
|
37
|
-
|
62
|
+
'Output type. Newsman prints a report to a stdout by default.'\
|
63
|
+
"You can choose another options like '-o html', '-o txt' or even '-o html'") do |o|
|
38
64
|
options[:output] = o
|
39
65
|
end
|
40
66
|
opts.on('-t', '--title TITLE', 'Project Title. Empty by default') do |t|
|
@@ -45,118 +71,61 @@ def generate
|
|
45
71
|
def options.require_option(key, message)
|
46
72
|
raise OptionParser::MissingArgument, message if self[key].nil?
|
47
73
|
end
|
48
|
-
|
49
74
|
# Check for required options
|
50
75
|
options.require_option(:name, 'Reporter name is required. Please specify using -n or --name.')
|
51
76
|
options.require_option(:username, 'GitHub username is required. Please specify using -u or --username.')
|
52
77
|
options.require_option(:repositories,
|
53
|
-
'GitHub repository is required.
|
78
|
+
'GitHub repository is required.'\
|
79
|
+
' Please specify one or several repositories using -r or --repositories.')
|
54
80
|
options[:position] ||= 'Software Developer'
|
55
81
|
options[:output] ||= 'stdout'
|
56
82
|
options[:title] ||= ''
|
57
83
|
all_params = options.map { |key, value| "#{key}: #{value}" }.join(', ')
|
58
84
|
puts "Parsed parameters: #{all_params}"
|
59
|
-
|
60
|
-
#
|
61
|
-
Dotenv.load
|
62
|
-
Dotenv.require_keys('GITHUB_TOKEN', 'OPENAI_TOKEN')
|
63
|
-
|
64
|
-
# Init all required parameters
|
65
|
-
# Reporter Info
|
85
|
+
load_environment_variables
|
86
|
+
# Init all required parameters Reporter Info
|
66
87
|
reporter = options[:name]
|
67
88
|
reporter_position = options[:position]
|
68
89
|
# GitHub
|
69
90
|
github_username = options[:username]
|
70
91
|
github_repositories = options[:repositories].split(',').map { |repo| "repo:#{repo}" }.join(' ')
|
71
|
-
|
72
92
|
# Your GitHub personal access token
|
73
93
|
# Make sure it has the 'repo'
|
74
94
|
github_token = ENV['GITHUB_TOKEN']
|
75
95
|
# Your OpenAI personal access token
|
76
96
|
openai_token = ENV['OPENAI_TOKEN']
|
77
97
|
# Create a GitHub client instance with your access token
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
one_month_ago = Date.today.prev_month.strftime('%Y-%m-%d')
|
82
|
-
# Display pull request
|
83
|
-
query = "is:pr author:#{github_username} created:>=#{one_week_ago} #{github_repositories}"
|
84
|
-
issues_query = "is:issue is:open author:#{github_username} author:0pdd created:>=#{one_month_ago} #{github_repositories}"
|
85
|
-
puts "Searching pull requests for #{github_username}."
|
86
|
-
puts "Newsman uses the following request to GitHub to gather the required information about user activity: '#{query}'"
|
87
|
-
prs = []
|
88
|
-
pull_requests = client.search_issues(query)
|
89
|
-
pull_requests.items.each do |pr|
|
90
|
-
title = pr.title.to_s
|
91
|
-
description = pr.body.to_s
|
92
|
-
repository = pr.repository_url.split('/').last
|
93
|
-
puts "Found PR in #{repository}: #{title}"
|
94
|
-
# Create a new PullRequest object and add it to the list
|
95
|
-
pr = PullRequest.new(repository, title, description, url: pr.html_url)
|
96
|
-
prs << pr
|
97
|
-
end
|
98
|
-
raw_prs = prs
|
99
|
-
prs = prs.map(&:to_s).join("\n\n\n")
|
100
|
-
grouped_prs = raw_prs.group_by { |pr| pr.repository }
|
101
|
-
|
102
|
-
puts "Searching issues using the following query: '#{issues_query}'"
|
103
|
-
issues = []
|
104
|
-
client.search_issues(issues_query).items.each do |issue|
|
105
|
-
title = issue.title.to_s
|
106
|
-
body = issue.body.to_s
|
107
|
-
repository = issue.repository_url.split('/').last
|
108
|
-
number = issue.number.to_s
|
109
|
-
puts "Found issue in #{repository}:[##{number}] #{title}"
|
110
|
-
issues << if issue.user.login == '0pdd'
|
111
|
-
PddIssue.new(title, body, repository, number, url: issue.html_url)
|
112
|
-
else
|
113
|
-
Issue.new(title, body, repository, number, url: issue.html_url)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
raw_issues = issues
|
117
|
-
issues = issues.map(&:to_s).join("\n\n\n")
|
118
|
-
grouped_issues = raw_issues.group_by { |iss| iss.repo }
|
119
|
-
|
98
|
+
github = Github.new(github_token)
|
99
|
+
prs = github.pull_requests(github_username, github_repositories)
|
100
|
+
issues = github.issues(github_username, github_repositories)
|
120
101
|
puts "\nNow lets test some aggregation using OpenAI\n\n"
|
121
|
-
openai_client = OpenAI::Client.new(access_token: openai_token)
|
122
|
-
|
123
102
|
assistant = Assistant.new(openai_token)
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
risks_full_answer = assistant.old_risks(prs)
|
130
|
-
else
|
131
|
-
puts "Assistant builds a report using a new approach, using groupping"
|
132
|
-
# Build previous results
|
133
|
-
answer = ""
|
134
|
-
grouped_prs.each do |repository, rprs|
|
135
|
-
puts "Building a results report for the repository: #{repository}"
|
136
|
-
answer = answer + assistant.prev_results(rprs.map(&:to_s).join("\n\n\n"))
|
137
|
-
end
|
138
|
-
# Build next plans
|
139
|
-
issues_full_answer = ""
|
140
|
-
grouped_issues.each do |repository, rissues|
|
141
|
-
puts "Building a future plans report for the repository: #{repository}"
|
142
|
-
issues_full_answer = issues_full_answer + assistant.next_plans(rissues.map(&:to_s).join("\n\n\n"))
|
143
|
-
end
|
144
|
-
# Find risks
|
145
|
-
risks_full_answer = assistant.risks(prs)
|
103
|
+
# Build previous results
|
104
|
+
answer = ''
|
105
|
+
prs.group_by(&:repository).each do |repository, rprs|
|
106
|
+
puts "Building a results report for the repository: #{repository}"
|
107
|
+
answer = "#{answer}\n#{assistant.prev_results(join(rprs))}"
|
146
108
|
end
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
109
|
+
# Build next plans
|
110
|
+
issues_full_answer = ''
|
111
|
+
issues.group_by(&:repo).each do |repository, rissues|
|
112
|
+
puts "Building a future plans report for the repository: #{repository}"
|
113
|
+
issues_full_answer = "#{issues_full_answer}\n#{assistant.next_plans(join(rissues))}"
|
114
|
+
end
|
115
|
+
# Build report
|
116
|
+
report = Report.new(
|
117
|
+
reporter,
|
118
|
+
reporter_position,
|
151
119
|
options[:title],
|
152
|
-
additional: ReportItems.new(
|
153
|
-
).build(
|
154
|
-
answer,
|
155
|
-
issues_full_answer,
|
156
|
-
risks_full_answer,
|
157
|
-
Date.today
|
120
|
+
additional: ReportItems.new(prs, issues)
|
158
121
|
)
|
159
|
-
|
122
|
+
full_answer = assistant.format(report.build(
|
123
|
+
answer,
|
124
|
+
issues_full_answer,
|
125
|
+
assistant.risks(join(prs)),
|
126
|
+
Date.today
|
127
|
+
))
|
128
|
+
full_answer = report.append_additional(full_answer)
|
160
129
|
output_mode = options[:output]
|
161
130
|
puts "Output mode is '#{output_mode}'"
|
162
131
|
if output_mode.eql? 'txt'
|
@@ -173,20 +142,15 @@ def generate
|
|
173
142
|
output.print(full_answer)
|
174
143
|
end
|
175
144
|
end
|
145
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
176
146
|
|
177
|
-
def
|
178
|
-
|
179
|
-
|
180
|
-
# Subtract 7 days to get the date one week ago
|
181
|
-
one_week_ago = today - 7
|
182
|
-
# Format the date as "YYYY-MM-DD"
|
183
|
-
one_week_ago.strftime('%Y-%m-%d')
|
184
|
-
# Return the formatted date
|
147
|
+
def load_environment_variables
|
148
|
+
Dotenv.load
|
149
|
+
Dotenv.require_keys('GITHUB_TOKEN', 'OPENAI_TOKEN')
|
185
150
|
end
|
186
151
|
|
187
|
-
def
|
188
|
-
|
189
|
-
"WEEK #{number} #{project}"
|
152
|
+
def join(items)
|
153
|
+
"[#{items.map(&:to_json).join(',')}]"
|
190
154
|
end
|
191
155
|
|
192
156
|
# Execute the function only if this script is run directly like `./newsman.rb`
|
data/test/test_assistant.rb
CHANGED
@@ -26,8 +26,13 @@ require_relative '../lib/newsman/assistant'
|
|
26
26
|
|
27
27
|
class TestAssistant < Minitest::Test
|
28
28
|
def test_creates_default_assistant
|
29
|
-
assistant = Assistant
|
30
|
-
|
29
|
+
assistant = Assistant.new('test-token')
|
30
|
+
expected = <<~EXPECTED
|
31
|
+
I'm an assistant that can work with OpenAI client.
|
32
|
+
Please, use me, if you need any help.
|
33
|
+
I'm using gpt-3.5-turbo, with 0.3 temperature.
|
34
|
+
EXPECTED
|
35
|
+
assert_equal expected,
|
36
|
+
assistant.say_hello
|
31
37
|
end
|
32
38
|
end
|
33
|
-
|
data/test/test_htmlout.rb
CHANGED
data/test/test_issue.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in all
|
14
|
+
# copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
|
24
|
+
require 'minitest/autorun'
|
25
|
+
require_relative '../lib/newsman/issues'
|
26
|
+
|
27
|
+
class TestIssue < Minitest::Test
|
28
|
+
def test_converts_issue_to_json
|
29
|
+
issue = Issue.new(
|
30
|
+
'AnnotationsApplication.java:32-35: Check default values...',
|
31
|
+
'TEST_BODY',
|
32
|
+
'jeo-maven-plugin',
|
33
|
+
531
|
34
|
+
)
|
35
|
+
expected = <<~JSON.chomp
|
36
|
+
{"number":531,"title":"AnnotationsApplication.java:32-35: Check default values...","description":"TEST_BODY","repository":"jeo-maven-plugin","url":"undefined"}
|
37
|
+
JSON
|
38
|
+
assert_equal expected, issue.to_json
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_important_issue
|
42
|
+
issue = Issue.new(
|
43
|
+
'Important Issue Title',
|
44
|
+
'Important Issue Body',
|
45
|
+
'jeo-maven-plugin',
|
46
|
+
531,
|
47
|
+
labels: ['soon']
|
48
|
+
)
|
49
|
+
assert issue.important?
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_unimportant_issue
|
53
|
+
issue = Issue.new(
|
54
|
+
'Unimportant Issue Title',
|
55
|
+
'Unimportant Issue Body',
|
56
|
+
'jeo-maven-plugin',
|
57
|
+
531,
|
58
|
+
labels: ['not-soon']
|
59
|
+
)
|
60
|
+
assert !issue.important?
|
61
|
+
end
|
62
|
+
end
|
data/test/test_pdd_issue.rb
CHANGED
@@ -25,7 +25,7 @@ require 'minitest/autorun'
|
|
25
25
|
require_relative '../lib/newsman/issues'
|
26
26
|
|
27
27
|
class TestPddIssue < Minitest::Test
|
28
|
-
TEST_BODY =
|
28
|
+
TEST_BODY = <<~BODY
|
29
29
|
The puzzle `531-462261de` from #531 has to be resolved:
|
30
30
|
|
31
31
|
https://github.com/objectionary/jeo-maven-plugin/blob/5a42b2c9f7e0ff01cbb2c4626e1dc5dc3f8aa7b8/src/it/annotations/src/main/java/org/eolang/jeo/annotations/AnnotationsApplication.java#L32-L35
|
@@ -34,11 +34,18 @@ class TestPddIssue < Minitest::Test
|
|
34
34
|
|
35
35
|
Estimate: 90 minutes, role: DEV.
|
36
36
|
|
37
|
-
If you have any technical questions, don't ask me, submit new tickets instead.
|
38
|
-
|
37
|
+
If you have any technical questions, don't ask me, submit new tickets instead.
|
38
|
+
The task will be "done" when the problem is fixed and the text of the puzzle is _removed_ from the source code.
|
39
|
+
Here is more about [PDD](http://www.yegor256.com/2009/03/04/pdd.html) and [about me](http://www.yegor256.com/2017/04/05/pdd-in-action.html).
|
40
|
+
BODY
|
39
41
|
|
40
|
-
EXPECTED_DESCRIPTION = [
|
41
|
-
|
42
|
+
EXPECTED_DESCRIPTION = [
|
43
|
+
" * @todo #531:90min Check default values for annotation properties.\n",
|
44
|
+
" * We still encounter some problems with annotation processing.\n",
|
45
|
+
" * Especially with Autowired annotation from Spring Framework.\n",
|
46
|
+
" * It's relatively simple annotation, but it's not processed correctly.\n",
|
47
|
+
" */\n"
|
48
|
+
].freeze
|
42
49
|
|
43
50
|
def test_parses_pdd_issue
|
44
51
|
issue = PddIssue.new('AnnotationsApplication.java:32-35: Check default values...',
|
@@ -46,4 +53,27 @@ class TestPddIssue < Minitest::Test
|
|
46
53
|
'jeo-maven-plugin', 531)
|
47
54
|
assert_equal(EXPECTED_DESCRIPTION, issue.extract_real_body)
|
48
55
|
end
|
56
|
+
|
57
|
+
def test_converts_to_json
|
58
|
+
issue = PddIssue.new('AnnotationsApplication.java:32-35: Check default values...',
|
59
|
+
'TEST_BODY',
|
60
|
+
'jeo-maven-plugin', 531)
|
61
|
+
expected = <<~JSON.chomp
|
62
|
+
{"number":531,"title":"AnnotationsApplication.java:32-35: Check default values...","description":"TEST_BODY","repository":"jeo-maven-plugin","url":"undefined"}
|
63
|
+
JSON
|
64
|
+
assert_equal(
|
65
|
+
expected,
|
66
|
+
issue.to_json
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_important_issue
|
71
|
+
issue = PddIssue.new('Title', 'Body', 'jeo-maven-plugin', 531, labels: ['soon'])
|
72
|
+
assert issue.important?
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_unimportant_issue
|
76
|
+
issue = PddIssue.new('Title', 'Body', 'jeo-maven-plugin', 531)
|
77
|
+
assert !issue.important?
|
78
|
+
end
|
49
79
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in all
|
14
|
+
# copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
|
24
|
+
require 'minitest/autorun'
|
25
|
+
require_relative '../lib/newsman/pull_request'
|
26
|
+
|
27
|
+
class TestPullRequest < Minitest::Test
|
28
|
+
def test_converts_pr_to_json
|
29
|
+
pr = PullRequest.new(
|
30
|
+
'jeo-maven-plugin',
|
31
|
+
'Interesting Title',
|
32
|
+
'Pr description'
|
33
|
+
)
|
34
|
+
assert_equal(
|
35
|
+
'{"title":"Interesting Title","description":"Pr description","repository":"jeo-maven-plugin","url":"undefined"}',
|
36
|
+
pr.to_json
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
data/test/test_report.rb
CHANGED
@@ -27,42 +27,50 @@ require_relative '../lib/newsman/issues'
|
|
27
27
|
require_relative '../lib/newsman/pull_request'
|
28
28
|
|
29
29
|
class TestReport < Minitest::Test
|
30
|
-
|
31
|
-
|
32
|
-
Subject: WEEK 11 Project
|
30
|
+
REPORT_EXAMPLE = <<~EXPECTED
|
31
|
+
From: User
|
32
|
+
Subject: WEEK 11 Project
|
33
|
+
|
34
|
+
Hi all,
|
33
35
|
|
34
|
-
|
36
|
+
Last week achievements:
|
37
|
+
repository-a:
|
38
|
+
- Did a lot of for (a) repository
|
35
39
|
|
36
|
-
|
37
|
-
repository-
|
38
|
-
|
40
|
+
Next week plans:
|
41
|
+
repository-b:
|
42
|
+
- I will do a lot for repository (b)
|
39
43
|
|
40
|
-
|
41
|
-
|
42
|
-
- I will do a lot for repository (b)
|
44
|
+
Risks:
|
45
|
+
- <todo>
|
43
46
|
|
44
|
-
|
45
|
-
|
47
|
+
Best regards,
|
48
|
+
User
|
49
|
+
Developer
|
50
|
+
2024-03-14
|
51
|
+
EXPECTED
|
46
52
|
|
47
|
-
|
48
|
-
|
49
|
-
Developer
|
50
|
-
2024-03-14"
|
53
|
+
def test_report
|
54
|
+
expected = REPORT_EXAMPLE
|
51
55
|
report = Report.new('User', 'Developer', 'Project')
|
52
56
|
out = report.build("repository-a:\n - Did a lot of for (a) repository",
|
53
|
-
"repository-b:\n - I will do a lot for repository (b)",
|
57
|
+
"repository-b:\n - I will do a lot for repository (b)",
|
58
|
+
'- <todo>',
|
59
|
+
Date.new(2024, 3, 14))
|
54
60
|
assert_equal expected, out
|
55
61
|
end
|
56
62
|
|
57
63
|
def test_report_items
|
58
|
-
expected =
|
59
|
-
|
60
|
-
|
61
|
-
actual = ReportItems.new(prs, issues).to_s
|
64
|
+
expected = <<~EXPECTED
|
65
|
+
Closed Pull Requests:
|
66
|
+
- title: title, repo: repo, url: http://some.url.com
|
62
67
|
|
63
|
-
|
68
|
+
Open Issues:
|
69
|
+
- title: title, repo: repo, number: #123, url: http://google.com, labels: []
|
70
|
+
EXPECTED
|
71
|
+
issues = [Issue.new('title', 'body', 'repo', '123', url: 'http://google.com')]
|
72
|
+
prs = [PullRequest.new('repo', 'title', 'body', url: 'http://some.url.com')]
|
73
|
+
actual = ReportItems.new(prs, issues).to_s
|
64
74
|
assert_equal expected, actual
|
65
75
|
end
|
66
|
-
|
67
|
-
|
68
76
|
end
|