├── .rspec ├── CHANGELOG.md ├── lib ├── commitgpt │ ├── version.rb │ ├── cli.rb │ ├── string.rb │ └── commit_ai.rb └── commitgpt.rb ├── bin └── aicm ├── .gitignore ├── Rakefile ├── Gemfile ├── .rubocop.yml ├── spec ├── spec_helper.rb └── commitgpt_spec.rb ├── .github └── workflows │ └── main.yml ├── LICENSE ├── LICENSE.txt ├── commitgpt.gemspec ├── Gemfile.lock ├── README.md └── CODE_OF_CONDUCT.md /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | --require spec_helper 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [Unreleased] 2 | 3 | ## [0.1.0] - 2023-02-14 4 | 5 | - Initial release 6 | -------------------------------------------------------------------------------- /lib/commitgpt/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module CommitGpt 4 | VERSION = "0.1.2" 5 | end 6 | -------------------------------------------------------------------------------- /bin/aicm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require "commitgpt/cli" 5 | CommitGpt::CLI.start 6 | -------------------------------------------------------------------------------- /lib/commitgpt.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "commitgpt/version" 4 | require_relative "commitgpt/commit_ai" 5 | 6 | module CommitGpt 7 | class Error < StandardError; end 8 | end 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | /coverage/ 5 | /doc/ 6 | /pkg/ 7 | /spec/reports/ 8 | /tmp/ 9 | 10 | # rspec failure tracking 11 | .rspec_status 12 | .idea/** 13 | .DS_Store 14 | commitgpt-*.gem 15 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "bundler/gem_tasks" 4 | require "rspec/core/rake_task" 5 | 6 | RSpec::Core::RakeTask.new(:spec) 7 | 8 | require "rubocop/rake_task" 9 | 10 | RuboCop::RakeTask.new 11 | 12 | task default: %i[spec rubocop] 13 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | # Specify your gem's dependencies in commitgpt.gemspec 6 | gemspec 7 | 8 | gem "httparty" 9 | 10 | gem "rake", "~> 13.0" 11 | 12 | gem "rspec", "~> 3.0" 13 | 14 | gem "rubocop", "~> 1.21" 15 | 16 | gem "thor" 17 | -------------------------------------------------------------------------------- /lib/commitgpt/cli.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "thor" 4 | require "commitgpt/commit_ai" 5 | 6 | module CommitGpt 7 | # CommitGpt CLI 8 | class CLI < Thor 9 | default_task :aicm 10 | 11 | desc "aicm", "AI commits for you!" 12 | def aicm 13 | CommitGpt::CommitAi.new.aicm 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/commitgpt/string.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Open String to add color 4 | class String 5 | def red 6 | "\e[31m#{self}\e[0m" 7 | end 8 | 9 | def green 10 | "\e[32m#{self}\e[0m" 11 | end 12 | 13 | def gray 14 | "\e[90m#{self}\e[0m" 15 | end 16 | 17 | def magenta 18 | "\e[35m#{self}\e[0m" 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | TargetRubyVersion: 2.6 3 | 4 | Style/StringLiterals: 5 | Enabled: true 6 | EnforcedStyle: double_quotes 7 | 8 | Style/StringLiteralsInInterpolation: 9 | Enabled: true 10 | EnforcedStyle: double_quotes 11 | 12 | Layout/LineLength: 13 | Max: 160 14 | 15 | MethodLength: 16 | Max: 20 17 | 18 | Metrics/BlockLength: 19 | Max: 100 -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "commitgpt" 4 | 5 | RSpec.configure do |config| 6 | # Enable flags like --only-failures and --next-failure 7 | config.example_status_persistence_file_path = ".rspec_status" 8 | 9 | # Disable RSpec exposing methods globally on `Module` and `main` 10 | config.disable_monkey_patching! 11 | 12 | config.expect_with :rspec do |c| 13 | c.syntax = :expect 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Ruby 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | pull_request: 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | name: Ruby ${{ matrix.ruby }} 14 | strategy: 15 | matrix: 16 | ruby: 17 | - '3.0.4' 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: Set up Ruby 22 | uses: ruby/setup-ruby@v1 23 | with: 24 | ruby-version: ${{ matrix.ruby }} 25 | bundler-cache: true 26 | - name: Run the default task 27 | run: bundle exec rake 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 ZPVIP 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 NONINFRINGEMENT. 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 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Peng Zhang 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 13 | all 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 NONINFRINGEMENT. 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /spec/commitgpt_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | require "commitgpt/commit_ai" 5 | 6 | RSpec.describe CommitGpt do 7 | let(:commit_ai) { CommitGpt::CommitAi.new } 8 | 9 | it "has a version number" do 10 | expect(CommitGpt::VERSION).not_to be nil 11 | end 12 | 13 | describe "aicm" do 14 | it "gets commit text from OpenAI API" do 15 | allow(HTTParty).to receive(:post).and_return( 16 | { "id" => "cmpl-7joXJpCMcd0620evfesv8BGCXXX99", 17 | "object" => "text_completion", 18 | "created" => 1_676_409_742, 19 | "model" => "text-davinci-003", 20 | "choices" => [ 21 | { "text" => "Add AiCommit module to generate AI-generated commit messages.", 22 | "index" => 0, 23 | "logprobs" => nil, 24 | "finish_reason" => "stop" } 25 | ], 26 | "usage" => { "prompt_tokens" => 2856, "completion_tokens" => 13, "total_tokens" => 2869 } } 27 | ) 28 | expect(commit_ai.send(:message)).to eq("Add AiCommit module to generate AI-generated commit messages.") 29 | end 30 | end 31 | 32 | it "gets no commit text from OpenAI API" do 33 | allow(HTTParty).to receive(:post).and_return( 34 | { 35 | "error" => 36 | { 37 | "message" => "The server had an error while processing your request. Sorry about that!", 38 | "type" => "server_error", 39 | "param" => nil, 40 | "code" => nil 41 | } 42 | } 43 | ) 44 | expect(commit_ai.send(:message)).to eq(nil) 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /commitgpt.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "lib/commitgpt/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "commitgpt" 7 | spec.version = CommitGpt::VERSION 8 | spec.authors = ["Peng Zhang"] 9 | spec.email = ["zpregister@gmail.com"] 10 | 11 | spec.summary = "A CLI AI that writes git commit messages for you." 12 | spec.description = "A CLI that writes your git commit messages for you with AI. Never write a commit message again." 13 | spec.homepage = "https://github.com/ZPVIP/commitgpt" 14 | spec.license = "MIT" 15 | spec.required_ruby_version = ">= 2.6.0" 16 | spec.metadata["homepage_uri"] = spec.homepage 17 | spec.metadata["source_code_uri"] = spec.homepage 18 | spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md" 19 | 20 | # Specify which files should be added to the gem when it is released. 21 | # The `git ls-files -z` loads the files in the RubyGem that have been added into git. 22 | spec.files = Dir.chdir(File.expand_path(__dir__)) do 23 | `git ls-files -z`.split("\x0").reject do |f| 24 | (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)}) 25 | end 26 | end 27 | spec.bindir = "bin" 28 | spec.executables = spec.files.grep(%r{\Abin/}) { |f| File.basename(f) } 29 | spec.require_paths = ["lib"] 30 | 31 | # Uncomment to register a new dependency of your gem 32 | spec.add_dependency "httparty", "~> 0.18" 33 | spec.add_dependency "thor", "~> 1.2" 34 | 35 | # For more information and examples about making a new gem, checkout our 36 | # guide at: https://bundler.io/guides/creating_gem.html 37 | end 38 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | commitgpt (0.1.2) 5 | httparty (~> 0.18) 6 | thor (~> 1.2) 7 | 8 | GEM 9 | remote: https://rubygems.org/ 10 | specs: 11 | ast (2.4.2) 12 | diff-lcs (1.5.0) 13 | httparty (0.21.0) 14 | mini_mime (>= 1.0.0) 15 | multi_xml (>= 0.5.2) 16 | mini_mime (1.1.2) 17 | multi_xml (0.6.0) 18 | parallel (1.22.1) 19 | parser (3.1.2.0) 20 | ast (~> 2.4.1) 21 | rainbow (3.1.1) 22 | rake (13.0.6) 23 | regexp_parser (2.6.1) 24 | rexml (3.2.5) 25 | rspec (3.12.0) 26 | rspec-core (~> 3.12.0) 27 | rspec-expectations (~> 3.12.0) 28 | rspec-mocks (~> 3.12.0) 29 | rspec-core (3.12.0) 30 | rspec-support (~> 3.12.0) 31 | rspec-expectations (3.12.0) 32 | diff-lcs (>= 1.2.0, < 2.0) 33 | rspec-support (~> 3.12.0) 34 | rspec-mocks (3.12.0) 35 | diff-lcs (>= 1.2.0, < 2.0) 36 | rspec-support (~> 3.12.0) 37 | rspec-support (3.12.0) 38 | rubocop (1.29.1) 39 | parallel (~> 1.10) 40 | parser (>= 3.1.0.0) 41 | rainbow (>= 2.2.2, < 4.0) 42 | regexp_parser (>= 1.8, < 3.0) 43 | rexml (>= 3.2.5, < 4.0) 44 | rubocop-ast (>= 1.17.0, < 2.0) 45 | ruby-progressbar (~> 1.7) 46 | unicode-display_width (>= 1.4.0, < 3.0) 47 | rubocop-ast (1.17.0) 48 | parser (>= 3.1.1.0) 49 | ruby-progressbar (1.11.0) 50 | thor (1.2.1) 51 | unicode-display_width (1.8.0) 52 | 53 | PLATFORMS 54 | arm64-darwin-21 55 | x86_64-darwin-22 56 | 57 | DEPENDENCIES 58 | commitgpt! 59 | httparty 60 | rake (~> 13.0) 61 | rspec (~> 3.0) 62 | rubocop (~> 1.21) 63 | thor 64 | 65 | BUNDLED WITH 66 | 2.4.4 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
A CLI that writes your git commit messages for you with AI. Never write a commit message again.
6 |