autogitc 0.1.4 → 0.2.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 +4 -4
- data/bin/autogitc +15 -4
- data/lib/{autogitc.rb → commit_generator.rb} +13 -29
- data/lib/openai_wrapper.rb +27 -0
- data/lib/pr_template_generator.rb +80 -0
- metadata +5 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 31e42a7e24a75eb40f81bebbb8f10736713b09e81eea160c8ec272b4db7f4ac4
         | 
| 4 | 
            +
              data.tar.gz: 2d6baf30747d55b948565d59e4960b09cdc6d34cc9f48c3452377b8e5d294f9d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: fff1a7406f9b8068cc8540292d8ea66de54d18fc264cd6a6753e2c8f51e0c9785fe2a8194d9f618e9786d32cbc6e378c4cbc7b0124559be0335307fba8129eb7
         | 
| 7 | 
            +
              data.tar.gz: 3aad6d08f82d07e339efe31b8bb4051a0c5d127d8993be9f87e75f396904002932c71c006af54deedd51dcf7e70ec6af0e7c26f9f568066f88981b16b595dab3
         | 
    
        data/bin/autogitc
    CHANGED
    
    | @@ -1,8 +1,19 @@ | |
| 1 1 | 
             
            #!/usr/bin/env ruby
         | 
| 2 2 | 
             
            require 'bundler/setup'
         | 
| 3 | 
            -
            require_relative '../lib/ | 
| 3 | 
            +
            require_relative '../lib/commit_generator'
         | 
| 4 | 
            +
            require_relative '../lib/pr_template_generator'
         | 
| 4 5 |  | 
| 5 | 
            -
             | 
| 6 | 
            +
            if ARGV.include?('pr')
         | 
| 7 | 
            +
              base_branch_arg = ARGV.find { |arg| arg.start_with?('--base=') }
         | 
| 8 | 
            +
              base_branch = base_branch_arg ? base_branch_arg.split('=').last : 'main'
         | 
| 9 | 
            +
              puts "Base branch not specified, defaulting to 'main'." if base_branch_arg.nil?
         | 
| 6 10 |  | 
| 7 | 
            -
            puts 'Running  | 
| 8 | 
            -
             | 
| 11 | 
            +
              puts 'Running PR template generator...'
         | 
| 12 | 
            +
              PrTemplateGenerator.main(base_branch: base_branch)
         | 
| 13 | 
            +
            else
         | 
| 14 | 
            +
              no_commit = ARGV.include?('--nocommit') || ARGV.include?('--nc')
         | 
| 15 | 
            +
              must_have_text = ARGV.find { |arg| arg.start_with?('--text=') }&.split('=')&.last
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              puts 'Running autogitc...'
         | 
| 18 | 
            +
              CommitGenerator.main(no_commit: no_commit, must_have_text: must_have_text)
         | 
| 19 | 
            +
            end
         | 
| @@ -1,8 +1,7 @@ | |
| 1 | 
            -
            require 'net/http'
         | 
| 2 1 | 
             
            require 'json'
         | 
| 3 | 
            -
             | 
| 2 | 
            +
            require_relative 'openai_wrapper'
         | 
| 4 3 |  | 
| 5 | 
            -
            module  | 
| 4 | 
            +
            module CommitGenerator
         | 
| 6 5 | 
             
              def self.openai_api_key
         | 
| 7 6 | 
             
                ENV['AUTOGITC_KEY']
         | 
| 8 7 | 
             
              end
         | 
| @@ -15,21 +14,8 @@ module Autogitc | |
| 15 14 | 
             
                `git diff --staged #{file_path}`
         | 
| 16 15 | 
             
              end
         | 
| 17 16 |  | 
| 18 | 
            -
              def self.generate_commit_message(changes_summary)
         | 
| 19 | 
            -
                 | 
| 20 | 
            -
             | 
| 21 | 
            -
                http = Net::HTTP.new(uri.host, uri.port)
         | 
| 22 | 
            -
                http.use_ssl = true
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                request = Net::HTTP::Post.new(
         | 
| 25 | 
            -
                  uri.path, {
         | 
| 26 | 
            -
                    'Content-Type' => 'application/json',
         | 
| 27 | 
            -
                    'Authorization' => "Bearer #{openai_api_key}"
         | 
| 28 | 
            -
                  }
         | 
| 29 | 
            -
                )
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                request.body = {
         | 
| 32 | 
            -
                  model: 'gpt-4o-mini',
         | 
| 17 | 
            +
              def self.generate_commit_message(changes_summary:, must_have_text: nil)
         | 
| 18 | 
            +
                output = OpenAIWrapper.call_api(
         | 
| 33 19 | 
             
                  messages: [
         | 
| 34 20 | 
             
                    {
         | 
| 35 21 | 
             
                      role: 'system',
         | 
| @@ -37,19 +23,14 @@ module Autogitc | |
| 37 23 | 
             
                    },
         | 
| 38 24 | 
             
                    {
         | 
| 39 25 | 
             
                      role: 'user',
         | 
| 40 | 
            -
                      content: "Generate a conventional git commit message limited to 72 characters for the following changes in a JSON format with a key 'commit_message':\n\n#{changes_summary}"
         | 
| 26 | 
            +
                      content: "Generate a conventional git commit message limited to 72 characters for the following changes in a JSON format with a key 'commit_message', ensuring it includes the text: '#{must_have_text}':\n\n#{changes_summary}"
         | 
| 41 27 | 
             
                    }
         | 
| 42 | 
            -
                  ] | 
| 43 | 
            -
             | 
| 44 | 
            -
                 | 
| 45 | 
            -
             | 
| 46 | 
            -
                response = http.request(request)
         | 
| 47 | 
            -
                result = JSON.parse(response.body)
         | 
| 48 | 
            -
                output_text = result.dig('choices', 0, 'message', 'content')
         | 
| 49 | 
            -
                JSON.parse(output_text)['commit_message']
         | 
| 28 | 
            +
                  ]
         | 
| 29 | 
            +
                )
         | 
| 30 | 
            +
                JSON.parse(output)['commit_message']
         | 
| 50 31 | 
             
              end
         | 
| 51 32 |  | 
| 52 | 
            -
              def self.main(no_commit: false)
         | 
| 33 | 
            +
              def self.main(no_commit: false, must_have_text: nil)
         | 
| 53 34 | 
             
                if openai_api_key.nil?
         | 
| 54 35 | 
             
                  puts 'No AUTOGITC_KEY key found in environment variables.'
         | 
| 55 36 | 
             
                  return
         | 
| @@ -67,7 +48,10 @@ module Autogitc | |
| 67 48 | 
             
                  "Changes in #{file}:\n#{diff}\n"
         | 
| 68 49 | 
             
                end.join("\n")
         | 
| 69 50 |  | 
| 70 | 
            -
                commit_message = generate_commit_message( | 
| 51 | 
            +
                commit_message = generate_commit_message(
         | 
| 52 | 
            +
                  changes_summary: changes_summary,
         | 
| 53 | 
            +
                  must_have_text: must_have_text
         | 
| 54 | 
            +
                )
         | 
| 71 55 | 
             
                puts 'Generated commit message:'
         | 
| 72 56 | 
             
                puts commit_message
         | 
| 73 57 |  | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            require 'net/http'
         | 
| 2 | 
            +
            require 'json'
         | 
| 3 | 
            +
            require 'uri'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module OpenAIWrapper
         | 
| 6 | 
            +
              def self.call_api(messages:, is_json_output: true)
         | 
| 7 | 
            +
                uri = URI('https://api.openai.com/v1/chat/completions')
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                http = Net::HTTP.new(uri.host, uri.port)
         | 
| 10 | 
            +
                http.use_ssl = true
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                request = Net::HTTP::Post.new(
         | 
| 13 | 
            +
                  uri.path, {
         | 
| 14 | 
            +
                    'Content-Type' => 'application/json',
         | 
| 15 | 
            +
                    'Authorization' => "Bearer #{ENV['AUTOGITC_KEY']}"
         | 
| 16 | 
            +
                  }
         | 
| 17 | 
            +
                )
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                body = { model: 'gpt-4o-mini', messages: messages }
         | 
| 20 | 
            +
                body.merge!(response_format: { "type": 'json_object' }) if is_json_output
         | 
| 21 | 
            +
                request.body = body.to_json
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                response = http.request(request)
         | 
| 24 | 
            +
                result = JSON.parse(response.body)
         | 
| 25 | 
            +
                result.dig('choices', 0, 'message', 'content')
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,80 @@ | |
| 1 | 
            +
            require 'json'
         | 
| 2 | 
            +
            require_relative 'openai_wrapper'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module PrTemplateGenerator
         | 
| 5 | 
            +
              # refer to https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository
         | 
| 6 | 
            +
              def self.template_paths
         | 
| 7 | 
            +
                filename = 'pull_request_template.md'
         | 
| 8 | 
            +
                [
         | 
| 9 | 
            +
                  File.join(Dir.pwd, filename),
         | 
| 10 | 
            +
                  File.join(Dir.pwd, 'docs', filename),
         | 
| 11 | 
            +
                  File.join(Dir.pwd, '.github', filename)
         | 
| 12 | 
            +
                ]
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def self.template_path_where_file_is_found
         | 
| 16 | 
            +
                template_paths.each do |path|
         | 
| 17 | 
            +
                  return path if File.exist?(path)
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
                nil
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              def self.output_path
         | 
| 23 | 
            +
                File.join(Dir.pwd, "pull_request_template_#{Time.now.strftime('%Y-%m-%d-%H-%M-%S')}.md")
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              def self.branch_name
         | 
| 27 | 
            +
                `git rev-parse --abbrev-ref HEAD`.strip
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              def self.commits(base_branch:)
         | 
| 31 | 
            +
                `git log --oneline #{base_branch}..HEAD`.strip
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              def self.template_content
         | 
| 35 | 
            +
                File.read(template_path_where_file_is_found)
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              def self.generate_filled_template(base_branch:)
         | 
| 39 | 
            +
                output = OpenAIWrapper.call_api(
         | 
| 40 | 
            +
                  messages: [
         | 
| 41 | 
            +
                    {
         | 
| 42 | 
            +
                      role: 'system',
         | 
| 43 | 
            +
                      content: 'You are a helpful assistant that generates filled pull request templates based on provided templates and context.'
         | 
| 44 | 
            +
                    },
         | 
| 45 | 
            +
                    {
         | 
| 46 | 
            +
                      role: 'user',
         | 
| 47 | 
            +
                      content: <<~PROMPT
         | 
| 48 | 
            +
                        Please fill out the following pull request template as closely as possible using the branch name '#{branch_name}' and the following commits:
         | 
| 49 | 
            +
                        #{commits(base_branch: base_branch)}
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                        Template enclosed in ``` below:
         | 
| 52 | 
            +
                        ```
         | 
| 53 | 
            +
                        #{template_content}
         | 
| 54 | 
            +
                        ```
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                        Ensure the output closely resembles the provided template.
         | 
| 57 | 
            +
                        Be succinct in the content.
         | 
| 58 | 
            +
                        Return only the filled template without any additional comments.
         | 
| 59 | 
            +
                      PROMPT
         | 
| 60 | 
            +
                    }
         | 
| 61 | 
            +
                  ],
         | 
| 62 | 
            +
                  is_json_output: false
         | 
| 63 | 
            +
                )
         | 
| 64 | 
            +
                output.strip.gsub(/^```|```$/, '')
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              def self.main(base_branch:)
         | 
| 68 | 
            +
                if template_path_where_file_is_found.nil?
         | 
| 69 | 
            +
                  puts 'Pull request template not found.'
         | 
| 70 | 
            +
                  puts 'Template should be found at:'
         | 
| 71 | 
            +
                  template_paths.each { |path| puts " - #{path}" }
         | 
| 72 | 
            +
                  return
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                filled_template = generate_filled_template(base_branch: base_branch)
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                File.write(output_path, filled_template)
         | 
| 78 | 
            +
                puts "Filled pull request template created at #{output_path}."
         | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: autogitc
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Adrian Goh
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2024-08- | 
| 11 | 
            +
            date: 2024-08-31 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies: []
         | 
| 13 13 | 
             
            description: This gem simplifies the commit process by automatically generating descriptive
         | 
| 14 14 | 
             
              commit messages based on the files that have been added to the Git staging area.
         | 
| @@ -21,7 +21,9 @@ extensions: [] | |
| 21 21 | 
             
            extra_rdoc_files: []
         | 
| 22 22 | 
             
            files:
         | 
| 23 23 | 
             
            - bin/autogitc
         | 
| 24 | 
            -
            - lib/ | 
| 24 | 
            +
            - lib/commit_generator.rb
         | 
| 25 | 
            +
            - lib/openai_wrapper.rb
         | 
| 26 | 
            +
            - lib/pr_template_generator.rb
         | 
| 25 27 | 
             
            homepage: https://github.com/adriangohjw/autogitc
         | 
| 26 28 | 
             
            licenses:
         | 
| 27 29 | 
             
            - MIT
         |