tractive 1.0.14 → 1.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/README.adoc +5 -0
- data/exe/tractive +2 -0
- data/lib/tractive/github_api/graph_ql_client/issues.rb +29 -0
- data/lib/tractive/github_api/graph_ql_client.rb +31 -0
- data/lib/tractive/github_api.rb +1 -0
- data/lib/tractive/http/client/request.rb +1 -1
- data/lib/tractive/info.rb +13 -0
- data/lib/tractive/main.rb +3 -1
- data/lib/tractive/migrator/converter/trac_to_github.rb +15 -11
- data/lib/tractive/migrator/engine/migrate_from_db.rb +41 -0
- data/lib/tractive/migrator/engine.rb +2 -0
- data/lib/tractive/version.rb +1 -1
- data/tractive.gemspec +2 -0
- metadata +32 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e08becfcae314c82bdc793b7eb6bc2f7b52f9a7be040b7141da825753a9f1af2
         | 
| 4 | 
            +
              data.tar.gz: 51385bdf7fcf7b12b110c852b9d0b9dc277240abf0b8c2f94b68b77db2839c32
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ad89e67997dd07cb3b6d65c5baca788033991122d8a10a73a64b09df79695ed8e2488b033dfaaa5fdd07d4a65c4ee5b4230121f3f7f094c8286bce352bcd6118
         | 
| 7 | 
            +
              data.tar.gz: 04f60f8190dbc644367c3095f28e4f7fddba04dfa5140a820dfbced58430fb3b1df1bb9c72dd10dadba6e4f66e1cfe9a2ea57f647bbf982452643824e87622f8
         | 
    
        data/.rubocop.yml
    CHANGED
    
    
    
        data/README.adoc
    CHANGED
    
    | @@ -506,6 +506,8 @@ milestones: | |
| 506 506 | 
             
            ==== Attachments migration configuration
         | 
| 507 507 | 
             
            `ticket | wiki:`:: specifies the options for the tickets or wikis
         | 
| 508 508 |  | 
| 509 | 
            +
              `delete_mocked:`::: Whether to delete mocked tickets after migration or not
         | 
| 510 | 
            +
             | 
| 509 511 | 
             
              `attachments:`::: specifies method of obtaining attachments from Trac.
         | 
| 510 512 |  | 
| 511 513 | 
             
                `url:`:::: URL to obtain Trac attachments from
         | 
| @@ -517,9 +519,12 @@ milestones: | |
| 517 519 | 
             
                `export_script:`:::: output of a script that utilizes `trac-admin` to download 
         | 
| 518 520 | 
             
                all attachments from Trac.
         | 
| 519 521 |  | 
| 522 | 
            +
            NOTE: To delete the issues, an organization owner must enable deleting an issue for the organization's repositories, and you must have admin or owner permissions in the repository. For more information, see "https://docs.github.com/en/issues/tracking-your-work-with-issues/deleting-an-issue[deleting an issue]". 
         | 
| 523 | 
            +
             | 
| 520 524 | 
             
            [source,yaml]
         | 
| 521 525 | 
             
            ----
         | 
| 522 526 | 
             
            ticket:
         | 
| 527 | 
            +
              delete_mocked: true
         | 
| 523 528 | 
             
              attachments:
         | 
| 524 529 | 
             
                url: https://abc.com/raw-attachment/ticket
         | 
| 525 530 | 
             
                hashed: true
         | 
    
        data/exe/tractive
    CHANGED
    
    | @@ -47,6 +47,8 @@ class TractiveCommand < CommandBase | |
| 47 47 | 
             
                                          desc: "Put all issue comments in the first message."
         | 
| 48 48 | 
             
              method_option "start", type: :numeric, aliases: ["-s", "--start-at"], banner: "<ID>",
         | 
| 49 49 | 
             
                                     desc: "Start migration from ticket with number <ID>"
         | 
| 50 | 
            +
              method_option "make-owners-labels", type: :boolean,
         | 
| 51 | 
            +
                                                  desc: "If true, this will make a tag like `owner:<owner name>` and add it to the issue."
         | 
| 50 52 | 
             
              def migrate_tickets
         | 
| 51 53 | 
             
                Tractive::Main.new(options).run
         | 
| 52 54 | 
             
              end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module GithubApi
         | 
| 4 | 
            +
              class GraphQlClient
         | 
| 5 | 
            +
                # Methods for the Issues API
         | 
| 6 | 
            +
                module Issues
         | 
| 7 | 
            +
                  DELETE_ISSUE_QUERY = <<~QUERY
         | 
| 8 | 
            +
                    mutation ($input: DeleteIssueInput!) {
         | 
| 9 | 
            +
                      deleteIssue(input: $input) {
         | 
| 10 | 
            +
                        repository {
         | 
| 11 | 
            +
                          name
         | 
| 12 | 
            +
                          url
         | 
| 13 | 
            +
                        }
         | 
| 14 | 
            +
                      }
         | 
| 15 | 
            +
                    }
         | 
| 16 | 
            +
                  QUERY
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def delete_issue(issue_id)
         | 
| 19 | 
            +
                    variables = {
         | 
| 20 | 
            +
                      "input" => {
         | 
| 21 | 
            +
                        "issueId" => issue_id
         | 
| 22 | 
            +
                      }
         | 
| 23 | 
            +
                    }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    Client.query(DeleteIssueQuery, variables: variables)
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative "graph_ql_client/issues"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require "graphql/client"
         | 
| 6 | 
            +
            require "graphql/client/http"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            # Service to perform github actions
         | 
| 9 | 
            +
            module GithubApi
         | 
| 10 | 
            +
              class GraphQlClient
         | 
| 11 | 
            +
                include GithubApi::GraphQlClient::Issues
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                HttpAdapter = GraphQL::Client::HTTP.new("https://api.github.com/graphql") do
         | 
| 14 | 
            +
                  attr_writer :token
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def headers(_context)
         | 
| 17 | 
            +
                    {
         | 
| 18 | 
            +
                      "Authorization" => "bearer #{@token}"
         | 
| 19 | 
            +
                    }
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def self.add_constants(token)
         | 
| 24 | 
            +
                  HttpAdapter.token = token
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  GithubApi::GraphQlClient.const_set("Schema", GraphQL::Client.load_schema(HttpAdapter))
         | 
| 27 | 
            +
                  GithubApi::GraphQlClient.const_set("Client", GraphQL::Client.new(schema: Schema, execute: HttpAdapter))
         | 
| 28 | 
            +
                  GithubApi::GraphQlClient.const_set("DeleteIssueQuery", Client.parse(DELETE_ISSUE_QUERY))
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
    
        data/lib/tractive/github_api.rb
    CHANGED
    
    
| @@ -22,7 +22,7 @@ module Http | |
| 22 22 | 
             
                        minutes = retry_after / 60
         | 
| 23 23 | 
             
                        seconds = retry_after % 60
         | 
| 24 24 |  | 
| 25 | 
            -
                         | 
| 25 | 
            +
                        $logger.info "Rate Limit Exceeded, Will retry in #{minutes} min #{seconds} sec"
         | 
| 26 26 | 
             
                        sleep(1)
         | 
| 27 27 |  | 
| 28 28 | 
             
                        retry_after = e.http_headers[:x_ratelimit_reset].to_i - Time.now.to_i
         | 
    
        data/lib/tractive/info.rb
    CHANGED
    
    | @@ -29,12 +29,25 @@ module Tractive | |
| 29 29 | 
             
                  priorities  = Ticket.distinct.select(:priority).select_map(:priority).compact
         | 
| 30 30 | 
             
                  tracstates  = Ticket.distinct.select(:status).select_map(:status).compact
         | 
| 31 31 |  | 
| 32 | 
            +
                  keywords    = Ticket.distinct
         | 
| 33 | 
            +
                                      .select(:keywords)
         | 
| 34 | 
            +
                                      .select_map(:keywords)
         | 
| 35 | 
            +
                                      .map do |keyword|
         | 
| 36 | 
            +
                                        keyword&.split(",")&.map do |k|
         | 
| 37 | 
            +
                                          k.strip.gsub(" ", "_")
         | 
| 38 | 
            +
                                        end
         | 
| 39 | 
            +
                                      end
         | 
| 40 | 
            +
                                      .flatten
         | 
| 41 | 
            +
                                      .uniq
         | 
| 42 | 
            +
                                      .compact
         | 
| 43 | 
            +
             | 
| 32 44 | 
             
                  {
         | 
| 33 45 | 
             
                    "users" => Utilities.make_each_hash(users, %w[email name username]),
         | 
| 34 46 | 
             
                    "milestones" => milestones,
         | 
| 35 47 | 
             
                    "labels" => {
         | 
| 36 48 | 
             
                      "type" => Utilities.make_hash("type_", types),
         | 
| 37 49 | 
             
                      "resolution" => Utilities.make_hash("resolution_", resolutions),
         | 
| 50 | 
            +
                      "keywords" => Utilities.make_hash("keyword_", keywords),
         | 
| 38 51 | 
             
                      "component" => Utilities.make_each_hash(components, %w[name color], "component: "),
         | 
| 39 52 | 
             
                      "severity" => Utilities.make_each_hash(severity, %w[name color]),
         | 
| 40 53 | 
             
                      "priority" => Utilities.make_each_hash(priorities, %w[name color]),
         | 
    
        data/lib/tractive/main.rb
    CHANGED
    
    | @@ -9,7 +9,9 @@ module Tractive | |
| 9 9 | 
             
                  @cfg  = YAML.load_file(@opts[:config])
         | 
| 10 10 |  | 
| 11 11 | 
             
                  @cfg["github"] ||= {}
         | 
| 12 | 
            -
                  @cfg["github"]["token"] = @opts["git-token"]
         | 
| 12 | 
            +
                  @cfg["github"]["token"] = @opts["git-token"] if @opts["git-token"]
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  GithubApi::GraphQlClient.add_constants(@cfg["github"]["token"]) unless @opts[:info]
         | 
| 13 15 |  | 
| 14 16 | 
             
                  Tractive::Utilities.setup_logger(output_stream: @opts[:logfile] || $stderr, verbose: @opts[:verbose])
         | 
| 15 17 | 
             
                  @db = Tractive::Utilities.setup_db!(@opts["trac-database-path"] || @cfg["trac"]["database"])
         | 
| @@ -16,6 +16,7 @@ module Migrator | |
| 16 16 | 
             
                    @client               = GithubApi::Client.new(access_token: args[:cfg]["github"]["token"])
         | 
| 17 17 | 
             
                    @wiki_attachments_url = args[:cfg].dig("wiki", "attachments", "url")
         | 
| 18 18 | 
             
                    @revmap_file_path     = args[:opts][:revmapfile] || args[:cfg]["revmap_path"]
         | 
| 19 | 
            +
                    @make_owners_label    = args[:opts]["make-owners-labels"] || args[:cfg]["make_owners_labels"]
         | 
| 19 20 | 
             
                    @attachment_options   = {
         | 
| 20 21 | 
             
                      url: @attachurl,
         | 
| 21 22 | 
             
                      hashed: args[:cfg].dig("ticket", "attachments", "hashed")
         | 
| @@ -101,14 +102,11 @@ module Migrator | |
| 101 102 |  | 
| 102 103 | 
             
                    labels.delete(nil)
         | 
| 103 104 |  | 
| 104 | 
            -
                    keywords = ticket[:keywords]
         | 
| 105 | 
            -
                     | 
| 106 | 
            -
                       | 
| 107 | 
            -
                        labels.add(@labels_cfg.fetch("keywords", {})[ticket[:keywords].downcase])
         | 
| 108 | 
            -
                      else
         | 
| 109 | 
            -
                        badges.add(@labels_cfg.fetch("keywords", {})[ticket[:keywords]])
         | 
| 110 | 
            -
                      end
         | 
| 105 | 
            +
                    keywords = ticket[:keywords]&.split(",") || []
         | 
| 106 | 
            +
                    keywords.each do |keyword|
         | 
| 107 | 
            +
                      badges.add(@labels_cfg.fetch("keywords", {})[keyword.strip.gsub(" ", "_")])
         | 
| 111 108 | 
             
                    end
         | 
| 109 | 
            +
             | 
| 112 110 | 
             
                    # If the field is not set, it will be nil and generate an unprocessable json
         | 
| 113 111 |  | 
| 114 112 | 
             
                    milestone = @milestonemap[ticket[:milestone]]
         | 
| @@ -121,6 +119,14 @@ module Migrator | |
| 121 119 |  | 
| 122 120 | 
             
                    github_assignee = map_assignee(ticket[:owner])
         | 
| 123 121 |  | 
| 122 | 
            +
                    unless github_assignee.nil? || github_assignee.empty?
         | 
| 123 | 
            +
                      if @make_owners_label
         | 
| 124 | 
            +
                        labels.add("name" => "owner:#{github_assignee}")
         | 
| 125 | 
            +
                      else
         | 
| 126 | 
            +
                        badges.add("owner:#{github_assignee}")
         | 
| 127 | 
            +
                      end
         | 
| 128 | 
            +
                    end
         | 
| 129 | 
            +
             | 
| 124 130 | 
             
                    badges     = badges.to_a.compact.sort
         | 
| 125 131 | 
             
                    badgetable = badges.map { |i| %(`#{i}`) }.join(" ")
         | 
| 126 132 | 
             
                    badgetable += begin
         | 
| @@ -132,8 +138,6 @@ module Migrator | |
| 132 138 |  | 
| 133 139 | 
             
                    # compose body
         | 
| 134 140 | 
             
                    body = [badgetable, body, footer].join("\n\n___\n")
         | 
| 135 | 
            -
             | 
| 136 | 
            -
                    labels.add("name" => "owner:#{github_assignee}") unless github_assignee.nil? || github_assignee.empty?
         | 
| 137 141 | 
             
                    labels = labels.map { |label| label["name"] }
         | 
| 138 142 |  | 
| 139 143 | 
             
                    issue = {
         | 
| @@ -265,7 +269,7 @@ module Migrator | |
| 265 269 | 
             
                    end
         | 
| 266 270 |  | 
| 267 271 | 
             
                    case kind
         | 
| 268 | 
            -
                    when "owner", "status", "title", "resolution", "priority", "component", "type", "severity", "platform", "milestone"
         | 
| 272 | 
            +
                    when "owner", "status", "title", "resolution", "priority", "component", "type", "severity", "platform", "milestone", "keywords"
         | 
| 269 273 | 
             
                      old = meta[:oldvalue]
         | 
| 270 274 | 
             
                      new = meta[:newvalue]
         | 
| 271 275 | 
             
                      if old && new
         | 
| @@ -345,7 +349,7 @@ module Migrator | |
| 345 349 | 
             
                  end
         | 
| 346 350 |  | 
| 347 351 | 
             
                  def interested_in_change?(kind, newvalue)
         | 
| 348 | 
            -
                    !(%w[ | 
| 352 | 
            +
                    !(%w[cc reporter version].include?(kind) ||
         | 
| 349 353 | 
             
                      (kind == "comment" && (newvalue.nil? || newvalue.lstrip.empty?)))
         | 
| 350 354 | 
             
                  end
         | 
| 351 355 |  | 
| @@ -23,6 +23,7 @@ module Migrator | |
| 23 23 | 
             
                    begin
         | 
| 24 24 | 
             
                      lasttracid = tractickets.last[:id]
         | 
| 25 25 | 
             
                    rescue StandardError
         | 
| 26 | 
            +
                      delete_mocked_tickets if can_delete_mocked_tickets?
         | 
| 26 27 | 
             
                      raise("trac has no ticket #{start_ticket}")
         | 
| 27 28 | 
             
                    end
         | 
| 28 29 |  | 
| @@ -89,6 +90,46 @@ module Migrator | |
| 89 90 |  | 
| 90 91 | 
             
                      @last_created_issue = ticket[:id]
         | 
| 91 92 | 
             
                    end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                    delete_mocked_tickets if can_delete_mocked_tickets?
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  def can_delete_mocked_tickets?
         | 
| 98 | 
            +
                    @delete_mocked_tickets
         | 
| 99 | 
            +
                  end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                  def delete_mocked_tickets
         | 
| 102 | 
            +
                    page = 1
         | 
| 103 | 
            +
                    issues = @client.issues(@repo, { filter: "all",
         | 
| 104 | 
            +
                                                     state: "closed",
         | 
| 105 | 
            +
                                                     page: page })
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                    until issues.empty?
         | 
| 108 | 
            +
                      deleted = false
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                      issues.each do |issue|
         | 
| 111 | 
            +
                        next if issue["title"] != "Placeholder issue #{issue["number"]} created to align Github issue and trac ticket numbers during migration."
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                        response = @graph_ql_client.delete_issue(issue["node_id"])
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                        if response.data.errors.any?
         | 
| 116 | 
            +
                          error_message = response.data
         | 
| 117 | 
            +
                                                  .errors
         | 
| 118 | 
            +
                                                  .messages
         | 
| 119 | 
            +
                                                  .map { |k, v| "#{k}: #{v}" }
         | 
| 120 | 
            +
                                                  .join(", ")
         | 
| 121 | 
            +
                          raise StandardError, error_message
         | 
| 122 | 
            +
                        end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                        deleted = true
         | 
| 125 | 
            +
                        puts "Successfully deleted issue ##{issue["number"]}, Title: #{issue["title"]}"
         | 
| 126 | 
            +
                      end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                      page += 1 unless deleted
         | 
| 129 | 
            +
                      issues = @client.issues(@repo, { filter: "all",
         | 
| 130 | 
            +
                                                       state: "closed",
         | 
| 131 | 
            +
                                                       page: page })
         | 
| 132 | 
            +
                    end
         | 
| 92 133 | 
             
                  end
         | 
| 93 134 | 
             
                end
         | 
| 94 135 | 
             
              end
         | 
| @@ -32,6 +32,7 @@ module Migrator | |
| 32 32 | 
             
                  @trac  = Tractive::Trac.new(db)
         | 
| 33 33 | 
             
                  @repo  = github["repo"]
         | 
| 34 34 | 
             
                  @client = GithubApi::Client.new(access_token: github["token"])
         | 
| 35 | 
            +
                  @graph_ql_client = GithubApi::GraphQlClient.new
         | 
| 35 36 |  | 
| 36 37 | 
             
                  if input_file_name
         | 
| 37 38 | 
             
                    @from_file = input_file_name
         | 
| @@ -62,6 +63,7 @@ module Migrator | |
| 62 63 | 
             
                  @safetychecks     = safetychecks
         | 
| 63 64 | 
             
                  @start_ticket     = (start_ticket || (@last_created_issue + 1)).to_i
         | 
| 64 65 | 
             
                  @filter_closed    = filter_closed
         | 
| 66 | 
            +
                  @delete_mocked_tickets = args[:cfg]["ticket"]["delete_mocked"]
         | 
| 65 67 | 
             
                end
         | 
| 66 68 |  | 
| 67 69 | 
             
                def migrate
         | 
    
        data/lib/tractive/version.rb
    CHANGED
    
    
    
        data/tractive.gemspec
    CHANGED
    
    | @@ -27,6 +27,8 @@ Gem::Specification.new do |spec| | |
| 27 27 | 
             
              spec.executables   = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
         | 
| 28 28 | 
             
              spec.require_paths = ["lib"]
         | 
| 29 29 |  | 
| 30 | 
            +
              spec.add_dependency "graphql", "1.13.3"
         | 
| 31 | 
            +
              spec.add_dependency "graphql-client"
         | 
| 30 32 | 
             
              spec.add_dependency "mysql2"
         | 
| 31 33 | 
             
              spec.add_dependency "ox"
         | 
| 32 34 | 
             
              spec.add_dependency "rest-client"
         | 
    
        metadata
    CHANGED
    
    | @@ -1,15 +1,43 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: tractive
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.0. | 
| 4 | 
            +
              version: 1.0.18
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Ribose
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2022- | 
| 11 | 
            +
            date: 2022-02-08 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: graphql
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - '='
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: 1.13.3
         | 
| 20 | 
            +
              type: :runtime
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - '='
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: 1.13.3
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: graphql-client
         | 
| 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'
         | 
| 13 41 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 42 | 
             
              name: mysql2
         | 
| 15 43 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -145,6 +173,8 @@ files: | |
| 145 173 | 
             
            - lib/tractive/github_api/client/issues.rb
         | 
| 146 174 | 
             
            - lib/tractive/github_api/client/labels.rb
         | 
| 147 175 | 
             
            - lib/tractive/github_api/client/milestones.rb
         | 
| 176 | 
            +
            - lib/tractive/github_api/graph_ql_client.rb
         | 
| 177 | 
            +
            - lib/tractive/github_api/graph_ql_client/issues.rb
         | 
| 148 178 | 
             
            - lib/tractive/graceful_quit.rb
         | 
| 149 179 | 
             
            - lib/tractive/http/client.rb
         | 
| 150 180 | 
             
            - lib/tractive/http/client/request.rb
         |