pr_ai_gen 0.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 +7 -0
- data/.gitignore +1 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +82 -0
- data/exe/pr-ai-gen +12 -0
- data/lib/pull_request_ai_generator.rb +161 -0
- data/pr_ai_gen.gemspec +23 -0
- metadata +148 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9d88c164cc0b3c276e43759573219cc064e5d141cd264d46e184bca12f02926b
|
4
|
+
data.tar.gz: 10041eea9b1b4465539cf00d260782692f84db5ea2347b8cbe5cc2bbdd725c57
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dc88eee40aed632629dc2bdb1eb2fc2fa9ee5017b95a4f6c0dba9d2c9ca70d998563c020c6640766af70d57bdf6d74bf4412abe6d532730788e04e204f75d2fa
|
7
|
+
data.tar.gz: 553d015be904145afab53f9dde76bf605fe12d6d875ee5341522c18f637c84879c061e777c307edef44daba0a3c84dabff949153f37c29ede5c724812b1f5dce
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
addressable (2.8.6)
|
5
|
+
public_suffix (>= 2.0.2, < 6.0)
|
6
|
+
base64 (0.2.0)
|
7
|
+
capybara (3.39.2)
|
8
|
+
addressable
|
9
|
+
matrix
|
10
|
+
mini_mime (>= 0.1.3)
|
11
|
+
nokogiri (~> 1.8)
|
12
|
+
rack (>= 1.6.0)
|
13
|
+
rack-test (>= 0.6.3)
|
14
|
+
regexp_parser (>= 1.5, < 3.0)
|
15
|
+
xpath (~> 3.2)
|
16
|
+
coderay (1.1.3)
|
17
|
+
faraday (2.8.1)
|
18
|
+
base64
|
19
|
+
faraday-net_http (>= 2.0, < 3.1)
|
20
|
+
ruby2_keywords (>= 0.0.4)
|
21
|
+
faraday-net_http (3.0.2)
|
22
|
+
git (1.19.1)
|
23
|
+
addressable (~> 2.8)
|
24
|
+
rchardet (~> 1.8)
|
25
|
+
httparty (0.20.0)
|
26
|
+
mime-types (~> 3.0)
|
27
|
+
multi_xml (>= 0.5.2)
|
28
|
+
matrix (0.4.2)
|
29
|
+
method_source (1.0.0)
|
30
|
+
mime-types (3.4.1)
|
31
|
+
mime-types-data (~> 3.2015)
|
32
|
+
mime-types-data (3.2022.0105)
|
33
|
+
mini_mime (1.1.5)
|
34
|
+
multi_xml (0.6.0)
|
35
|
+
nokogiri (1.15.5-arm64-darwin)
|
36
|
+
racc (~> 1.4)
|
37
|
+
nokogiri (1.15.5-x86_64-linux)
|
38
|
+
racc (~> 1.4)
|
39
|
+
octokit (8.1.0)
|
40
|
+
base64
|
41
|
+
faraday (>= 1, < 3)
|
42
|
+
sawyer (~> 0.9)
|
43
|
+
optparse (0.4.0)
|
44
|
+
pry (0.14.1)
|
45
|
+
coderay (~> 1.1)
|
46
|
+
method_source (~> 1.0)
|
47
|
+
public_suffix (5.0.4)
|
48
|
+
racc (1.7.3)
|
49
|
+
rack (3.0.9.1)
|
50
|
+
rack-test (2.1.0)
|
51
|
+
rack (>= 1.3)
|
52
|
+
rchardet (1.8.0)
|
53
|
+
regexp_parser (2.9.0)
|
54
|
+
rexml (3.2.6)
|
55
|
+
ruby2_keywords (0.0.5)
|
56
|
+
rubyzip (2.3.2)
|
57
|
+
sawyer (0.9.2)
|
58
|
+
addressable (>= 2.3.5)
|
59
|
+
faraday (>= 0.17.3, < 3)
|
60
|
+
selenium-webdriver (4.9.0)
|
61
|
+
rexml (~> 3.2, >= 3.2.5)
|
62
|
+
rubyzip (>= 1.2.2, < 3.0)
|
63
|
+
websocket (~> 1.0)
|
64
|
+
websocket (1.2.10)
|
65
|
+
xpath (3.2.0)
|
66
|
+
nokogiri (~> 1.8)
|
67
|
+
|
68
|
+
PLATFORMS
|
69
|
+
arm64-darwin-22
|
70
|
+
x86_64-linux
|
71
|
+
|
72
|
+
DEPENDENCIES
|
73
|
+
capybara
|
74
|
+
git
|
75
|
+
httparty
|
76
|
+
octokit
|
77
|
+
optparse
|
78
|
+
pry
|
79
|
+
selenium-webdriver
|
80
|
+
|
81
|
+
BUNDLED WITH
|
82
|
+
2.4.21
|
data/exe/pr-ai-gen
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'git'
|
3
|
+
require 'httparty'
|
4
|
+
require 'octokit'
|
5
|
+
require 'capybara/dsl'
|
6
|
+
require 'pry'
|
7
|
+
|
8
|
+
# Define the CLI class
|
9
|
+
class PullRequestAIGenerator
|
10
|
+
OPEN_AI_URL = "https://api.openai.com/v1"
|
11
|
+
|
12
|
+
include Capybara::DSL
|
13
|
+
|
14
|
+
attr_reader :options
|
15
|
+
|
16
|
+
def initialize(args)
|
17
|
+
@options = parse_options(args)
|
18
|
+
@diff = nil
|
19
|
+
@pr_content = nil
|
20
|
+
@git_repo = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def init
|
24
|
+
puts 'Initializing pr-ai-gen...'
|
25
|
+
credentials_path = File.expand_path('~/.pr-gem/credentials')
|
26
|
+
pr_gem_path = File.expand_path('~/.pr-gem')
|
27
|
+
|
28
|
+
unless File.exist?(pr_gem_path)
|
29
|
+
Dir.mkdir(pr_gem_path)
|
30
|
+
puts '.pr-gem repository created successfully!'
|
31
|
+
end
|
32
|
+
|
33
|
+
if File.exist?(credentials_path)
|
34
|
+
puts 'Credentials file already exists!'
|
35
|
+
return
|
36
|
+
end
|
37
|
+
|
38
|
+
puts 'Please enter your OpenAI API key:'
|
39
|
+
openai_token = STDIN.gets.chomp
|
40
|
+
File.write(credentials_path, "OPENAI_TOKEN=#{openai_token}\n")
|
41
|
+
puts 'Credentials file created successfully!'
|
42
|
+
end
|
43
|
+
|
44
|
+
def run
|
45
|
+
puts 'Running pr-ai-gen...'
|
46
|
+
fetch_diff
|
47
|
+
load_template
|
48
|
+
get_openai_token
|
49
|
+
generate_pr_content
|
50
|
+
print_content
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def parse_options(args)
|
56
|
+
options = { target_branch: 'main', directory_location: File.expand_path("."), command: :run }
|
57
|
+
|
58
|
+
if args[0] == 'init'
|
59
|
+
options[:command] = :init
|
60
|
+
elsif args[0] == 'generate'
|
61
|
+
options[:command] = :run
|
62
|
+
|
63
|
+
if args[1]
|
64
|
+
options[:directory_location] = File.expand_path(args[1])
|
65
|
+
end
|
66
|
+
|
67
|
+
if args[2]
|
68
|
+
local, target = args[2].split(':')
|
69
|
+
options[:local_branch] = local
|
70
|
+
options[:target_branch] = target || options[:target_branch]
|
71
|
+
end
|
72
|
+
else
|
73
|
+
raise Exception.new "Invalid command!"
|
74
|
+
end
|
75
|
+
|
76
|
+
OptionParser.new do |opts|
|
77
|
+
opts.banner = "Usage: pr-ai-gen <directory_location> <branch>:<target-branch=main>"
|
78
|
+
|
79
|
+
opts.on("-h", "--help", "Prints this help") do
|
80
|
+
puts opts
|
81
|
+
exit
|
82
|
+
end
|
83
|
+
|
84
|
+
end.parse!(args)
|
85
|
+
|
86
|
+
options
|
87
|
+
end
|
88
|
+
|
89
|
+
def fetch_diff
|
90
|
+
# Start the ssh-agent in the background
|
91
|
+
`eval $(ssh-agent -s)`
|
92
|
+
|
93
|
+
# Add your SSH private key to the ssh-agent
|
94
|
+
`ssh-add ~/.ssh/id_ed25519`
|
95
|
+
ssh_keys = `ssh-add -l`
|
96
|
+
|
97
|
+
if ssh_keys.include?('No identities')
|
98
|
+
puts 'No SSH keys are added to the ssh-agent.'
|
99
|
+
exit
|
100
|
+
end
|
101
|
+
|
102
|
+
@git_repo = Git.open(@options[:directory_location])
|
103
|
+
@git_repo.fetch
|
104
|
+
@git_repo.checkout(@options[:local_branch])
|
105
|
+
@diff = @git_repo.diff(@options[:target_branch], @options[:local_branch])
|
106
|
+
end
|
107
|
+
|
108
|
+
def load_template
|
109
|
+
template_path = File.join(@options[:directory_location], '.github', 'PULL_REQUEST_TEMPLATE.md')
|
110
|
+
if File.exist?(template_path)
|
111
|
+
@template = File.read(template_path)
|
112
|
+
else
|
113
|
+
@template = "# Default PR Template\n\n## Changes Made\n\nDescribe your changes in detail here."
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def get_openai_token
|
118
|
+
credentials_path = File.expand_path('~/.pr-gem/credentials')
|
119
|
+
if File.exist?(credentials_path)
|
120
|
+
credentials = File.readlines(credentials_path).map(&:strip)
|
121
|
+
@openai_token = credentials.find { |line| line.start_with?('OPENAI_TOKEN=') }
|
122
|
+
raise "OpenAI credentials not found!" unless @openai_token
|
123
|
+
@openai_token = @openai_token.split('=')[1]
|
124
|
+
else
|
125
|
+
raise "OpenAI credentials file not found!"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def generate_pr_content
|
130
|
+
puts "Generating PR content..."
|
131
|
+
|
132
|
+
response = HTTParty.post(
|
133
|
+
"#{OPEN_AI_URL}/chat/completions",
|
134
|
+
headers: {
|
135
|
+
"Content-Type" => "application/json",
|
136
|
+
"Authorization" => "Bearer #{@openai_token}"
|
137
|
+
},
|
138
|
+
body: {
|
139
|
+
model: "gpt-4-turbo-preview",
|
140
|
+
messages: [
|
141
|
+
{
|
142
|
+
role: "user",
|
143
|
+
content: "fill this templete:\n #{@template}\n with the following changes:\n #{@diff.to_s}"
|
144
|
+
},
|
145
|
+
],
|
146
|
+
max_tokens: 1024
|
147
|
+
}.to_json
|
148
|
+
)
|
149
|
+
|
150
|
+
@pr_content = response.dig("choices", 0, "message", "content").strip
|
151
|
+
|
152
|
+
puts "PR content generated successfully!"
|
153
|
+
end
|
154
|
+
|
155
|
+
def print_content
|
156
|
+
puts "PR CONTENT FOLLOWING:"
|
157
|
+
puts "BEGIN-------------------------------------------------------------------------"
|
158
|
+
puts @pr_content
|
159
|
+
puts "---------------------------------------------------------------------------END"
|
160
|
+
end
|
161
|
+
end
|
data/pr_ai_gen.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = "pr_ai_gen"
|
3
|
+
spec.version = "0.1.0"
|
4
|
+
spec.authors = ["Lucas Stoller"]
|
5
|
+
spec.email = ["l.s.stoller@gmail.com"]
|
6
|
+
spec.summary = "A CLI tool to generate pull requests using OpenAI"
|
7
|
+
spec.description = "This tool automates the process of creating pull requests by using OpenAI to generate the content based on the differences between two git branches."
|
8
|
+
spec.homepage = "https://theright.dev"
|
9
|
+
|
10
|
+
spec.files = `git ls-files`.split($/)
|
11
|
+
spec.bindir = "exe"
|
12
|
+
spec.executables = spec.executables = ['pr-ai-gen']
|
13
|
+
spec.require_paths = ["lib"]
|
14
|
+
|
15
|
+
spec.add_dependency "git"
|
16
|
+
spec.add_dependency "openai"
|
17
|
+
spec.add_dependency "octokit"
|
18
|
+
spec.add_dependency "capybara"
|
19
|
+
spec.add_dependency "selenium-webdriver"
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
22
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pr_ai_gen
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lucas Stoller
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-03-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: git
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: openai
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: octokit
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: capybara
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: selenium-webdriver
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '13.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '13.0'
|
111
|
+
description: This tool automates the process of creating pull requests by using OpenAI
|
112
|
+
to generate the content based on the differences between two git branches.
|
113
|
+
email:
|
114
|
+
- l.s.stoller@gmail.com
|
115
|
+
executables:
|
116
|
+
- pr-ai-gen
|
117
|
+
extensions: []
|
118
|
+
extra_rdoc_files: []
|
119
|
+
files:
|
120
|
+
- ".gitignore"
|
121
|
+
- Gemfile
|
122
|
+
- Gemfile.lock
|
123
|
+
- exe/pr-ai-gen
|
124
|
+
- lib/pull_request_ai_generator.rb
|
125
|
+
- pr_ai_gen.gemspec
|
126
|
+
homepage: https://theright.dev
|
127
|
+
licenses: []
|
128
|
+
metadata: {}
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
requirements: []
|
144
|
+
rubygems_version: 3.3.7
|
145
|
+
signing_key:
|
146
|
+
specification_version: 4
|
147
|
+
summary: A CLI tool to generate pull requests using OpenAI
|
148
|
+
test_files: []
|