newsman 0.1.13 → 0.2.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
2
  SHA256:
3
- metadata.gz: e0b76df23c180a0cc0a30bdc4d60fd675ece0c5201605bcbdea44bd0a7d25bce
4
- data.tar.gz: 72e37a051f065fcc3a625ba3175439b1351e28acc6e0b2cc33a352c3f5dda652
3
+ metadata.gz: c0ec4c08d224982a75fc3ae533368cdeff2c4d7cab0072441fcfbd604f194b42
4
+ data.tar.gz: 8633c4f4dc84b0f6a285e06b67b0cb9dd3f9e7a18d6dc032589237652181d36f
5
5
  SHA512:
6
- metadata.gz: e66602a260c38095c76e367b8a84f52f1f16bc6a74b103e3b0c0e6e8690e8bea1d1d54b41ca97cc0c259c55b571485e788864b3f788251730759ffd19ce356ec
7
- data.tar.gz: e4d0aef6d9a2958084402468adc84f2e24d8f7da507ea8a2dab7515f5855411f6e6a73e1969a4cc30f413e180eee2ceaab520c5addb7d59fa780090516dc7e76
6
+ metadata.gz: 85df6a743456154cdfcd2999a2f3a1977347cf9b101c8f2e35bd0b13024e6e1d66e8cf699bc7a11feac586f5b7bb6a2bdc08b75936bf967b011afdc2f1963716
7
+ data.tar.gz: e4aa02defb4c4a02dee05fe334fb799f0f10b825110e194e0f3d7e5da79ce54144e5a77d1543c57acbdc56ca444fa4be625f4e16a9c83487abc917711d0e771c
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Newsman
2
2
 
3
+
4
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE.txt)
5
+ [![Gem Version](https://img.shields.io/gem/v/newsman.svg)](https://rubygems.org/gems/newsman)
6
+
3
7
  Newsman is a simple script that collects information about a developer's weekly activity on GitHub and creates a human-readable summary of the work done. To create the summary, Newsman asks ChatGPT to handle all the information about a developer's activity, including their pull requests and created issues.
4
8
 
5
9
  ## Install
@@ -31,7 +35,9 @@ Usage: newsman [options]
31
35
  -n, --name NAME Reporter name. Human readable name that will be used in a report
32
36
  -u, --username USERNAME GitHub username. For example, 'volodya-lombrozo'
33
37
  -r, --repository REPOSITORIES Specify which repositories to include in a report. You can specify several repositories using a comma separator, for example: '-r objectionary/jeo-maven-plugin,objectionary/opeo-maven-plugin'
34
- -p, --position Reporter position in a company. Default value is a 'Software Developer'.
38
+ -p, --position POSITION Reporter position in a company. Default value is a 'Software Developer'.
39
+ -o, --output OUTPUT Output type. Newsman prints a report to a stdout by default. You can choose another options like '-o html', '-o txt' or even '-o html'
40
+ -t, --title TITLE Project Title. Empty by default
35
41
  ```
36
42
 
37
43
  ### Example
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
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
+ require 'openai'
24
+
25
+ # This class mimics a robot that can analyse a developer activity.
26
+ # The assistant uses OpenAI API to analyze.
27
+ class Assistant
28
+ CONTEXT = 'You are a developer tasked'\
29
+ ' with composing a concise report detailing your activities'\
30
+ ' and progress for the previous week,'\
31
+ ' intended for submission to your supervisor.'
32
+
33
+ def initialize(token, model: 'gpt-3.5-turbo', temperature: 0.3)
34
+ @token = token
35
+ @model = model
36
+ @temperature = temperature
37
+ @client = OpenAI::Client.new(access_token: token)
38
+ end
39
+
40
+ def say_hello
41
+ <<~HELLO
42
+ I'm an assistant that can work with OpenAI client.
43
+ Please, use me, if you need any help.
44
+ I'm using #{@model}, with #{@temperature} temperature.
45
+ HELLO
46
+ end
47
+
48
+ # rubocop:disable Metrics/MethodLength
49
+ def next_plans(issues)
50
+ example = "repository-name:\n
51
+ - To publish ABC package draft [#27]\n
52
+ - To review first draft of the report [#56]\n
53
+ - To implement optimization for the class X [#125]"
54
+ prompt = <<~PROMPT
55
+ Please compile a summary of the plans for the next week using the GitHub Issues.
56
+ Each issue should be summarized in a single sentence.
57
+ Combine all the information from each Issue into a concise and fluent sentence.
58
+ Pay attention, that you didn't loose any issue.
59
+ Ensure that each sentence includes the corresponding issue number as an integer value. If an issue doesn't mention an issue number, just print [#chore].
60
+ If several issues have the same number, combine them into a single sentence.
61
+ Please strictly adhere to the example template provided: "#{example}".
62
+ List of GitHub Issues in JSON format: ```json #{issues}```.
63
+ PROMPT
64
+ send(prompt)
65
+ end
66
+ # rubocop:enable Metrics/MethodLength
67
+
68
+ # rubocop:disable Metrics/MethodLength
69
+ def prev_results(prs)
70
+ example = "repository-name:\n
71
+ - Added 100 new files to the Dataset [#168]\n
72
+ - Fixed the deployment of XYZ [#169]\n
73
+ - Refined the requirements [#177]\n"
74
+ prompt = <<~PROMPT
75
+ Please compile a summary of the work completed in the following Pull Requests (PRs).
76
+ Each PR should be summarized in a single sentence, focusing on the PR title rather than the implementation details.
77
+ Ensure no PR is omitted.
78
+ Each sentence must include the corresponding issue number as an integer value. If a PR does not mention an issue number, use [#chore].
79
+ If several PRs have the same number, combine them into a single sentence.
80
+ Combine the information from each PR into a concise and fluent sentence.
81
+ Follow the provided example template strictly: "#{example}".
82
+ List of Pull Requests in JSON format: ```json #{prs}```.
83
+ PROMPT
84
+ send(prompt)
85
+ end
86
+ # rubocop:enable Metrics/MethodLength
87
+
88
+ # rubocop:disable Metrics/MethodLength
89
+ def risks(all)
90
+ example = "repository-name:\n
91
+ - The server is weak, we may fail the delivery\n
92
+ of the dataset, report milestone will be missed [#487].\n
93
+ - The code in repository is suboptimal, we might have some problems for the future maintainability [#44].\n"
94
+ prompt = <<~PROMPT
95
+ Please compile a summary of the risks identified in the repository from the list of pull requests provided.
96
+ If no risks are identified in a pull request, just answer 'No risks identified' for that PR.
97
+ Each risk should be summarized in a concise and fluent single sentence.
98
+ Developers usually mention some risks in pull request descriptions, either as 'risk' or 'issue'.#{' '}
99
+ Ensure that each sentence includes the corresponding PR number as an integer value. If a PR doesn't mention an issue number, just print [#chore].
100
+ Please strictly adhere to the example template provided: "#{example}".
101
+ List of Pull Requests: ```json #{all}```.
102
+ PROMPT
103
+ send(prompt)
104
+ end
105
+ # rubocop:enable Metrics/MethodLength
106
+
107
+ def format(report)
108
+ prompt = <<~PROMPT
109
+ I have a weekly report with different parts that use various formatting styles.
110
+ Please format the entire report into a single cohesive format while preserving the original text without any changes.
111
+ Ensure that the formatting is consistent throughout the document.
112
+
113
+ Here is the report:
114
+
115
+ #{report}
116
+ PROMPT
117
+ send(prompt)
118
+ end
119
+
120
+ def send(request)
121
+ @client.chat(
122
+ parameters: {
123
+ model: @model,
124
+ messages: [
125
+ { role: 'system', content: CONTEXT },
126
+ { role: 'user', content: request.to_s }
127
+ ],
128
+ temperature: @temperature
129
+ }
130
+ ).dig('choices', 0, 'message', 'content')
131
+ end
132
+
133
+ def deprecated(method)
134
+ warn "Warning! '#{method}' is deprecated and will be removed in future versions."
135
+ end
136
+ end
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
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
+
25
+ # This class represents a useful abstraction over Github API.
26
+ class Github
27
+ def initialize(token)
28
+ @client = Octokit::Client.new(github_token: token)
29
+ end
30
+
31
+ def pull_requests(username, repositories)
32
+ query = "is:pr author:#{username} created:>=#{date_one_week_ago(Date.today)} #{repositories}"
33
+ puts "Searching pull requests for #{username}."
34
+ puts 'Newsman uses the following request to GitHub to gather the'\
35
+ " required information about user activity: '#{query}'"
36
+ @client.search_issues(query).items.map do |pull_request|
37
+ parse_pr(pull_request)
38
+ end
39
+ end
40
+
41
+ def issues(username, repositories)
42
+ one_month_ago = Date.today.prev_month.strftime('%Y-%m-%d')
43
+ query = "is:issue is:open author:#{username}"\
44
+ " author:0pdd created:>=#{one_month_ago} #{repositories}"
45
+ puts "Searching issues using the following query: '#{query}'"
46
+ @client.search_issues(query).items.map do |issue|
47
+ parse_issue(issue)
48
+ end.select(&:important?)
49
+ end
50
+
51
+ def parse_pr(pull_request)
52
+ title = pull_request.title.to_s
53
+ repository = pull_request.repository_url.split('/').last
54
+ puts "Found PR in #{repository}: #{title}"
55
+ PullRequest.new(repository, title, pull_request.body.to_s, url: pull_request.html_url)
56
+ end
57
+
58
+ def parse_issue(issue)
59
+ title, repository, number = issue_details(issue)
60
+ if issue.user.login == '0pdd'
61
+ PddIssue.new(title, issue.body.to_s, repository, number, url: issue.html_url, labels: issue.labels.map(&:name))
62
+ else
63
+ Issue.new(title, issue.body.to_s, repository, number, url: issue.html_url, labels: issue.labels.map(&:name))
64
+ end
65
+ end
66
+
67
+ def issue_details(issue)
68
+ title = issue.title.to_s
69
+ repository = issue.repository_url.split('/').last
70
+ number = issue.number.to_s
71
+ puts "Found issue in #{repository}:[##{number}] #{title}"
72
+ [title, repository, number]
73
+ end
74
+ end
75
+
76
+ def date_one_week_ago(today)
77
+ today = Date.parse(today) unless today.is_a?(Date)
78
+ one_week_ago = today - 7
79
+ one_week_ago.strftime('%Y-%m-%d')
80
+ end
@@ -1,40 +1,57 @@
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
+
3
23
  require 'erb'
4
24
  require 'redcarpet'
5
25
  require 'nokogiri'
6
- # frozen_string_literal: true
7
26
 
27
+ # This class represents a report output in HTML format.
8
28
  class Htmlout
9
- TEMPLATE = "
10
- <head>
11
- <title><%= title %></title>
12
- </head>
13
- <body>
14
- <h1><%= title %></h1>
15
- <%= body %>
16
- </body>
17
- "
29
+ TEMPLATE = <<~HTML
30
+ <head>
31
+ <title><%= title %></title>
32
+ </head>
33
+ <body>
34
+ <h1><%= title %></h1>
35
+ <%= body %>
36
+ </body>
37
+ HTML
18
38
 
19
39
  def initialize(root = '.')
20
40
  @root = root
21
41
  end
22
42
 
43
+ # rubocop:disable Metrics/AbcSize
23
44
  def print(report, reporter)
24
45
  title = title(reporter)
25
- renderer = Redcarpet::Render::HTML.new(no_links: true, hard_wrap: true, prettify: true)
26
- markdown = Redcarpet::Markdown.new(renderer, autolink: true, tables: true)
27
- body = markdown.render(report)
28
- renderer = ERB.new(TEMPLATE)
29
- html_content = renderer.result(binding)
30
- html_content = Nokogiri::HTML(html_content, &:noblanks).to_xhtml(indent: 2)
46
+ body = to_html(report)
31
47
  puts "Create a html file in a directory #{@root}"
32
48
  file = File.new(File.join(@root, filename(reporter)), 'w')
33
49
  puts "File #{file.path} was successfully created"
34
- file.puts html_content
50
+ file.puts Nokogiri::HTML(ERB.new(TEMPLATE).result(binding), &:noblanks).to_xhtml(indent: 2)
35
51
  puts "Report was successfully printed to a #{file.path}"
36
52
  file.close
37
53
  end
54
+ # rubocop:enable Metrics/AbcSize
38
55
 
39
56
  def title(reporter)
40
57
  date = Time.new.strftime('%d.%m.%Y')
@@ -45,4 +62,12 @@ class Htmlout
45
62
  date = Time.new.strftime('%d.%m.%Y')
46
63
  "#{date}.#{reporter}.html"
47
64
  end
65
+
66
+ def to_html(report)
67
+ Redcarpet::Markdown.new(
68
+ Redcarpet::Render::HTML.new(no_links: true, hard_wrap: true, prettify: true),
69
+ autolink: true,
70
+ tables: true
71
+ ).render(report)
72
+ end
48
73
  end
@@ -1,37 +1,89 @@
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
+
3
23
  require 'net/http'
4
- # frozen_string_literal: true
24
+ require 'json'
5
25
 
26
+ # This class represents a GitHub Issue abstraction created by a user.
6
27
  class Issue
7
28
  attr_accessor :title, :body, :repo, :number
8
- attr_reader :url
9
29
 
10
- def initialize(title, body, repo, number, url: 'undefined')
30
+ def initialize(title, body, repo, number, **additional)
31
+ defaults = { url: 'undefined', labels: [] }
11
32
  @title = title
12
33
  @body = body
13
34
  @repo = repo
14
35
  @number = number
15
- @url = url
36
+ @additional = defaults.merge(additional)
16
37
  end
17
38
 
18
39
  def to_s
19
- "title: ```#{@title}```,\ndescription: ```#{@body}```,\nrepo: ```#{@repo}```,\nissue number: \##{@number}\n"
40
+ <<~MARKDOWN
41
+ title: ```#{@title}```,
42
+ description: ```#{@body}```,
43
+ repo: ```#{@repo}```,
44
+ issue number: \##{@number},
45
+ additional: #{@additional}
46
+ MARKDOWN
47
+ end
48
+
49
+ def detailed_title
50
+ "title: #{@title}, repo: #{@repo}, number: \##{@number}, url: #{url}, labels: #{labels}"
20
51
  end
21
52
 
22
- def detailed_title
23
- "title: #{@title}, repo: #{@repo}, number: \##{@number}, url: #{@url}"
53
+ def url
54
+ @additional[:url]
55
+ end
56
+
57
+ def labels
58
+ @additional[:labels]
59
+ end
60
+
61
+ def to_json(*_args)
62
+ {
63
+ number: @number,
64
+ title: @title,
65
+ description: @body,
66
+ repository: @repo,
67
+ url: url.to_s
68
+ }.to_json
69
+ end
70
+
71
+ def important?
72
+ labels.include? 'soon'
24
73
  end
25
-
26
74
  end
27
75
 
76
+ # This class represents a GitHub issue abstraction created by a 0pdd robot.
28
77
  class PddIssue
29
- def initialize(title, body, repo, number, url: 'undefined')
78
+ attr_accessor :repo
79
+
80
+ def initialize(title, body, repo, number, **additional)
81
+ defaults = { url: 'undefined', labels: [] }
30
82
  @title = title
31
83
  @body = body
32
84
  @repo = repo
33
85
  @number = number
34
- @url = url
86
+ @additional = defaults.merge(additional)
35
87
  end
36
88
 
37
89
  def extract_real_body
@@ -42,17 +94,44 @@ class PddIssue
42
94
  end
43
95
 
44
96
  def issue_link
45
- @body[%r{https://github\.com/[\w\-/]+/blob/[\w\d]+/[\w/.-]+#\w+-\w+}, 0].gsub('https://github.com', 'https://raw.githubusercontent.com').gsub(
46
- 'blob/', ''
47
- )
97
+ @body[%r{https://github\.com/[\w\-/]+/blob/[\w\d]+/[\w/.-]+#\w+-\w+}, 0]
98
+ .gsub('https://github.com', 'https://raw.githubusercontent.com')
99
+ .gsub('blob/', '')
48
100
  end
49
101
 
50
102
  def to_s
51
- "title: ```#{@title}```,\ndescription: ```#{extract_real_body}```,\nrepo: ```#{@repo}```,\nissue number: \##{@number}\n"
103
+ <<~MARKDOWN
104
+ title: ```#{@title}```,
105
+ description: ```#{extract_real_body}```,
106
+ repo: ```#{@repo}```,
107
+ issue number: \##{@number},
108
+ additional: #{@additional}
109
+ MARKDOWN
52
110
  end
53
111
 
54
112
  def detailed_title
55
- "title: #{@title}, repo: #{@repo}, issue number: \##{@number}, url: #{@url}"
113
+ "title: #{@title}, repo: #{@repo}, issue number: \##{@number}, url: #{url}, labels: #{labels}"
56
114
  end
57
115
 
116
+ def to_json(*_args)
117
+ {
118
+ number: @number,
119
+ title: @title,
120
+ description: @body,
121
+ repository: @repo,
122
+ url: url.to_s
123
+ }.to_json
124
+ end
125
+
126
+ def important?
127
+ labels.include? 'soon'
128
+ end
129
+
130
+ def url
131
+ @additional[:url]
132
+ end
133
+
134
+ def labels
135
+ @additional[:labels]
136
+ end
58
137
  end
@@ -1,5 +1,28 @@
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
+ require 'json'
23
+
24
+ # This class represents GitHub Pull Request abstraction.
25
+ # In the future, it might be any Pull or Merge request.
3
26
  class PullRequest
4
27
  attr_accessor :repository, :title, :description
5
28
  attr_reader :url
@@ -11,6 +34,15 @@ class PullRequest
11
34
  @url = url
12
35
  end
13
36
 
37
+ def to_json(*_args)
38
+ {
39
+ title: @title,
40
+ description: @description,
41
+ repository: @repository,
42
+ url: @url
43
+ }.to_json
44
+ end
45
+
14
46
  def to_s
15
47
  "title: ```#{@title}```,\ndescription: ```#{@description}```,\nrepo: ```#{@repository}```\n"
16
48
  end
@@ -18,5 +50,4 @@ class PullRequest
18
50
  def detailed_title
19
51
  "title: #{@title}, repo: #{@repository}, url: #{@url}"
20
52
  end
21
-
22
53
  end
@@ -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
- start = "From: #{@user}\nSubject: #{week_of_a_year(@title,
14
- date)}\n\nHi all,\n\nLast week achievements:\n#{achievements}\n\nNext week plans:\n#{plans}\n\nRisks:\n#{risks}\n\nBest regards,\n#{@user}\n#{@position}\n#{date}"
15
-
16
- finish = ''
17
- if !@additional.empty?
18
- finish = "\n------\n" + @additional.to_s
19
- end
20
- return start + finish;
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
- return "Closed Pull Requests:\n#{prs_list}\nOpen Issues:\n#{issues_list}"
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'
@@ -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