code-review-ai 0.1.1
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 +7 -0
- data/bin/code-review-ai +60 -0
- data/lib/code_review_ai/client/branch_summary.rb +29 -0
- data/lib/code_review_ai/client/code_review.rb +33 -0
- data/lib/code_review_ai/client/initialize.rb +25 -0
- data/lib/code_review_ai/client/utils.rb +63 -0
- data/lib/code_review_ai/prompts.rb +52 -0
- data/lib/code_review_ai/version.rb +5 -0
- data/lib/code_review_ai.rb +8 -0
- metadata +153 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 44b987a9b718977db5cb57cc5070619c83527a885415ef390c1d816bfeadae2b
|
4
|
+
data.tar.gz: 175707830a53cba891cd74bd612cc6fb7e3efa3da3afeff59a5ddd2bc6607112
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 95a4b53f801fed345232ee28aaca77ebbe7266ed154bc9c5ca4fd463b80e9a4bc2ed364d169a948c439f05c65f3735fff6adfc5112c84dcacb87c48704023027
|
7
|
+
data.tar.gz: a419729cc7f97749e220e453d8d80ad98bc96282950e3b9fd06cc366a3d1c66610c689a5108df0f8e1c9911e70c8d6a061e69c7e72a6a1f3f418add41d2f0097
|
data/bin/code-review-ai
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'code_review_ai'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.banner = <<~BANNER
|
9
|
+
Code Review AI - AI-powered code review tool
|
10
|
+
|
11
|
+
Usage: code-review-ai --command [review|summary] [options]
|
12
|
+
|
13
|
+
Commands:
|
14
|
+
review - Conduct AI code review on current branch
|
15
|
+
summary - Generate branch change summary
|
16
|
+
|
17
|
+
Environment Variables:
|
18
|
+
OPENAI_ACCESS_TOKEN - OpenAI API key
|
19
|
+
OPENAI_MODEL - AI model (default: gpt-3.5-turbo)
|
20
|
+
OPENAI_LANGUAGE - Output language (default: English)
|
21
|
+
BANNER
|
22
|
+
|
23
|
+
opts.on("-k", "--api-key KEY", "OpenAI API key") do |key|
|
24
|
+
options[:api_key] = key
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-m", "--model MODEL", "AI model to use") do |model|
|
28
|
+
options[:model] = model
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("-l", "--language LANG", "Language for output") do |lang|
|
32
|
+
options[:language] = lang
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("-c", "--command CMD", "Command (review or summary)") do |cmd|
|
36
|
+
options[:command] = cmd
|
37
|
+
end
|
38
|
+
end.parse!
|
39
|
+
|
40
|
+
begin
|
41
|
+
api_key = options[:api_key] || ENV['OPENAI_ACCESS_TOKEN']
|
42
|
+
model = options[:model] || ENV['OPENAI_MODEL'] || 'gpt-3.5-turbo'
|
43
|
+
language = options[:language] || ENV['OPENAI_LANGUAGE'] || 'English'
|
44
|
+
command = options[:command] || 'review'
|
45
|
+
|
46
|
+
reviewer = CodeReviewAi::Client.new(api_key, model, language)
|
47
|
+
|
48
|
+
case command
|
49
|
+
when 'review'
|
50
|
+
reviewer.conduct_code_review
|
51
|
+
when 'summary'
|
52
|
+
puts reviewer.generate_branch_summary
|
53
|
+
else
|
54
|
+
puts "Unknown command. Use 'review' or 'summary'"
|
55
|
+
exit 1
|
56
|
+
end
|
57
|
+
rescue StandardError => e
|
58
|
+
puts "Error: #{e.message}"
|
59
|
+
exit 1
|
60
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative '../prompts'
|
3
|
+
|
4
|
+
module CodeReviewAi
|
5
|
+
class Client
|
6
|
+
def generate_branch_summary
|
7
|
+
prompt = generate_prompt(CodeReviewAi::Prompts::BRANCH_SUMMARY_TEMPLATE, @language)
|
8
|
+
response = @client.chat(
|
9
|
+
parameters: {
|
10
|
+
model: @ai_model,
|
11
|
+
messages: [
|
12
|
+
{
|
13
|
+
role: 'system',
|
14
|
+
content: 'You are an assistant summarizing git branch changes clearly and concisely.'
|
15
|
+
},
|
16
|
+
{
|
17
|
+
role: 'user',
|
18
|
+
content: prompt
|
19
|
+
}
|
20
|
+
]
|
21
|
+
}
|
22
|
+
)
|
23
|
+
summary = process_response(response)
|
24
|
+
puts summary
|
25
|
+
rescue StandardError => e
|
26
|
+
"Error generating branch summary: #{e.message}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative '../prompts'
|
3
|
+
|
4
|
+
module CodeReviewAi
|
5
|
+
class Client
|
6
|
+
# Conduct an AI-powered code review on the current branch
|
7
|
+
# Analyzes git diff and generates review comments using OpenAI
|
8
|
+
#
|
9
|
+
# @return [String] Generated code review comments
|
10
|
+
def conduct_code_review
|
11
|
+
prompt = generate_prompt(CodeReviewAi::Prompts::CODE_REVIEW_TEMPLATE, @language)
|
12
|
+
response = @client.chat(
|
13
|
+
parameters: {
|
14
|
+
model: @ai_model,
|
15
|
+
messages: [
|
16
|
+
{
|
17
|
+
role: 'system',
|
18
|
+
content: 'You are an assistant generating code review comments based on repository changes.'
|
19
|
+
},
|
20
|
+
{
|
21
|
+
role: 'user',
|
22
|
+
content: prompt
|
23
|
+
}
|
24
|
+
]
|
25
|
+
}
|
26
|
+
)
|
27
|
+
code_review_comments = process_response(response)
|
28
|
+
apply_code_review_comments(code_review_comments)
|
29
|
+
rescue StandardError => e
|
30
|
+
"Error communicating with OpenAI API: #{e.message}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CodeReviewAi
|
4
|
+
class Client
|
5
|
+
# Initialize a new CodeReviewAi client
|
6
|
+
#
|
7
|
+
# @param api_token [String] OpenAI API access token for authentication
|
8
|
+
# @param ai_model [String] OpenAI model to use (e.g., 'gpt-3.5-turbo', 'gpt-4')
|
9
|
+
# @param language [String] Output language for generated content
|
10
|
+
def initialize(api_token, ai_model, language)
|
11
|
+
@client = create_openai_client(api_token)
|
12
|
+
@ai_model = ai_model
|
13
|
+
@language = language
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def create_openai_client(api_token)
|
19
|
+
OpenAI::Client.new(
|
20
|
+
access_token: api_token,
|
21
|
+
log_errors: true
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CodeReviewAi
|
4
|
+
class Client
|
5
|
+
private
|
6
|
+
|
7
|
+
def process_response(response)
|
8
|
+
response.dig('choices', 0, 'message', 'content') || 'Error: Unable to generate code review.'
|
9
|
+
end
|
10
|
+
|
11
|
+
def generate_prompt(template, language)
|
12
|
+
format(template, changes: fetch_branch_changes, language: language)
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch_branch_changes
|
16
|
+
current_branch = get_current_branch
|
17
|
+
default_branch = check_for_default_branch('main') || check_for_default_branch('master')
|
18
|
+
|
19
|
+
raise 'Neither main nor master branch found in the repository' unless default_branch
|
20
|
+
raise 'Could not determine current branch' unless current_branch
|
21
|
+
|
22
|
+
stdout, stderr, status = Open3.capture3("git diff #{default_branch}..#{current_branch}")
|
23
|
+
|
24
|
+
raise "Error getting git diff: #{stderr}" unless status.success?
|
25
|
+
|
26
|
+
stdout.strip
|
27
|
+
end
|
28
|
+
|
29
|
+
def check_for_default_branch(branch_name)
|
30
|
+
_, _, status = Open3.capture3("git show-ref refs/heads/#{branch_name}")
|
31
|
+
status.success? ? branch_name : nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_current_branch
|
35
|
+
stdout, _, status = Open3.capture3('git rev-parse --abbrev-ref HEAD')
|
36
|
+
return stdout.strip if status.success?
|
37
|
+
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def apply_code_review_comments(code_review_comments)
|
42
|
+
comment_blocks = code_review_comments.scan(/File:\s+(.*?)\s+Line:\s+(\d+)\s+Suggestion:\s+(.*?)\s*(?:\n|$)/m)
|
43
|
+
|
44
|
+
comment_blocks.each do |file_path, line_number, suggestion|
|
45
|
+
add_comments_to_file(file_path, line_number.to_i, suggestion)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_comments_to_file(file_path, line_number, suggestion)
|
50
|
+
file_content = File.readlines(file_path)
|
51
|
+
|
52
|
+
# Ensure the line number is within the bounds of the file's length
|
53
|
+
if (1..file_content.size).cover?(line_number)
|
54
|
+
# Add the comment at the specified line
|
55
|
+
file_content[line_number - 1] = "#{file_content[line_number - 1].chomp} # #{suggestion}\n"
|
56
|
+
# Write the modified content back to the file
|
57
|
+
File.write(file_path, file_content.join)
|
58
|
+
else
|
59
|
+
puts "Warning: Line #{line_number} does not exist in file #{file_path}."
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module CodeReviewAi
|
2
|
+
module Prompts
|
3
|
+
CODE_REVIEW_TEMPLATE = <<~PROMPT
|
4
|
+
Act as a Ruby developer with expert-level knowledge of OOP principles and best practices.
|
5
|
+
You are tasked with reviewing the changes in the repository and providing ACTIONABLE code improvement suggestions.
|
6
|
+
|
7
|
+
I will specifiy the language(e.g., English) of the code review and provide the differences between the "current branch" and "main (or master)" branch at the end of this prompt.
|
8
|
+
|
9
|
+
Instructions for your response:
|
10
|
+
|
11
|
+
1. Carefully analyze the changes in terms of Object-Oriented Principles, performance, readability and maintainability, scalability, and error handling.
|
12
|
+
2. Provide improvement suggestions for each file and line number where applicable.
|
13
|
+
3. Use the exact format like below for every suggestion:
|
14
|
+
|
15
|
+
"File: lib/code_review_ai.rb \nLine: 12 \nSuggestion: [👉SUGGESTION💡]Consider adding error handling for scenarios where the Git repository cannot be opened.\n\nFile: lib/code_review_ai.rb \nLine: 24 \nSuggestion: [👉SUGGESTION💡]Add a comment to explain the purpose of the `generate_code_review` method.\n\nFile: lib/code_review_ai.rb \nLine: 33 \nSuggestion: [👉SUGGESTION💡]Add a comment to clarify what the expected format of the prompt is.\n\nFile: lib/code_review_ai.rb \nLine: 41 \nSuggestion: [👉SUGGESTION💡]Include a comment to describe what `apply_code_review_comments` does."
|
16
|
+
|
17
|
+
Ensure that each suggestion is clearly associated with the relevant file and line of code.
|
18
|
+
Make sure to FOLLOW THE FORMAT strictly to avoid any errors in processing the suggestions.
|
19
|
+
|
20
|
+
If code examples are available, make your best effort to include them in the suggestions.
|
21
|
+
|
22
|
+
Make sure NOT TO RETURN ANYTHING OUTSIDE OF THE REQUIRED FORMAT. No introduction or conclusion is needed.
|
23
|
+
|
24
|
+
Please generate the code review suggestions in following language:
|
25
|
+
%<language>s
|
26
|
+
|
27
|
+
Here are the changes in the repository:
|
28
|
+
%<changes>s
|
29
|
+
PROMPT
|
30
|
+
|
31
|
+
BRANCH_SUMMARY_TEMPLATE = <<~PROMPT
|
32
|
+
You are a Ruby developer with expert-level proficiency in OOP principles and best practices.
|
33
|
+
Your task is to provide a concise, well-structured summary of the changes made in the following branch.
|
34
|
+
|
35
|
+
Please ensure that all output is written in %<language>s.
|
36
|
+
|
37
|
+
Follow this format for your summary:
|
38
|
+
|
39
|
+
1. **Overview**: A high-level summary of the changes made in the branch, written in %<language>s.
|
40
|
+
|
41
|
+
2. **File-wise Breakdown**: For each file, list the key changes in bullet points. Be specific and concise:
|
42
|
+
- **Summary**: A brief description of the change.
|
43
|
+
- **Impact**: How the change affects the functionality or performance.
|
44
|
+
- **Potential Issues**: Any concerns or potential pitfalls with the change.
|
45
|
+
- **Suggestions for Improvement**: Recommendations for enhancing the change or code.
|
46
|
+
- **Other Notes**: Any additional relevant details or context.
|
47
|
+
|
48
|
+
Changes:
|
49
|
+
%<changes>s
|
50
|
+
PROMPT
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openai'
|
4
|
+
require 'open3'
|
5
|
+
require_relative 'code_review_ai/client/initialize'
|
6
|
+
require_relative 'code_review_ai/client/code_review'
|
7
|
+
require_relative 'code_review_ai/client/branch_summary'
|
8
|
+
require_relative 'code_review_ai/client/utils'
|
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: code-review-ai
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michiharu Ono
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 2025-01-26 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: faraday
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '2.1'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '2.1'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: optparse
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.6'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.6'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: ruby-openai
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '7.3'
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '7.3'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: bundler-audit
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0.9'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0.9'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: pry
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 0.14.0
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 0.14.0
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: rspec
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '3.13'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '3.13'
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: rubocop
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '1.6'
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '1.6'
|
110
|
+
description: CLI tool that leverages OpenAI to generate code reviews
|
111
|
+
email: michiharuono77@gmail.com
|
112
|
+
executables:
|
113
|
+
- code-review-ai
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- bin/code-review-ai
|
118
|
+
- lib/code_review_ai.rb
|
119
|
+
- lib/code_review_ai/client/branch_summary.rb
|
120
|
+
- lib/code_review_ai/client/code_review.rb
|
121
|
+
- lib/code_review_ai/client/initialize.rb
|
122
|
+
- lib/code_review_ai/client/utils.rb
|
123
|
+
- lib/code_review_ai/prompts.rb
|
124
|
+
- lib/code_review_ai/version.rb
|
125
|
+
licenses:
|
126
|
+
- MIT
|
127
|
+
metadata:
|
128
|
+
rubygems_mfa_required: 'true'
|
129
|
+
post_install_message: |
|
130
|
+
After installing the gem, please run the following command to install Node.js dependencies:
|
131
|
+
npm install -g standard-version
|
132
|
+
|
133
|
+
You can then add a changelog by running:
|
134
|
+
npx standard-version --no-tag
|
135
|
+
This refers the version defined in the package.json file.
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '3.0'
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
requirements: []
|
150
|
+
rubygems_version: 3.6.2
|
151
|
+
specification_version: 4
|
152
|
+
summary: Generate code reviews effortlessly using OpenAI.
|
153
|
+
test_files: []
|