fuel-cli 0.0.2
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 +15 -0
 - data/.gitignore +22 -0
 - data/Gemfile +4 -0
 - data/LICENSE.txt +22 -0
 - data/README.md +29 -0
 - data/Rakefile +6 -0
 - data/bin/fuel +4 -0
 - data/bin/gerrit +4 -0
 - data/bin/jenkins +4 -0
 - data/bin/jira +4 -0
 - data/fuel-cli.gemspec +30 -0
 - data/lib/fuel/cli/base.rb +27 -0
 - data/lib/fuel/cli/gerrit.rb +328 -0
 - data/lib/fuel/cli/gerrit_common.rb +21 -0
 - data/lib/fuel/cli/jenkins.rb +89 -0
 - data/lib/fuel/cli/jira.rb +86 -0
 - data/lib/fuel/cli/main.rb +86 -0
 - data/lib/fuel/cli/patches.rb +13 -0
 - data/lib/fuel/cli/version.rb +5 -0
 - data/lib/fuel/cli.rb +13 -0
 - data/lib/fuel/util/config.rb +54 -0
 - data/lib/fuel/util/json_parser.rb +15 -0
 - metadata +154 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            !binary "U0hBMQ==":
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: !binary |-
         
     | 
| 
      
 4 
     | 
    
         
            +
                ZDBlMjU0MmNiZjIyOTc2NWYzZjQwYjNkNDBiNzBlYjgyMDMxN2MzNQ==
         
     | 
| 
      
 5 
     | 
    
         
            +
              data.tar.gz: !binary |-
         
     | 
| 
      
 6 
     | 
    
         
            +
                ZWZkMDVmMjZkOTRiZjRiMTk1MmViY2YxZjRhZDNiMjIwNThjMjUxZA==
         
     | 
| 
      
 7 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 8 
     | 
    
         
            +
              metadata.gz: !binary |-
         
     | 
| 
      
 9 
     | 
    
         
            +
                NDFjYWRjYzIyMjlhOGJmOGRmZDlmZGY1M2M1M2E0MzI1MDNkOGIwYzQxYjNl
         
     | 
| 
      
 10 
     | 
    
         
            +
                YTY2MmZmMzcyOWFkNTY1YWQ1NzgxZTYwNmQ0NmY0NjY5ZDkwMGIwZDVmNDIz
         
     | 
| 
      
 11 
     | 
    
         
            +
                MGZkN2VhM2IyNGQ0ZGRmNTJlZDU3MWViNTE2ZjE2YzAzOWY2ODM=
         
     | 
| 
      
 12 
     | 
    
         
            +
              data.tar.gz: !binary |-
         
     | 
| 
      
 13 
     | 
    
         
            +
                Mjg2YWIyYjVmZDMxOTRmMzRmZDUxNmQyMWI2MTA1MzZhNGNlMzNkMzgzMjgz
         
     | 
| 
      
 14 
     | 
    
         
            +
                M2QwNThlMzkwMTNkNGJhZTM5OWQ1M2UxNGNjZjE3MDIwN2I0Y2Y3NzQ4OTY0
         
     | 
| 
      
 15 
     | 
    
         
            +
                MWRkOTIxNDFiNjY2YzlmOTA5MDE5NWY0OTZmNjI4Y2ZiNGEzZjQ=
         
     | 
    
        data/.gitignore
    ADDED
    
    | 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            *.gem
         
     | 
| 
      
 2 
     | 
    
         
            +
            *.rbc
         
     | 
| 
      
 3 
     | 
    
         
            +
            .bundle
         
     | 
| 
      
 4 
     | 
    
         
            +
            .config
         
     | 
| 
      
 5 
     | 
    
         
            +
            .yardoc
         
     | 
| 
      
 6 
     | 
    
         
            +
            Gemfile.lock
         
     | 
| 
      
 7 
     | 
    
         
            +
            InstalledFiles
         
     | 
| 
      
 8 
     | 
    
         
            +
            _yardoc
         
     | 
| 
      
 9 
     | 
    
         
            +
            coverage
         
     | 
| 
      
 10 
     | 
    
         
            +
            doc/
         
     | 
| 
      
 11 
     | 
    
         
            +
            lib/bundler/man
         
     | 
| 
      
 12 
     | 
    
         
            +
            pkg
         
     | 
| 
      
 13 
     | 
    
         
            +
            rdoc
         
     | 
| 
      
 14 
     | 
    
         
            +
            spec/reports
         
     | 
| 
      
 15 
     | 
    
         
            +
            test/tmp
         
     | 
| 
      
 16 
     | 
    
         
            +
            test/version_tmp
         
     | 
| 
      
 17 
     | 
    
         
            +
            tmp
         
     | 
| 
      
 18 
     | 
    
         
            +
            *.bundle
         
     | 
| 
      
 19 
     | 
    
         
            +
            *.so
         
     | 
| 
      
 20 
     | 
    
         
            +
            *.o
         
     | 
| 
      
 21 
     | 
    
         
            +
            *.a
         
     | 
| 
      
 22 
     | 
    
         
            +
            mkmf.log
         
     | 
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE.txt
    ADDED
    
    | 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) 2014 Alex Zherdev
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            MIT License
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining
         
     | 
| 
      
 6 
     | 
    
         
            +
            a copy of this software and associated documentation files (the
         
     | 
| 
      
 7 
     | 
    
         
            +
            "Software"), to deal in the Software without restriction, including
         
     | 
| 
      
 8 
     | 
    
         
            +
            without limitation the rights to use, copy, modify, merge, publish,
         
     | 
| 
      
 9 
     | 
    
         
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         
     | 
| 
      
 10 
     | 
    
         
            +
            permit persons to whom the Software is furnished to do so, subject to
         
     | 
| 
      
 11 
     | 
    
         
            +
            the following conditions:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be
         
     | 
| 
      
 14 
     | 
    
         
            +
            included in all copies or substantial portions of the Software.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         
     | 
| 
      
 17 
     | 
    
         
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         
     | 
| 
      
 18 
     | 
    
         
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         
     | 
| 
      
 19 
     | 
    
         
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         
     | 
| 
      
 20 
     | 
    
         
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         
     | 
| 
      
 21 
     | 
    
         
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         
     | 
| 
      
 22 
     | 
    
         
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Fuel::Cli
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            TODO: Write a gem description
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Add this line to your application's Gemfile:
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                gem 'fuel-cli'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            And then execute:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                $ bundle
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            Or install it yourself as:
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                $ gem install fuel-cli
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            ## Usage
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            TODO: Write usage instructions here
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            ## Contributing
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            1. Fork it ( https://github.com/[my-github-username]/fuel-cli/fork )
         
     | 
| 
      
 26 
     | 
    
         
            +
            2. Create your feature branch (`git checkout -b my-new-feature`)
         
     | 
| 
      
 27 
     | 
    
         
            +
            3. Commit your changes (`git commit -am 'Add some feature'`)
         
     | 
| 
      
 28 
     | 
    
         
            +
            4. Push to the branch (`git push origin my-new-feature`)
         
     | 
| 
      
 29 
     | 
    
         
            +
            5. Create a new Pull Request
         
     | 
    
        data/Rakefile
    ADDED
    
    
    
        data/bin/fuel
    ADDED
    
    
    
        data/bin/gerrit
    ADDED
    
    
    
        data/bin/jenkins
    ADDED
    
    
    
        data/bin/jira
    ADDED
    
    
    
        data/fuel-cli.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # coding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            lib = File.expand_path('../lib', __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'fuel/cli/version'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 7 
     | 
    
         
            +
              spec.name          = "fuel-cli"
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.version       = Fuel::CLI::VERSION
         
     | 
| 
      
 9 
     | 
    
         
            +
              spec.authors       = ["Alex Zherdev"]
         
     | 
| 
      
 10 
     | 
    
         
            +
              spec.email         = ["azherdev@rocketfuel.com"]
         
     | 
| 
      
 11 
     | 
    
         
            +
              spec.summary       = %q{Simple set of command-line tools to aid in Fuel dev process.}
         
     | 
| 
      
 12 
     | 
    
         
            +
              spec.description   = %q{}
         
     | 
| 
      
 13 
     | 
    
         
            +
              spec.homepage      = ""
         
     | 
| 
      
 14 
     | 
    
         
            +
              spec.license       = "MIT"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              spec.files         = `git ls-files -z`.split("\x0")
         
     | 
| 
      
 17 
     | 
    
         
            +
              spec.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
         
     | 
| 
      
 18 
     | 
    
         
            +
              spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
         
     | 
| 
      
 19 
     | 
    
         
            +
              spec.require_paths = ["lib"]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              spec.post_install_message = "\e[36m\e[1mWelcome, Fuel developer! Type \"fuel setup\" to get started.\e[0m"
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              spec.add_dependency "thor"
         
     | 
| 
      
 24 
     | 
    
         
            +
              spec.add_dependency "httparty"
         
     | 
| 
      
 25 
     | 
    
         
            +
              spec.add_dependency "jenkins_api_client"
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              spec.add_development_dependency "bundler", "~> 1.6"
         
     | 
| 
      
 28 
     | 
    
         
            +
              spec.add_development_dependency "rake"
         
     | 
| 
      
 29 
     | 
    
         
            +
              spec.add_development_dependency "debugger"
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Fuel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module CLI
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Base < Thor
         
     | 
| 
      
 4 
     | 
    
         
            +
                  include Fuel::Util
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  include HTTParty
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def commit_message
         
     | 
| 
      
 11 
     | 
    
         
            +
                    `git log -1 --pretty=%B`
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def fetch_change_id_or_fail
         
     | 
| 
      
 15 
     | 
    
         
            +
                    change_id = commit_message =~ /Change-Id: (.*)/ && $1
         
     | 
| 
      
 16 
     | 
    
         
            +
                    change_id or raise Thor::Error, set_color("No appropriate commit found at HEAD", :red)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def set_credentials(user, user_keys, password_keys)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    password = ask("Password:", echo: false)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    Config.set(*user_keys, user)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    Config.set(*password_keys, password)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    puts
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,328 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'time'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'cgi'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'fileutils'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'base64'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Fuel
         
     | 
| 
      
 7 
     | 
    
         
            +
              module CLI
         
     | 
| 
      
 8 
     | 
    
         
            +
                class Gerrit < Base
         
     | 
| 
      
 9 
     | 
    
         
            +
                  include GerritCommon
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  package_name "gerrit"
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  headers "Content-Type" => "application/json"
         
     | 
| 
      
 14 
     | 
    
         
            +
                  digest_auth Config.get('gerrit', 'user'), Config.get('gerrit', 'password')
         
     | 
| 
      
 15 
     | 
    
         
            +
                  parser GerritJsonParser
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  desc "status", "Show a brief overview of the current gerrit status"
         
     | 
| 
      
 18 
     | 
    
         
            +
                  def status
         
     | 
| 
      
 19 
     | 
    
         
            +
                    change_id = 'Ia8b172edcedcef7856b4d5fa7aee9e58649abe75'#fetch_change_id_or_fail
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    result = self.class.get(changes_endpoint(change_id, "?o=CURRENT_REVISION")).parsed_response
         
     | 
| 
      
 22 
     | 
    
         
            +
                    current_rev = result['current_revision']
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    say result["subject"], :bold
         
     | 
| 
      
 25 
     | 
    
         
            +
                    table = [["Owner", result["owner"]["name"]]]
         
     | 
| 
      
 26 
     | 
    
         
            +
                    table << ["Updated", format_time(result["updated"])]
         
     | 
| 
      
 27 
     | 
    
         
            +
                    table << ["Status", result["status"]]
         
     | 
| 
      
 28 
     | 
    
         
            +
                    table << ["Ref", gerrit_ref(result)]
         
     | 
| 
      
 29 
     | 
    
         
            +
                    print_table table
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    result = fetch_comments(change_id, current_rev)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    print_comments_info(result)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    puts
         
     | 
| 
      
 34 
     | 
    
         
            +
                    result = self.class.get(reviewers_endpoint(change_id)).parsed_response
         
     | 
| 
      
 35 
     | 
    
         
            +
                    table = result.map { |row| format_row(row) }
         
     | 
| 
      
 36 
     | 
    
         
            +
                    table.unshift(["Reviewer", "CR", "QA", "V"])
         
     | 
| 
      
 37 
     | 
    
         
            +
                    print_table table
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  desc "open", "Open Gerrit in your browser"
         
     | 
| 
      
 41 
     | 
    
         
            +
                  def open
         
     | 
| 
      
 42 
     | 
    
         
            +
                    `open #{gerrit_change_url}`
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  desc "review-add USER[, USER, ...]", "Add reviewer(s) to the gerrit"
         
     | 
| 
      
 46 
     | 
    
         
            +
                  def review_add(*emails_or_aliases)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    change_id = fetch_change_id_or_fail
         
     | 
| 
      
 48 
     | 
    
         
            +
                    emails_or_aliases.each do |value|
         
     | 
| 
      
 49 
     | 
    
         
            +
                      emails = Array(to_email(value))
         
     | 
| 
      
 50 
     | 
    
         
            +
                      if emails.empty?
         
     | 
| 
      
 51 
     | 
    
         
            +
                        say "No email found for alias #{value}; reviewer not added", :yellow
         
     | 
| 
      
 52 
     | 
    
         
            +
                        next
         
     | 
| 
      
 53 
     | 
    
         
            +
                      end
         
     | 
| 
      
 54 
     | 
    
         
            +
                      emails.each do |email|
         
     | 
| 
      
 55 
     | 
    
         
            +
                        result = self.class.post(reviewers_endpoint(change_id), body: { reviewer: email }.to_json).parsed_response
         
     | 
| 
      
 56 
     | 
    
         
            +
                      end
         
     | 
| 
      
 57 
     | 
    
         
            +
                    end
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  desc "alias EMAIL [ALIAS]", "Add an alias or show all existing aliases for the given email"
         
     | 
| 
      
 61 
     | 
    
         
            +
                  def alias(email, alias_name = nil)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    if alias_name
         
     | 
| 
      
 63 
     | 
    
         
            +
                      Config.set('gerrit', 'aliases', alias_name, email)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    else
         
     | 
| 
      
 65 
     | 
    
         
            +
                      aliases = Config.get('gerrit-aliases') || {}
         
     | 
| 
      
 66 
     | 
    
         
            +
                      aliases_found = aliases.map { |k, v| v == email ? k : nil }.compact
         
     | 
| 
      
 67 
     | 
    
         
            +
                      if aliases_found.empty?
         
     | 
| 
      
 68 
     | 
    
         
            +
                        say "No aliases created for #{email}", :yellow
         
     | 
| 
      
 69 
     | 
    
         
            +
                      else
         
     | 
| 
      
 70 
     | 
    
         
            +
                        say "Aliases for #{email}: #{aliases_found.join("; ")}"
         
     | 
| 
      
 71 
     | 
    
         
            +
                      end
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  desc "auth USER", "Store authentication information for Gerrit"
         
     | 
| 
      
 76 
     | 
    
         
            +
                  def auth(user)
         
     | 
| 
      
 77 
     | 
    
         
            +
                    set_credentials(user, ['gerrit', 'user'], ['gerrit', 'password'])
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  desc "submit", "Submit the current change"
         
     | 
| 
      
 81 
     | 
    
         
            +
                  def submit
         
     | 
| 
      
 82 
     | 
    
         
            +
                    change_id = fetch_change_id_or_fail
         
     | 
| 
      
 83 
     | 
    
         
            +
                    result = self.class.post(changes_endpoint(change_id, 'submit'), body: { wait_for_merge: true }.to_json)
         
     | 
| 
      
 84 
     | 
    
         
            +
                    puts result.code
         
     | 
| 
      
 85 
     | 
    
         
            +
                    puts result.parsed_response.inspect
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  option :message, :aliases => '-m'
         
     | 
| 
      
 89 
     | 
    
         
            +
                  desc "abandon", "Abandon the current change"
         
     | 
| 
      
 90 
     | 
    
         
            +
                  def abandon
         
     | 
| 
      
 91 
     | 
    
         
            +
                    change_id = fetch_change_id_or_fail
         
     | 
| 
      
 92 
     | 
    
         
            +
                    params = options['message'] ? { body: { message: options['message'] }.to_json } : {}
         
     | 
| 
      
 93 
     | 
    
         
            +
                    result = self.class.post(changes_endpoint(change_id, 'abandon'), params).parsed_response
         
     | 
| 
      
 94 
     | 
    
         
            +
                    puts result.inspect
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                  option :message, :aliases => '-m'
         
     | 
| 
      
 98 
     | 
    
         
            +
                  desc "restore", "Restore the current change"
         
     | 
| 
      
 99 
     | 
    
         
            +
                  def restore
         
     | 
| 
      
 100 
     | 
    
         
            +
                    change_id = fetch_change_id_or_fail
         
     | 
| 
      
 101 
     | 
    
         
            +
                    params = options['message'] ? { body: { message: options['message'] }.to_json } : {}
         
     | 
| 
      
 102 
     | 
    
         
            +
                    result = self.class.post(changes_endpoint(change_id, 'restore'), params).parsed_response
         
     | 
| 
      
 103 
     | 
    
         
            +
                    puts result.inspect
         
     | 
| 
      
 104 
     | 
    
         
            +
                  end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                  desc "rebase", "Rebase the current change"
         
     | 
| 
      
 107 
     | 
    
         
            +
                  def rebase
         
     | 
| 
      
 108 
     | 
    
         
            +
                    change_id = fetch_change_id_or_fail
         
     | 
| 
      
 109 
     | 
    
         
            +
                    result = self.class.post(changes_endpoint(change_id, "rebase"))
         
     | 
| 
      
 110 
     | 
    
         
            +
                    if result.response.code == "409"
         
     | 
| 
      
 111 
     | 
    
         
            +
                      say "Rebase failed, conflicts found", :red
         
     | 
| 
      
 112 
     | 
    
         
            +
                    else
         
     | 
| 
      
 113 
     | 
    
         
            +
                      say "Rebased successfully", :green
         
     | 
| 
      
 114 
     | 
    
         
            +
                    end
         
     | 
| 
      
 115 
     | 
    
         
            +
                  end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                  desc "checkout USER", "Pulls the latest patchset by the given user for local QA"
         
     | 
| 
      
 118 
     | 
    
         
            +
                  def checkout(email_or_alias)
         
     | 
| 
      
 119 
     | 
    
         
            +
                    email = to_email(email_or_alias)
         
     | 
| 
      
 120 
     | 
    
         
            +
                    say "Group aliases are not supported", :red and return if email.is_a?(Array)
         
     | 
| 
      
 121 
     | 
    
         
            +
                    result = self.class.get(changes_endpoint(nil, "?q=status:open+owner:#{email}&n=1&o=CURRENT_REVISION&o=DOWNLOAD_COMMANDS")).parsed_response
         
     | 
| 
      
 122 
     | 
    
         
            +
                    say "No open changes found for #{email_or_alias}", :yellow and return if result.empty?
         
     | 
| 
      
 123 
     | 
    
         
            +
                    current_rev = result[0]['current_revision']
         
     | 
| 
      
 124 
     | 
    
         
            +
                    command = result[0]['revisions'][current_rev]['fetch']['ssh']['commands']['Checkout']
         
     | 
| 
      
 125 
     | 
    
         
            +
                    `#{command}`
         
     | 
| 
      
 126 
     | 
    
         
            +
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                  option :message, :aliases => '-m'
         
     | 
| 
      
 129 
     | 
    
         
            +
                  desc "qa VOTE", "Put a QA mark on the patch currently checked out"
         
     | 
| 
      
 130 
     | 
    
         
            +
                  def qa(vote)
         
     | 
| 
      
 131 
     | 
    
         
            +
                    submit_review('QA-Test-Passed', vote)
         
     | 
| 
      
 132 
     | 
    
         
            +
                  end
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                  option :message, :aliases => '-m'
         
     | 
| 
      
 135 
     | 
    
         
            +
                  desc "cr VOTE", "Put a Code Review mark on the patch currently checked out"
         
     | 
| 
      
 136 
     | 
    
         
            +
                  def cr(vote)
         
     | 
| 
      
 137 
     | 
    
         
            +
                    submit_review('Code-Review', vote)
         
     | 
| 
      
 138 
     | 
    
         
            +
                  end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                  desc "comments FILE", "View the file with comments"
         
     | 
| 
      
 141 
     | 
    
         
            +
                  def comments(file)
         
     | 
| 
      
 142 
     | 
    
         
            +
                    comments, lines = comments_for_file(file)
         
     | 
| 
      
 143 
     | 
    
         
            +
                    extra_lines = 0
         
     | 
| 
      
 144 
     | 
    
         
            +
                    comments.each do |c|
         
     | 
| 
      
 145 
     | 
    
         
            +
                      line = c['line'] + extra_lines
         
     | 
| 
      
 146 
     | 
    
         
            +
                      comment_lines = format_comment(c)
         
     | 
| 
      
 147 
     | 
    
         
            +
                      lines.insert(line, *comment_lines)
         
     | 
| 
      
 148 
     | 
    
         
            +
                      extra_lines += comment_lines.size
         
     | 
| 
      
 149 
     | 
    
         
            +
                    end
         
     | 
| 
      
 150 
     | 
    
         
            +
                    exec("printf #{lines.join('\n').inspect} | less -F -X -R")
         
     | 
| 
      
 151 
     | 
    
         
            +
                  end
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                  desc "respond FILE", "Look through the comments and respond to them"
         
     | 
| 
      
 154 
     | 
    
         
            +
                  def respond(file)
         
     | 
| 
      
 155 
     | 
    
         
            +
                    comments, lines, change_id, revision_id = comments_for_file(file)
         
     | 
| 
      
 156 
     | 
    
         
            +
                    commented_on = {}
         
     | 
| 
      
 157 
     | 
    
         
            +
                    comments_for_lines = comments.inject({}) do |h, c|
         
     | 
| 
      
 158 
     | 
    
         
            +
                      h[c['line']] ||= []
         
     | 
| 
      
 159 
     | 
    
         
            +
                      h[c['line']] << c
         
     | 
| 
      
 160 
     | 
    
         
            +
                      h
         
     | 
| 
      
 161 
     | 
    
         
            +
                    end
         
     | 
| 
      
 162 
     | 
    
         
            +
                    comments_to_post = comments_for_lines.map do |line, cc|
         
     | 
| 
      
 163 
     | 
    
         
            +
                      next if cc.all? { |c| c['author']['username'] != gerrit_user }
         
     | 
| 
      
 164 
     | 
    
         
            +
                      system 'tput smcup'
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                      line_in_array = line - 1
         
     | 
| 
      
 167 
     | 
    
         
            +
                      first_line = [0, line_in_array - 4].max
         
     | 
| 
      
 168 
     | 
    
         
            +
                      if first_line == line_in_array
         
     | 
| 
      
 169 
     | 
    
         
            +
                        say "Line #{line}:", :bold
         
     | 
| 
      
 170 
     | 
    
         
            +
                      else
         
     | 
| 
      
 171 
     | 
    
         
            +
                        say "Lines #{first_line + 1}-#{line}:", :bold
         
     | 
| 
      
 172 
     | 
    
         
            +
                      end
         
     | 
| 
      
 173 
     | 
    
         
            +
                      say lines[first_line..line_in_array].join("\n")
         
     | 
| 
      
 174 
     | 
    
         
            +
                      cc.each do |c|
         
     | 
| 
      
 175 
     | 
    
         
            +
                        say format_comment(c).join("\n")
         
     | 
| 
      
 176 
     | 
    
         
            +
                      end
         
     | 
| 
      
 177 
     | 
    
         
            +
                      reply = ask "Reply on this line (press enter to skip):"
         
     | 
| 
      
 178 
     | 
    
         
            +
                      system 'tput rmcup'
         
     | 
| 
      
 179 
     | 
    
         
            +
                      next if reply.strip.empty?
         
     | 
| 
      
 180 
     | 
    
         
            +
                      { line: line, message: reply }
         
     | 
| 
      
 181 
     | 
    
         
            +
                    end.compact
         
     | 
| 
      
 182 
     | 
    
         
            +
                    say 'No comments to respond to!', :green and return if comments_to_post.empty?
         
     | 
| 
      
 183 
     | 
    
         
            +
                    puts comments_to_post.inspect
         
     | 
| 
      
 184 
     | 
    
         
            +
                    result = self.class.post(revisions_endpoint(change_id, revision_id, 'review'), body: { comments: { file => comments_to_post } }.to_json).parsed_response
         
     | 
| 
      
 185 
     | 
    
         
            +
                    puts result.inspect
         
     | 
| 
      
 186 
     | 
    
         
            +
                  end
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
                  no_commands do
         
     | 
| 
      
 189 
     | 
    
         
            +
                    def gerrit_change_url
         
     | 
| 
      
 190 
     | 
    
         
            +
                      change_id = fetch_change_id_or_fail
         
     | 
| 
      
 191 
     | 
    
         
            +
                      result = self.class.get(changes_endpoint(change_id)).parsed_response
         
     | 
| 
      
 192 
     | 
    
         
            +
                      "#{gerrit_url}/#{result['_number']}"
         
     | 
| 
      
 193 
     | 
    
         
            +
                    end
         
     | 
| 
      
 194 
     | 
    
         
            +
                  end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                  private
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
                  def format_comment(c)
         
     | 
| 
      
 199 
     | 
    
         
            +
                    msg = c['message'].gsub("\n\n", "\n")
         
     | 
| 
      
 200 
     | 
    
         
            +
                    date = format_time(c['updated'])
         
     | 
| 
      
 201 
     | 
    
         
            +
                    author = set_color(c['author']['name'], :yellow)
         
     | 
| 
      
 202 
     | 
    
         
            +
                    prefix = "[#{date}] #{author}: "
         
     | 
| 
      
 203 
     | 
    
         
            +
                    comment_lines = msg.split("\n")
         
     | 
| 
      
 204 
     | 
    
         
            +
                    comment_lines[0].prepend prefix
         
     | 
| 
      
 205 
     | 
    
         
            +
                    comment_lines[1..-1].each do |cline|
         
     | 
| 
      
 206 
     | 
    
         
            +
                      cline.prepend " " * prefix.size
         
     | 
| 
      
 207 
     | 
    
         
            +
                    end
         
     | 
| 
      
 208 
     | 
    
         
            +
                    comment_lines
         
     | 
| 
      
 209 
     | 
    
         
            +
                  end
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
      
 211 
     | 
    
         
            +
                  def submit_review(label, vote)
         
     | 
| 
      
 212 
     | 
    
         
            +
                    change_id = fetch_change_id_or_fail
         
     | 
| 
      
 213 
     | 
    
         
            +
                    result = self.class.get(changes_endpoint(change_id, "?o=CURRENT_REVISION")).parsed_response
         
     | 
| 
      
 214 
     | 
    
         
            +
                    current_rev = result['current_revision']
         
     | 
| 
      
 215 
     | 
    
         
            +
                    body = { labels: { label => vote.to_i } }
         
     | 
| 
      
 216 
     | 
    
         
            +
                    message = options['message'] || run_editor.gsub("\n", "\n\n")
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
                    body[:message] = message
         
     | 
| 
      
 219 
     | 
    
         
            +
                    result = self.class.post(revisions_endpoint(change_id, current_rev, 'review'), body: body.to_json).parsed_response
         
     | 
| 
      
 220 
     | 
    
         
            +
                  end
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
                  def to_email(value)
         
     | 
| 
      
 223 
     | 
    
         
            +
                    is_email?(value) ? value : emails_for_alias(value)
         
     | 
| 
      
 224 
     | 
    
         
            +
                  end
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
                  def is_email?(value)
         
     | 
| 
      
 227 
     | 
    
         
            +
                    !!value.index('@')
         
     | 
| 
      
 228 
     | 
    
         
            +
                  end
         
     | 
| 
      
 229 
     | 
    
         
            +
             
     | 
| 
      
 230 
     | 
    
         
            +
                  def emails_for_alias(alias_name)
         
     | 
| 
      
 231 
     | 
    
         
            +
                    aliases = Config.get('gerrit-aliases', alias_name)
         
     | 
| 
      
 232 
     | 
    
         
            +
                  end
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
                  def format_row(row)
         
     | 
| 
      
 235 
     | 
    
         
            +
                    result = [row["name"]]
         
     | 
| 
      
 236 
     | 
    
         
            +
                    approvals = row["approvals"]
         
     | 
| 
      
 237 
     | 
    
         
            +
                    result << format_review(approvals && approvals["Code-Review"])
         
     | 
| 
      
 238 
     | 
    
         
            +
                    result << format_verified(approvals && approvals["QA-Test-Passed"])
         
     | 
| 
      
 239 
     | 
    
         
            +
                    result << format_verified(approvals && approvals["Verified"])
         
     | 
| 
      
 240 
     | 
    
         
            +
                    result
         
     | 
| 
      
 241 
     | 
    
         
            +
                  end
         
     | 
| 
      
 242 
     | 
    
         
            +
             
     | 
| 
      
 243 
     | 
    
         
            +
                  def format_review(cell)
         
     | 
| 
      
 244 
     | 
    
         
            +
                    characters = { "0" => " ", "-1" => set_color("-1", :red), "+1" => set_color("+1", :green), "+2" => tick }
         
     | 
| 
      
 245 
     | 
    
         
            +
                    characters[(cell || "").strip]
         
     | 
| 
      
 246 
     | 
    
         
            +
                  end
         
     | 
| 
      
 247 
     | 
    
         
            +
             
     | 
| 
      
 248 
     | 
    
         
            +
                  def format_verified(cell)
         
     | 
| 
      
 249 
     | 
    
         
            +
                    characters = { "0" => " ", "-1" => cross, "+1" => tick }
         
     | 
| 
      
 250 
     | 
    
         
            +
                    characters[(cell || "").strip]
         
     | 
| 
      
 251 
     | 
    
         
            +
                  end
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
      
 253 
     | 
    
         
            +
                  def format_time(time)
         
     | 
| 
      
 254 
     | 
    
         
            +
                    Time.parse(time + " UTC").getlocal.strftime("%b %-d %l:%M %p")
         
     | 
| 
      
 255 
     | 
    
         
            +
                  end
         
     | 
| 
      
 256 
     | 
    
         
            +
             
     | 
| 
      
 257 
     | 
    
         
            +
                  def tick
         
     | 
| 
      
 258 
     | 
    
         
            +
                    set_color([10003].pack("U*"), :green)
         
     | 
| 
      
 259 
     | 
    
         
            +
                  end
         
     | 
| 
      
 260 
     | 
    
         
            +
             
     | 
| 
      
 261 
     | 
    
         
            +
                  def cross
         
     | 
| 
      
 262 
     | 
    
         
            +
                    set_color([10008].pack("U*"), :red)
         
     | 
| 
      
 263 
     | 
    
         
            +
                  end
         
     | 
| 
      
 264 
     | 
    
         
            +
             
     | 
| 
      
 265 
     | 
    
         
            +
                  def revisions_endpoint(change_id, revision_id = nil, path = nil)
         
     | 
| 
      
 266 
     | 
    
         
            +
                    url = "#{changes_endpoint(change_id)}revisions/"
         
     | 
| 
      
 267 
     | 
    
         
            +
                    url += "#{revision_id}/" if revision_id
         
     | 
| 
      
 268 
     | 
    
         
            +
                    url += path if path
         
     | 
| 
      
 269 
     | 
    
         
            +
                    url
         
     | 
| 
      
 270 
     | 
    
         
            +
                  end
         
     | 
| 
      
 271 
     | 
    
         
            +
             
     | 
| 
      
 272 
     | 
    
         
            +
                  def reviewers_endpoint(change_id)
         
     | 
| 
      
 273 
     | 
    
         
            +
                    changes_endpoint(change_id, "reviewers")
         
     | 
| 
      
 274 
     | 
    
         
            +
                  end
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
                  def run_editor
         
     | 
| 
      
 277 
     | 
    
         
            +
                    path = File.expand_path('~/.fuel/MSG')
         
     | 
| 
      
 278 
     | 
    
         
            +
                    FileUtils.touch(path)
         
     | 
| 
      
 279 
     | 
    
         
            +
                    system((ENV['EDITOR'] || 'vi') + ' ' + path)
         
     | 
| 
      
 280 
     | 
    
         
            +
                    content = File.read(path)
         
     | 
| 
      
 281 
     | 
    
         
            +
                    FileUtils.rm(path)
         
     | 
| 
      
 282 
     | 
    
         
            +
                    content
         
     | 
| 
      
 283 
     | 
    
         
            +
                  end
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
      
 285 
     | 
    
         
            +
                  def fetch_comments(change_id, revision_id)
         
     | 
| 
      
 286 
     | 
    
         
            +
                    return self.class.get(revisions_endpoint(change_id, revision_id, 'comments')).parsed_response
         
     | 
| 
      
 287 
     | 
    
         
            +
                  end
         
     | 
| 
      
 288 
     | 
    
         
            +
             
     | 
| 
      
 289 
     | 
    
         
            +
                  def comments_for_file(file)
         
     | 
| 
      
 290 
     | 
    
         
            +
                    change_id = fetch_change_id_or_fail
         
     | 
| 
      
 291 
     | 
    
         
            +
                    result = self.class.get(changes_endpoint(change_id, "detail?o=CURRENT_REVISION&o=CURRENT_FILES")).parsed_response
         
     | 
| 
      
 292 
     | 
    
         
            +
                    current_rev = result['current_revision']
         
     | 
| 
      
 293 
     | 
    
         
            +
             
     | 
| 
      
 294 
     | 
    
         
            +
                    content = self.class.get(revisions_endpoint(change_id, current_rev, "files/#{CGI::escape(file)}/content")).parsed_response
         
     | 
| 
      
 295 
     | 
    
         
            +
                    content = Base64::decode64(content)
         
     | 
| 
      
 296 
     | 
    
         
            +
                    lines = content.split("\n")
         
     | 
| 
      
 297 
     | 
    
         
            +
                    comments = fetch_comments(change_id, current_rev)[file]
         
     | 
| 
      
 298 
     | 
    
         
            +
                    comments.sort_by! { |c| [c['line'], Time.parse(c['updated'])] }
         
     | 
| 
      
 299 
     | 
    
         
            +
                    [comments, lines, change_id, current_rev]
         
     | 
| 
      
 300 
     | 
    
         
            +
                  end
         
     | 
| 
      
 301 
     | 
    
         
            +
             
     | 
| 
      
 302 
     | 
    
         
            +
                  def gerrit_user
         
     | 
| 
      
 303 
     | 
    
         
            +
                    Config.get('gerrit', 'user')
         
     | 
| 
      
 304 
     | 
    
         
            +
                  end
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
      
 306 
     | 
    
         
            +
                  def print_comments_info(data)
         
     | 
| 
      
 307 
     | 
    
         
            +
                    table = data.inject([]) do |memo, (file, comments)|
         
     | 
| 
      
 308 
     | 
    
         
            +
                      memo << [file, set_color(plural(comments.count, 'comment'), :yellow)] if comments.count > 0
         
     | 
| 
      
 309 
     | 
    
         
            +
                      memo
         
     | 
| 
      
 310 
     | 
    
         
            +
                    end
         
     | 
| 
      
 311 
     | 
    
         
            +
                    unless table.empty?
         
     | 
| 
      
 312 
     | 
    
         
            +
                      puts
         
     | 
| 
      
 313 
     | 
    
         
            +
                      say "Files with comments:"
         
     | 
| 
      
 314 
     | 
    
         
            +
                      say "  (use \"gerrit comments FILE\" to see the comments)"
         
     | 
| 
      
 315 
     | 
    
         
            +
                      print_table table, :indent => 8
         
     | 
| 
      
 316 
     | 
    
         
            +
                    end
         
     | 
| 
      
 317 
     | 
    
         
            +
                  end
         
     | 
| 
      
 318 
     | 
    
         
            +
             
     | 
| 
      
 319 
     | 
    
         
            +
                  def plural(n, singular)
         
     | 
| 
      
 320 
     | 
    
         
            +
                    if n == 1
         
     | 
| 
      
 321 
     | 
    
         
            +
                      "1 #{singular}"
         
     | 
| 
      
 322 
     | 
    
         
            +
                    else
         
     | 
| 
      
 323 
     | 
    
         
            +
                      "#{n} #{singular}s"
         
     | 
| 
      
 324 
     | 
    
         
            +
                    end
         
     | 
| 
      
 325 
     | 
    
         
            +
                  end
         
     | 
| 
      
 326 
     | 
    
         
            +
                end
         
     | 
| 
      
 327 
     | 
    
         
            +
              end
         
     | 
| 
      
 328 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Fuel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module CLI
         
     | 
| 
      
 3 
     | 
    
         
            +
                module GerritCommon
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def gerrit_url
         
     | 
| 
      
 5 
     | 
    
         
            +
                    Fuel::Util::Config.get('gerrit', 'url').chomp('/')
         
     | 
| 
      
 6 
     | 
    
         
            +
                  end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def gerrit_ref(result)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    current_rev = result['current_revision']
         
     | 
| 
      
 10 
     | 
    
         
            +
                    result['revisions'][current_rev]['fetch']['ssh']['ref']
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def changes_endpoint(change_id = nil, path = nil)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    url = "#{gerrit_url}/a/changes/"
         
     | 
| 
      
 15 
     | 
    
         
            +
                    url += "#{change_id}/" if change_id
         
     | 
| 
      
 16 
     | 
    
         
            +
                    url += path if path
         
     | 
| 
      
 17 
     | 
    
         
            +
                    url
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,89 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Fuel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module CLI
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Jenkins < Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                  include GerritCommon
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  headers "Content-Type" => "application/json"
         
     | 
| 
      
 7 
     | 
    
         
            +
                  digest_auth Config.get('gerrit', 'user'), Config.get('gerrit', 'password')
         
     | 
| 
      
 8 
     | 
    
         
            +
                  parser GerritJsonParser
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  package_name "jenkins"
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  desc "open", "Open the most recent Jenkins build for the current change"
         
     | 
| 
      
 13 
     | 
    
         
            +
                  def open
         
     | 
| 
      
 14 
     | 
    
         
            +
                    build_link = build_link_or_fail
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    `open #{build_link}`
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  desc "deploy", "Deploy the latest patchset to your QA server"
         
     | 
| 
      
 20 
     | 
    
         
            +
                  def deploy
         
     | 
| 
      
 21 
     | 
    
         
            +
                    change_id = 'Ia8b172edcedcef7856b4d5fa7aee9e58649abe75'#fetch_change_id_or_fail
         
     | 
| 
      
 22 
     | 
    
         
            +
                    result = self.class.get(changes_endpoint(change_id, "?o=CURRENT_REVISION")).parsed_response
         
     | 
| 
      
 23 
     | 
    
         
            +
                    current_rev = result['current_revision']
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    client = create_client
         
     | 
| 
      
 26 
     | 
    
         
            +
                    ref = gerrit_ref(result).sub('refs/', '')
         
     | 
| 
      
 27 
     | 
    
         
            +
                    client.job.build("ui.fuel-deploy.gerrit", { "Environment" => "qa", "GerritRef" => ref })
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  desc "status", "View the status of the current build"
         
     | 
| 
      
 31 
     | 
    
         
            +
                  def status
         
     | 
| 
      
 32 
     | 
    
         
            +
                    details = build_details
         
     | 
| 
      
 33 
     | 
    
         
            +
                    result = details['result']
         
     | 
| 
      
 34 
     | 
    
         
            +
                    say 'Build is still running', :yellow and return unless result
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    color = case result
         
     | 
| 
      
 37 
     | 
    
         
            +
                    when "FAILURE", "ABORTED"
         
     | 
| 
      
 38 
     | 
    
         
            +
                      :red
         
     | 
| 
      
 39 
     | 
    
         
            +
                    when "SUCCESS"
         
     | 
| 
      
 40 
     | 
    
         
            +
                      :green
         
     | 
| 
      
 41 
     | 
    
         
            +
                    else
         
     | 
| 
      
 42 
     | 
    
         
            +
                      :default
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    say result, color
         
     | 
| 
      
 46 
     | 
    
         
            +
                    say 'Build artifacts are available via "jenkins artifacts"'
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  desc "artifacts", "Open build artifacts in the browser"
         
     | 
| 
      
 50 
     | 
    
         
            +
                  def artifacts
         
     | 
| 
      
 51 
     | 
    
         
            +
                    build_link = build_link_or_fail
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                    details = build_details
         
     | 
| 
      
 54 
     | 
    
         
            +
                    say 'No artifacts available, build might be still running', :yellow and return if details['artifacts'].empty?
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    `open #{build_link}artifact/`
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  desc "auth USER", "Store authentication information for Jenkins"
         
     | 
| 
      
 60 
     | 
    
         
            +
                  def auth(user)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    set_credentials(user, ['jenkins', :username], ['jenkins', :password])
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  private
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  def build_details
         
     | 
| 
      
 67 
     | 
    
         
            +
                    build_link = build_link_or_fail
         
     | 
| 
      
 68 
     | 
    
         
            +
                    build_number = build_link =~ /\/(\d+)\// && $1
         
     | 
| 
      
 69 
     | 
    
         
            +
                    client = create_client
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                    client.job.get_build_details("ui.fuel-gerrit", build_number)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  def create_client
         
     | 
| 
      
 75 
     | 
    
         
            +
                    @client ||= JenkinsApi::Client.new(Config.get('jenkins'))
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  def build_link_or_fail
         
     | 
| 
      
 79 
     | 
    
         
            +
                    change_id = 'I89fe9b251904fb929adf61605438fcc6fdbf534d'#fetch_change_id_or_fail
         
     | 
| 
      
 80 
     | 
    
         
            +
                    result = self.class.get(changes_endpoint(change_id, "detail")).parsed_response
         
     | 
| 
      
 81 
     | 
    
         
            +
                    build_message = result['messages'].reverse.find { |m| m['author']['username'] == 'hbuilduser' }
         
     | 
| 
      
 82 
     | 
    
         
            +
                    build_message &&= build_message['message']
         
     | 
| 
      
 83 
     | 
    
         
            +
                    build_link = build_message && URI.extract(build_message)[0]
         
     | 
| 
      
 84 
     | 
    
         
            +
                    raise Thor::Error, set_color('No Jenkins build found for this change', :red) unless build_link
         
     | 
| 
      
 85 
     | 
    
         
            +
                    build_link
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
              end
         
     | 
| 
      
 89 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Fuel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module CLI
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Jira < Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                  package_name "jira"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  headers "Content-Type" => "application/json"
         
     | 
| 
      
 7 
     | 
    
         
            +
                  basic_auth Config.get('jira', 'user'), Config.get('jira', 'password')
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  desc "status [JIRA]", "View a brief summary of the jira"
         
     | 
| 
      
 10 
     | 
    
         
            +
                  def status(jira = nil)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    jira_id = jira || fetch_jira_or_fail
         
     | 
| 
      
 12 
     | 
    
         
            +
                    result = self.class.get(issue_endpoint(jira_id)).parsed_response
         
     | 
| 
      
 13 
     | 
    
         
            +
                    fields = result["fields"]
         
     | 
| 
      
 14 
     | 
    
         
            +
                    say "#{jira_id}: #{fields['summary']}", :bold
         
     | 
| 
      
 15 
     | 
    
         
            +
                    table = [['Type', fields['issuetype']['name']]]
         
     | 
| 
      
 16 
     | 
    
         
            +
                    table << ['Status', fields['status']['name']]
         
     | 
| 
      
 17 
     | 
    
         
            +
                    table << ['Assignee', fields['assignee']['displayName']]
         
     | 
| 
      
 18 
     | 
    
         
            +
                    print_table table
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  desc "start [JIRA]", "Start progress on the jira"
         
     | 
| 
      
 22 
     | 
    
         
            +
                  def start(jira = nil)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    transition('start progress', jira)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  desc "resolve", "Resolve the current jira"
         
     | 
| 
      
 27 
     | 
    
         
            +
                  def resolve
         
     | 
| 
      
 28 
     | 
    
         
            +
                    transition('resolve issue')
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  desc "submit", "Put the current jira in review"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  def submit
         
     | 
| 
      
 33 
     | 
    
         
            +
                    transition('submit', nil, fields: { get_field_id(fetch_jira_or_fail, 'review id') => Gerrit.new.gerrit_change_url })
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  desc "auth USER", "Store authentication information for JIRA"
         
     | 
| 
      
 37 
     | 
    
         
            +
                  def auth(user)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    set_credentials(user, ['jira', 'user'], ['jira', 'password'])
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  private
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  def transition(name, jira = nil, extra_body = {})
         
     | 
| 
      
 44 
     | 
    
         
            +
                    jira_id = jira || fetch_jira_or_fail
         
     | 
| 
      
 45 
     | 
    
         
            +
                    body = { transition: { id: get_transition_id(jira_id, name) } }.merge(extra_body)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    result = self.class.post(issue_endpoint(jira_id, "transitions"),
         
     | 
| 
      
 47 
     | 
    
         
            +
                      body: body.to_json).parsed_response
         
     | 
| 
      
 48 
     | 
    
         
            +
                    puts result.inspect
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  def jira_url
         
     | 
| 
      
 52 
     | 
    
         
            +
                    Config.get('jira', 'url').chomp('/')
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  def get_field_id(jira_id, name)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    result = self.class.get(jira_endpoint("field")).parsed_response
         
     | 
| 
      
 57 
     | 
    
         
            +
                    field = result.find { |r| r['name'].downcase == name.downcase }
         
     | 
| 
      
 58 
     | 
    
         
            +
                    field && field['id']
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  def get_transition_id(jira_id, name)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    get_allowed_transitions(jira_id).each do |transition|
         
     | 
| 
      
 63 
     | 
    
         
            +
                      return transition["id"] if transition["name"].downcase == name.downcase
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  def get_allowed_transitions(jira_id)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    result = self.class.get(issue_endpoint(jira_id, "transitions")).parsed_response
         
     | 
| 
      
 70 
     | 
    
         
            +
                    result["transitions"]
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  def fetch_jira_or_fail
         
     | 
| 
      
 74 
     | 
    
         
            +
                    commit_message.split("\n")[2] or raise Thor::Error, set_color("No JIRA found at HEAD", :red)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  def jira_endpoint(path = "")
         
     | 
| 
      
 78 
     | 
    
         
            +
                    "#{jira_url}/rest/api/2/#{path}"
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  def issue_endpoint(id, path = "")
         
     | 
| 
      
 82 
     | 
    
         
            +
                    jira_endpoint("issue/#{id}/#{path}")
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Fuel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module CLI
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Main < Thor
         
     | 
| 
      
 4 
     | 
    
         
            +
                  include Fuel::Util
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  package_name "fuel"
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  desc "setup", "Set up the CLI interactively"
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def setup
         
     | 
| 
      
 10 
     | 
    
         
            +
                    say flame, :cyan
         
     | 
| 
      
 11 
     | 
    
         
            +
                    say "\nWelcome to Fuel-CLI!\n\n", :bold
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    setup_gerrit
         
     | 
| 
      
 14 
     | 
    
         
            +
                    setup_jira
         
     | 
| 
      
 15 
     | 
    
         
            +
                    setup_jenkins
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    say "You are good to go!", [:green, :bold]
         
     | 
| 
      
 18 
     | 
    
         
            +
                    say 'You have "fuel", "gerrit", "jira" and "jenkins" executables in your PATH.', :green
         
     | 
| 
      
 19 
     | 
    
         
            +
                    say 'Use the "help" command (e.g. "gerrit help") to get started.', :green
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  option :gerrit_url
         
     | 
| 
      
 23 
     | 
    
         
            +
                  option :jira_url
         
     | 
| 
      
 24 
     | 
    
         
            +
                  option :jenkins_url
         
     | 
| 
      
 25 
     | 
    
         
            +
                  desc "config", "Set configuration values"
         
     | 
| 
      
 26 
     | 
    
         
            +
                  def config
         
     | 
| 
      
 27 
     | 
    
         
            +
                    raise Thor::Error, set_color("Provide at least one key-value pair!", :red) if options.empty?
         
     | 
| 
      
 28 
     | 
    
         
            +
                    if options.has_key?('gerrit_url')
         
     | 
| 
      
 29 
     | 
    
         
            +
                      Config.set('gerrit', 'url', options['gerrit_url'])
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                    if options.has_key?('jira_url')
         
     | 
| 
      
 32 
     | 
    
         
            +
                      Config.set('jira', 'url', options['jira_url'])
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
                    if options.has_key?('jenkins_url')
         
     | 
| 
      
 35 
     | 
    
         
            +
                      Config.set('jenkins', :server_url, options['jenkins_url'])
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  private
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def setup_gerrit
         
     | 
| 
      
 42 
     | 
    
         
            +
                    say "[Setting up gerrit]", :yellow
         
     | 
| 
      
 43 
     | 
    
         
            +
                    gerrit_url = ask "URL:"
         
     | 
| 
      
 44 
     | 
    
         
            +
                    self.class.new.invoke :config, [], gerrit_url: gerrit_url
         
     | 
| 
      
 45 
     | 
    
         
            +
                    gerrit_user = ask "User name:"
         
     | 
| 
      
 46 
     | 
    
         
            +
                    say "Please go to your Gerrit user settings now, and generate an HTTP password there."
         
     | 
| 
      
 47 
     | 
    
         
            +
                    Gerrit.new.invoke :auth, [gerrit_user]
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    say "gerrit configured successfully!\n\n", :green
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def setup_jira
         
     | 
| 
      
 53 
     | 
    
         
            +
                    say "[Setting up jira]", :yellow
         
     | 
| 
      
 54 
     | 
    
         
            +
                    jira_url = ask "URL:"
         
     | 
| 
      
 55 
     | 
    
         
            +
                    self.class.new.invoke :config, [], jira_url: jira_url
         
     | 
| 
      
 56 
     | 
    
         
            +
                    jira_user = ask "User name:"
         
     | 
| 
      
 57 
     | 
    
         
            +
                    Jira.new.invoke :auth, [jira_user]
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                    say "jira configured successfully!\n\n", :green
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  def setup_jenkins
         
     | 
| 
      
 63 
     | 
    
         
            +
                    say "[Setting up jenkins]", :yellow
         
     | 
| 
      
 64 
     | 
    
         
            +
                    jenkins_url = ask "URL:"
         
     | 
| 
      
 65 
     | 
    
         
            +
                    self.class.new.invoke :config, [], jenkins_url: jenkins_url
         
     | 
| 
      
 66 
     | 
    
         
            +
                    jenkins_user = ask "User name:"
         
     | 
| 
      
 67 
     | 
    
         
            +
                    Jenkins.new.invoke :auth, [jenkins_user]
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                    say "jenkins configured successfully!\n\n", :green
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  def flame
         
     | 
| 
      
 73 
     | 
    
         
            +
                    <<-EOT
         
     | 
| 
      
 74 
     | 
    
         
            +
                                        `.--..`
         
     | 
| 
      
 75 
     | 
    
         
            +
                     `-/+syyso/.      .sdddddddhs+:.
         
     | 
| 
      
 76 
     | 
    
         
            +
                  -+ydddddddddddh/`  .dddh:.`.:+sdddho:`
         
     | 
| 
      
 77 
     | 
    
         
            +
                :yhsso+oshddddddddds/yddy`       `+ddddo`
         
     | 
| 
      
 78 
     | 
    
         
            +
               `.   ```   .+ddds/-:/+o+:     `-+ydds/.
         
     | 
| 
      
 79 
     | 
    
         
            +
                 .:odddh+   `sdddho:`    .:+ydds/.
         
     | 
| 
      
 80 
     | 
    
         
            +
            `:ohdddddddddy`   /ddddddhhhddhs/.
         
     | 
| 
      
 81 
     | 
    
         
            +
               `./oyhddhs:`    .ohhdhys+:`
         
     | 
| 
      
 82 
     | 
    
         
            +
                    EOT
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/fuel/cli.rb
    ADDED
    
    | 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'thor'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'jenkins_api_client'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'fuel/cli/version'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'fuel/util/config'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'fuel/util/json_parser'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'fuel/cli/gerrit_common'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'fuel/cli/patches'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'fuel/cli/base'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'fuel/cli/gerrit'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'fuel/cli/jira'
         
     | 
| 
      
 12 
     | 
    
         
            +
            require 'fuel/cli/jenkins'
         
     | 
| 
      
 13 
     | 
    
         
            +
            require 'fuel/cli/main'
         
     | 
| 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'fileutils'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'yaml'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Fuel
         
     | 
| 
      
 5 
     | 
    
         
            +
              module Util
         
     | 
| 
      
 6 
     | 
    
         
            +
                class Config
         
     | 
| 
      
 7 
     | 
    
         
            +
                  CONFIG_PATH = File.expand_path("~/.fuel")
         
     | 
| 
      
 8 
     | 
    
         
            +
                  CONFIG_FILENAME = "#{CONFIG_PATH}/cliconfig"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def self.set(*keys, value)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    ensure_config_exists
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    config = load
         
     | 
| 
      
 14 
     | 
    
         
            +
                    key = keys.pop
         
     | 
| 
      
 15 
     | 
    
         
            +
                    h = keys.inject(config) { |memo, k| memo[k] ||= {}; memo[k] }
         
     | 
| 
      
 16 
     | 
    
         
            +
                    h[key] = value
         
     | 
| 
      
 17 
     | 
    
         
            +
                    save(config)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def self.get(*keys)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    ensure_config_exists
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    config = load
         
     | 
| 
      
 24 
     | 
    
         
            +
                    keys.inject(config, :fetch)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  rescue KeyError
         
     | 
| 
      
 26 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def self.add(key, value)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    ensure_config_exists
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    config = load
         
     | 
| 
      
 33 
     | 
    
         
            +
                    config[key] ||= []
         
     | 
| 
      
 34 
     | 
    
         
            +
                    config[key] << value
         
     | 
| 
      
 35 
     | 
    
         
            +
                    save(config)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  private
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  def self.load
         
     | 
| 
      
 41 
     | 
    
         
            +
                    YAML.load_file(CONFIG_FILENAME) || {}
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  def self.save(config)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    File.open(CONFIG_FILENAME, "w") { |f| f.write(YAML.dump(config)) }
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  def self.ensure_config_exists
         
     | 
| 
      
 49 
     | 
    
         
            +
                    FileUtils.mkdir_p(CONFIG_PATH)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    FileUtils.touch(CONFIG_FILENAME)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'httparty'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Fuel
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Util
         
     | 
| 
      
 5 
     | 
    
         
            +
                class GerritJsonParser < HTTParty::Parser
         
     | 
| 
      
 6 
     | 
    
         
            +
                  XSSI_PREFIX = ")]}'"
         
     | 
| 
      
 7 
     | 
    
         
            +
                  SupportedFormats.merge!("application/json" => :json, "text/json" => :json)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def json
         
     | 
| 
      
 10 
     | 
    
         
            +
                    body.sub!(XSSI_PREFIX, "") if body.start_with?(XSSI_PREFIX)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    JSON.load(body, nil)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,154 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: fuel-cli
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.2
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Alex Zherdev
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2014-06-26 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: thor
         
     | 
| 
      
 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: httparty
         
     | 
| 
      
 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: jenkins_api_client
         
     | 
| 
      
 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: bundler
         
     | 
| 
      
 57 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 58 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 59 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 60 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '1.6'
         
     | 
| 
      
 62 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 63 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 64 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 65 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 66 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 67 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '1.6'
         
     | 
| 
      
 69 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 70 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 71 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 72 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 73 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 74 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 75 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 76 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 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: debugger
         
     | 
| 
      
 85 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 86 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 87 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 88 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 89 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 90 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 91 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 92 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 93 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 94 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 95 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 96 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 97 
     | 
    
         
            +
            description: ''
         
     | 
| 
      
 98 
     | 
    
         
            +
            email:
         
     | 
| 
      
 99 
     | 
    
         
            +
            - azherdev@rocketfuel.com
         
     | 
| 
      
 100 
     | 
    
         
            +
            executables:
         
     | 
| 
      
 101 
     | 
    
         
            +
            - fuel
         
     | 
| 
      
 102 
     | 
    
         
            +
            - gerrit
         
     | 
| 
      
 103 
     | 
    
         
            +
            - jenkins
         
     | 
| 
      
 104 
     | 
    
         
            +
            - jira
         
     | 
| 
      
 105 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 106 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 107 
     | 
    
         
            +
            files:
         
     | 
| 
      
 108 
     | 
    
         
            +
            - .gitignore
         
     | 
| 
      
 109 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 110 
     | 
    
         
            +
            - LICENSE.txt
         
     | 
| 
      
 111 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 112 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 113 
     | 
    
         
            +
            - bin/fuel
         
     | 
| 
      
 114 
     | 
    
         
            +
            - bin/gerrit
         
     | 
| 
      
 115 
     | 
    
         
            +
            - bin/jenkins
         
     | 
| 
      
 116 
     | 
    
         
            +
            - bin/jira
         
     | 
| 
      
 117 
     | 
    
         
            +
            - fuel-cli.gemspec
         
     | 
| 
      
 118 
     | 
    
         
            +
            - lib/fuel/cli.rb
         
     | 
| 
      
 119 
     | 
    
         
            +
            - lib/fuel/cli/base.rb
         
     | 
| 
      
 120 
     | 
    
         
            +
            - lib/fuel/cli/gerrit.rb
         
     | 
| 
      
 121 
     | 
    
         
            +
            - lib/fuel/cli/gerrit_common.rb
         
     | 
| 
      
 122 
     | 
    
         
            +
            - lib/fuel/cli/jenkins.rb
         
     | 
| 
      
 123 
     | 
    
         
            +
            - lib/fuel/cli/jira.rb
         
     | 
| 
      
 124 
     | 
    
         
            +
            - lib/fuel/cli/main.rb
         
     | 
| 
      
 125 
     | 
    
         
            +
            - lib/fuel/cli/patches.rb
         
     | 
| 
      
 126 
     | 
    
         
            +
            - lib/fuel/cli/version.rb
         
     | 
| 
      
 127 
     | 
    
         
            +
            - lib/fuel/util/config.rb
         
     | 
| 
      
 128 
     | 
    
         
            +
            - lib/fuel/util/json_parser.rb
         
     | 
| 
      
 129 
     | 
    
         
            +
            homepage: ''
         
     | 
| 
      
 130 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 131 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 132 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 133 
     | 
    
         
            +
            post_install_message: ! "\e[36m\e[1mWelcome, Fuel developer! Type \"fuel setup\" to
         
     | 
| 
      
 134 
     | 
    
         
            +
              get started.\e[0m"
         
     | 
| 
      
 135 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 136 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 137 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 138 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 139 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 140 
     | 
    
         
            +
              - - ! '>='
         
     | 
| 
      
 141 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 142 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 143 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 144 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 145 
     | 
    
         
            +
              - - ! '>='
         
     | 
| 
      
 146 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 147 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 148 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 149 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 150 
     | 
    
         
            +
            rubygems_version: 2.3.0
         
     | 
| 
      
 151 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 152 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 153 
     | 
    
         
            +
            summary: Simple set of command-line tools to aid in Fuel dev process.
         
     | 
| 
      
 154 
     | 
    
         
            +
            test_files: []
         
     |