ghx 0.2.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54d0617ded0141f352b6e27b38245f8d269546093d328ffa8428cef0cc45ae0f
4
- data.tar.gz: 52bd1ef5a4c214203938a1dbbadf487ac49c5fc398ccc17045ec2c400425ff80
3
+ metadata.gz: 844c71686d364775951d08395893eb266f66255d9a3ad08bae723301b85fc7e9
4
+ data.tar.gz: e2ac2f47f1673a8876358ce39513193741a26a9a42a314044a35b3e6d9c553c6
5
5
  SHA512:
6
- metadata.gz: 14df558d839c2efb46d68b78482b30c7c6b26ba86be9c1c38a6e4d22202678f5e19f1a2f4a56f713060ba216523c75b2ee57945e590e10407059c5c9ce1a3382
7
- data.tar.gz: 14c21c92397ade112c51e2bef0253bcd5d61a28a5b28b776c699fb0b8c6af392d9e611c03bb0aaa1575bf1ec075e7b337f2e717fe9dd4a85cb0995280f3d7932
6
+ metadata.gz: 2034b514c2005c54a97a7cae8b5acae0eb80993d40e03504371e4b83bffc84f642513183fb5615e132b831e1e4747e3787a767ad9ca049c5e0960b968a7caa45
7
+ data.tar.gz: 9d02fac7a48c996d82a8122249fa74902b0ba8671d93de4442c56b756794a3bcb77cceeed2e9b654c480625d8efbba91ce577b15ff349ee4afa55328758a261d
@@ -115,9 +115,11 @@
115
115
 
116
116
  module GHX
117
117
  module Dependabot
118
+ # A Dependabot Alert
118
119
  class Alert
119
120
  attr_reader :number, :state, :dependency, :security_advisory, :security_vulnerability, :url, :html_url, :created_at, :updated_at
120
121
 
122
+ # @param json_data [Hash] The JSON data for the alert, from the API
121
123
  def initialize(json_data)
122
124
  @number = json_data["number"]
123
125
  @state = json_data["state"]
@@ -1,5 +1,6 @@
1
1
  module GHX
2
2
  module Dependabot
3
+ # A package is a dependency that is managed by a package manager. Referenced by a SecurityVulnerability.
3
4
  class Package
4
5
  attr_reader :ecosystem, :name
5
6
 
@@ -1,5 +1,6 @@
1
1
  module GHX
2
2
  module Dependabot
3
+ # A SecurityVulnerability is referenced by an Alert
3
4
  class SecurityVulnerability
4
5
  attr_reader :package, :severity, :vulnerable_version_range, :first_patched_version
5
6
 
@@ -1,6 +1,15 @@
1
1
  module GHX
2
+ # Module for Dependabot-related classes and methods
2
3
  module Dependabot
4
+ # Get Dependabot alerts for a given repository
5
+ #
6
+ # @note ONLY RETURNS THE FIRST 100 ALERTS
7
+ # @param owner [String] the owner of the repository
8
+ # @param repo [String] the repository name
9
+ # @return [Array<GHX::Dependabot::Alert>] the alerts
3
10
  def self.get_alerts(owner:, repo:)
11
+ # TODO: Add pagination to get all alerts in one go
12
+
4
13
  GHX.rest_client.get("repos/#{owner}/#{repo}/dependabot/alerts?state=open&per_page=100").map do |alert|
5
14
  GHX::Dependabot::Alert.new(alert)
6
15
  end
data/lib/ghx/errors.rb ADDED
@@ -0,0 +1,7 @@
1
+ module GHX
2
+ class GHXError < StandardError; end
3
+
4
+ class RateLimitExceededError < GHXError; end
5
+
6
+ class OtherApiError < GHXError; end
7
+ end
@@ -1,9 +1,14 @@
1
1
  module GHX
2
+ # Internal class to interact with the GitHub GraphQL API
2
3
  class GraphqlClient
4
+ # @param api_key [String]
3
5
  def initialize(api_key)
4
6
  @api_key = api_key
5
7
  end
6
8
 
9
+ # Perform a GraphQL Query and return the result
10
+ # @param query [String] GraphQL Query
11
+ # @return [Net::HTTPResponse]
7
12
  def query(query)
8
13
  uri = URI("https://api.github.com/graphql")
9
14
  req = Net::HTTP::Post.new(uri)
@@ -15,54 +20,5 @@ module GHX
15
20
  http.request(req)
16
21
  end
17
22
  end
18
-
19
- # @param [String] project_id
20
- # @param [GithubProjectItem] project_item
21
- # @param [DateTime] reported_at
22
- def update_project_item_reported_at(project_item_id:, reported_at:, project_id: GithubProject::MAIN_GH_PROJECT_ID)
23
- field_id = "PVTF_lADOALH_aM4Ac-_zzgSzAZs" # project_item.field_map["Reported At"]
24
-
25
- gql_query = <<~GQL
26
- mutation {
27
- updateProjectV2ItemFieldValue(input: {
28
- fieldId: "#{field_id}",
29
- itemId: "#{project_item_id}",
30
- projectId: "#{project_id}",
31
- value: {
32
- date: "#{reported_at.to_date}"
33
- }
34
- }) {
35
- projectV2Item {
36
- id
37
- }
38
- }
39
- }
40
- GQL
41
-
42
- query(gql_query)
43
- end
44
-
45
- def update_project_item_reported_by(project_item_id:, reported_by:, project_id: GithubProject::MAIN_GH_PROJECT_ID)
46
- field_id = "PVTF_lADOALH_aM4Ac-_zzgSzBcc" # project_item.field_map["Reporter"]
47
-
48
- gql_query = <<~GQL
49
- mutation {
50
- updateProjectV2ItemFieldValue(input: {
51
- fieldId: "#{field_id}",
52
- itemId: "#{project_item_id}",
53
- projectId: "#{project_id}",
54
- value: {
55
- text: "#{reported_by}"
56
- }
57
- }) {
58
- projectV2Item {
59
- id
60
- }
61
- }
62
- }
63
- GQL
64
-
65
- query(gql_query)
66
- end
67
23
  end
68
24
  end
data/lib/ghx/issue.rb CHANGED
@@ -1,29 +1,45 @@
1
1
  module GHX
2
+ # A GitHub Issue
2
3
  class Issue
3
4
  attr_accessor :owner, :repo, :number, :title, :body, :state, :state_reason, :author, :assignees, :labels, :milestone, :created_at, :updated_at, :closed_at
4
5
 
6
+ # Search for issues in a repository
7
+ # @param owner [String] the owner of the repository
8
+ # @param repo [String] the repository name
9
+ # @param query [String] the search query, using GitHub's search syntax
10
+ # @return [Array<Issue>] the issues found
5
11
  def self.search(owner:, repo:, query:)
6
12
  data = GHX.rest_client.get("search/issues?q=#{URI.encode_www_form_component(query)}+is:issue+repo:#{owner}/#{repo}")
7
13
  data.fetch("items").to_a.map do |issue_data|
8
14
  new(owner: owner, repo: repo, **issue_data)
9
15
  end
10
- rescue => e
11
- GHX.logger.error "Error searching for issues with query: #{e.message}"
12
- GHX.logger.error "Received data: #{data}"
13
- []
14
16
  end
15
17
 
18
+ # Find an issue by its number
19
+ # @param owner [String] the owner of the repository
20
+ # @param repo [String] the repository name
21
+ # @param number [Integer] the issue number
22
+ # @return [Issue] the issue found
16
23
  def self.find(owner:, repo:, number:)
17
24
  response_data = GHX.rest_client.get("repos/#{owner}/#{repo}/issues/#{number}")
18
25
  new(owner: owner, repo: repo, **response_data)
19
26
  end
20
27
 
28
+ # @param owner [String] the owner of the repository
29
+ # @param repo [String] the repository name
30
+ # @param **args [Hash] the attributes of the issue you wish to assign
31
+ # @return [Issue] the new issue
21
32
  def initialize(owner:, repo:, **args)
22
33
  @owner = owner
23
34
  @repo = repo
24
35
  update_attributes(args)
25
36
  end
26
37
 
38
+ # Save the issue to GitHub. Handles both creating and updating.
39
+ #
40
+ # If the issue has a number, it will be updated. Otherwise, it will be created.
41
+ #
42
+ # @return [Issue] the saved issue
27
43
  def save
28
44
  @number.nil? ? create : update
29
45
  end
data/lib/ghx/project.rb CHANGED
@@ -48,7 +48,7 @@ module GHX
48
48
  }
49
49
  GQL
50
50
 
51
- client = GraphqlClient.new(ENV["GITHUB_TOKEN"])
51
+ client = GHX.graphql
52
52
  res = client.query(gql_query)
53
53
 
54
54
  data = JSON.parse(res.body)
@@ -177,7 +177,7 @@ module GHX
177
177
  }
178
178
  GQL
179
179
 
180
- client = GraphqlClient.new(ENV["GITHUB_TOKEN"])
180
+ client = GHX.graphql
181
181
  res = client.query(gql_query)
182
182
 
183
183
  data = JSON.parse(res.body)
@@ -1,7 +1,14 @@
1
1
  module GHX
2
+ # A GitHub Project Item. This is a single item in a GitHub Project Board.
3
+ #
4
+ # ProjectsV2 are only available via the GraphQL API. This class wraps access to the API and provides a more OO interface.
5
+ #
6
+ # @note Access to ProjectItems should be done largely (if not always) through the Project class.
2
7
  class ProjectItem
3
8
  attr_accessor :id, :project_id, :issue_number, :issue_title, :issue_url, :issue_state, :field_values, :field_map
4
9
 
10
+ # @param field_configuration [Array<Hash>] An array of field configurations. These are the fields that are available to the Project Item. These are provided via the Project itself. It's much easier to access ProjectItems through the project because of this.
11
+ # @param data [Hash] The data from the GraphQL API.
5
12
  def initialize(field_configuration:, data:)
6
13
  _setup_field_configuration(field_configuration)
7
14
 
@@ -33,7 +40,11 @@ module GHX
33
40
  end
34
41
  end
35
42
 
36
- # Updates the given fields to the given values. Makes a GraphQL call per field to do the update.
43
+ # Updates the given fields to the given values. Makes a GraphQL call *per field* to do the update.
44
+ #
45
+ # The implementation wraps access to the various types for each field. Since GraphQL requires us to type match on all
46
+ # requests, this gives us convenience, especially for things like a select field. We can pass in the value, and the
47
+ # method will find the ID of the option and update the field for us.
37
48
  #
38
49
  # @param fields [Hash] A hash of field names to values.
39
50
  def update(**fields)
@@ -76,7 +87,7 @@ module GHX
76
87
  }
77
88
  GQL
78
89
 
79
- client = GraphqlClient.new(ENV["GITHUB_TOKEN"])
90
+ client = GHX.graphql
80
91
  res = client.query(gql_query)
81
92
  GHX.logger.debug "Update text field result"
82
93
  GHX.logger.debug res
@@ -100,7 +111,7 @@ module GHX
100
111
  }
101
112
  GQL
102
113
 
103
- client = GraphqlClient.new(ENV["GITHUB_TOKEN"])
114
+ client = GHX.graphql
104
115
  res = client.query(gql_query)
105
116
  GHX.logger.debug "Update date field result"
106
117
  GHX.logger.debug res
@@ -130,7 +141,7 @@ module GHX
130
141
  }
131
142
  GQL
132
143
 
133
- client = GraphqlClient.new(ENV["GITHUB_TOKEN"])
144
+ client = GHX.graphql
134
145
  res = client.query(gql_query)
135
146
  GHX.logger.debug "Update single select field result"
136
147
  GHX.logger.debug res.body
@@ -138,23 +149,27 @@ module GHX
138
149
 
139
150
  private
140
151
 
152
+ # Parse the field_configuration and set up the instance variables and accessors.
153
+ #
154
+ # Example field_configuration:
155
+ # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCno", :name=>"Title", :data_type=>"TITLE", :options=>nil}
156
+ # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCns", :name=>"Assignees", :data_type=>"ASSIGNEES", :options=>nil}
157
+ # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSzAZs", :name=>"Reported At", :data_type=>"DATE", :options=>nil}
158
+ # {:id=>"PVTSSF_lADOALH_aM4Ac-_zzgSxCnw", :name=>"Status", :data_type=>"SINGLE_SELECT", :options=>[{:id=>"f971fb55", :name=>"To triage"}, {:id=>"856cdede", :name=>"Ready to Assign"}, {:id=>"f75ad846", :name=>"Assigned"}, {:id=>"47fc9ee4", :name=>"Fix In progress"}, {:id=>"5ef0dc97", :name=>"Additional Info Requested"}, {:id=>"98236657", :name=>"Done - Fixed"}, {:id=>"98aea6ad", :name=>"Done - Won't Fix"}, {:id=>"a3b4fc3a", :name=>"Duplicate"}, {:id=>"81377549", :name=>"Not a Vulnerability"}]}
159
+ # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCn0", :name=>"Labels", :data_type=>"LABELS", :options=>nil}
160
+ # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCn4", :name=>"Linked pull requests", :data_type=>"LINKED_PULL_REQUESTS", :options=>nil}
161
+ # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCn8", :name=>"Milestone", :data_type=>"MILESTONE", :options=>nil}
162
+ # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCoA", :name=>"Repository", :data_type=>"REPOSITORY", :options=>nil}
163
+ # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCoM", :name=>"Reviewers", :data_type=>"REVIEWERS", :options=>nil}
164
+ # {:id=>"PVTSSF_lADOALH_aM4Ac-_zzgSxCuA", :name=>"Severity", :data_type=>"SINGLE_SELECT", :options=>[{:id=>"79628723", :name=>"Informational"}, {:id=>"153889c6", :name=>"Low"}, {:id=>"093709ee", :name=>"Medium"}, {:id=>"5a00bbe7", :name=>"High"}, {:id=>"00e0bbaf", :name=>"Critical"}, {:id=>"fd986bd9", :name=>"Duplicate"}]}
165
+ # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSzBcc", :name=>"Reporter", :data_type=>"TEXT", :options=>nil}
166
+ # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSzBho", :name=>"Resolve By", :data_type=>"DATE", :options=>nil}
167
+ # {:id=>"PVTSSF_lADOALH_aM4Ac-_zzgTKjOw", :name=>"Payout Status", :data_type=>"SINGLE_SELECT", :options=>[{:id=>"53c47c02", :name=>"Ready for Invoice"}, {:id=>"0b8a4629", :name=>"Payout in Process"}, {:id=>"5f356a58", :name=>"Payout Complete"}, {:id=>"368048ac", :name=>"Ineligible for Payout"}]}
168
+ #
169
+ #
141
170
  def _setup_field_configuration(field_configuration)
142
171
  @field_configuration = field_configuration.map { |fc| fc.merge({normalized_name: normalized_field_value_name(fc[:name])}) }
143
172
 
144
- # Example field_configuration:
145
- # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCno", :name=>"Title", :data_type=>"TITLE", :options=>nil}
146
- # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCns", :name=>"Assignees", :data_type=>"ASSIGNEES", :options=>nil}
147
- # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSzAZs", :name=>"Reported At", :data_type=>"DATE", :options=>nil}
148
- # {:id=>"PVTSSF_lADOALH_aM4Ac-_zzgSxCnw", :name=>"Status", :data_type=>"SINGLE_SELECT", :options=>[{:id=>"f971fb55", :name=>"To triage"}, {:id=>"856cdede", :name=>"Ready to Assign"}, {:id=>"f75ad846", :name=>"Assigned"}, {:id=>"47fc9ee4", :name=>"Fix In progress"}, {:id=>"5ef0dc97", :name=>"Additional Info Requested"}, {:id=>"98236657", :name=>"Done - Fixed"}, {:id=>"98aea6ad", :name=>"Done - Won't Fix"}, {:id=>"a3b4fc3a", :name=>"Duplicate"}, {:id=>"81377549", :name=>"Not a Vulnerability"}]}
149
- # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCn0", :name=>"Labels", :data_type=>"LABELS", :options=>nil}
150
- # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCn4", :name=>"Linked pull requests", :data_type=>"LINKED_PULL_REQUESTS", :options=>nil}
151
- # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCn8", :name=>"Milestone", :data_type=>"MILESTONE", :options=>nil}
152
- # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCoA", :name=>"Repository", :data_type=>"REPOSITORY", :options=>nil}
153
- # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSxCoM", :name=>"Reviewers", :data_type=>"REVIEWERS", :options=>nil}
154
- # {:id=>"PVTSSF_lADOALH_aM4Ac-_zzgSxCuA", :name=>"Severity", :data_type=>"SINGLE_SELECT", :options=>[{:id=>"79628723", :name=>"Informational"}, {:id=>"153889c6", :name=>"Low"}, {:id=>"093709ee", :name=>"Medium"}, {:id=>"5a00bbe7", :name=>"High"}, {:id=>"00e0bbaf", :name=>"Critical"}, {:id=>"fd986bd9", :name=>"Duplicate"}]}
155
- # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSzBcc", :name=>"Reporter", :data_type=>"TEXT", :options=>nil}
156
- # {:id=>"PVTF_lADOALH_aM4Ac-_zzgSzBho", :name=>"Resolve By", :data_type=>"DATE", :options=>nil}
157
- # {:id=>"PVTSSF_lADOALH_aM4Ac-_zzgTKjOw", :name=>"Payout Status", :data_type=>"SINGLE_SELECT", :options=>[{:id=>"53c47c02", :name=>"Ready for Invoice"}, {:id=>"0b8a4629", :name=>"Payout in Process"}, {:id=>"5f356a58", :name=>"Payout Complete"}, {:id=>"368048ac", :name=>"Ineligible for Payout"}]}
158
173
  @field_configuration.each do |field|
159
174
  next unless field[:name]
160
175
  next if field[:name].to_s.empty?
@@ -1,57 +1,62 @@
1
1
  require "net/http"
2
2
 
3
3
  module GHX
4
+ # RestClient is a simple wrapper around Net::HTTP to make it easier to make API calls to the GitHub REST API.
5
+ #
6
+ # This is necessary because not all GitHub API endpoints are covered by Octokit.
4
7
  class RestClient
5
8
  attr_reader :api_key
6
9
 
10
+ # @param api_key [String] the GitHub API key
7
11
  def initialize(api_key)
8
12
  @api_key = api_key
9
13
  end
10
14
 
11
- # @return [Hash] the JSON response
15
+ # Make a GET request to the given path
16
+ # @param path [String] the path to the API endpoint
17
+ # @return [Hash] the parsed JSON response
12
18
  def get(path)
13
19
  uri = URI.parse("https://api.github.com/#{path}")
14
20
  request = Net::HTTP::Get.new(uri)
15
- request["Accept"] = "application/vnd.github+json"
16
- request["Authorization"] = "Bearer #{@api_key}"
17
- request["X-Github-Api-Version"] = "2022-11-28"
18
-
19
- req_options = {
20
- use_ssl: uri.scheme == "https"
21
- }
22
21
 
23
- response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
24
- http.request(request)
25
- end
22
+ response = _http_request(uri: uri, request: request)
26
23
 
27
24
  JSON.parse(response.body)
28
25
  end
29
26
 
30
- # @return [Hash] the JSON response
27
+ # Make a POST request to the given path with the given params
28
+ # @param path [String] the path to the API endpoint
29
+ # @param params [Hash] the request body
30
+ # @return [Hash] the parsed JSON response
31
31
  def post(path, params)
32
32
  uri = URI.parse("https://api.github.com/#{path}")
33
33
  request = Net::HTTP::Post.new(uri)
34
- request["Accept"] = "application/vnd.github+json"
35
- request["Authorization"] = "Bearer #{@api_key}"
36
- request["X-Github-Api-Version"] = "2022-11-28"
37
-
38
- req_options = {
39
- use_ssl: uri.scheme == "https"
40
- }
41
34
 
42
35
  request.body = params.to_json
43
36
 
44
- response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
45
- http.request(request)
46
- end
37
+ response = _http_request(uri: uri, request: request)
47
38
 
48
39
  JSON.parse(response.body)
49
40
  end
50
41
 
51
- # @return [Hash] the JSON response
42
+ # Make a PATCH request to the given path with the given params
43
+ # @param path [String] the path to the API endpoint
44
+ # @param params [Hash] the request body
45
+ # @return [Hash] the parsed JSON response
52
46
  def patch(path, params)
53
47
  uri = URI.parse("https://api.github.com/#{path}")
54
48
  request = Net::HTTP::Patch.new(uri)
49
+
50
+ request.body = params.to_json
51
+
52
+ response = _http_request(uri: uri, request: request)
53
+
54
+ JSON.parse(response.body)
55
+ end
56
+
57
+ private
58
+
59
+ def _http_request(uri:, request:)
55
60
  request["Accept"] = "application/vnd.github+json"
56
61
  request["Authorization"] = "Bearer #{@api_key}"
57
62
  request["X-Github-Api-Version"] = "2022-11-28"
@@ -60,13 +65,22 @@ module GHX
60
65
  use_ssl: uri.scheme == "https"
61
66
  }
62
67
 
63
- request.body = params.to_json
64
-
65
68
  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
66
69
  http.request(request)
67
70
  end
68
71
 
69
- JSON.parse(response.body)
72
+ if response.code.to_i < 400
73
+ response
74
+ elsif [403, 429].include?(response.code.to_i)
75
+ if response["X-RateLimit-Remaining"].to_i == 0
76
+ reset_time = Time.at(response["X-RateLimit-Reset"].to_i)
77
+ raise GHX::RateLimitExceededError, "GitHub API rate limit exceeded. Try again after #{reset_time}"
78
+ else
79
+ raise GHX::RateLimitExceededError, "GitHub API rate limit exceeded. Try again later."
80
+ end
81
+ else
82
+ raise GHX::OtherApiError, "GitHub API returned an error: #{response.code} #{response.body}"
83
+ end
70
84
  end
71
85
  end
72
86
  end
data/lib/ghx.rb CHANGED
@@ -13,6 +13,7 @@ class Hash
13
13
  end
14
14
 
15
15
  require_relative "version"
16
+ require_relative "ghx/errors"
16
17
  require_relative "ghx/graphql_client"
17
18
  require_relative "ghx/rest_client"
18
19
  require_relative "ghx/dependabot"
@@ -25,35 +26,85 @@ require_relative "ghx/project_item"
25
26
  # Extra classes to support more OO interfaces to the GitHub API. Wraps both the REST API and GraphQL API. Currently
26
27
  # incomplete. Functionality has been built for our existing use-cases, but nothing else.
27
28
  module GHX
29
+ # Defaults to $stdout
30
+ # @return [Logger]
28
31
  def self.logger
29
32
  @logger ||= Logger.new($stdout)
30
33
  end
31
34
 
35
+ # @param logger [Logger]
32
36
  def self.logger=(logger)
33
37
  @logger = logger
34
38
  end
35
39
 
40
+ # Internal octokit client.
41
+ # API Key defaults to ENV["GITHUB_TOKEN"]
42
+ # @return [Octokit::Client]
36
43
  def self.octokit
37
- @octokit ||= Octokit::Client.new(access_token: ENV["GITHUB_TOKEN"])
44
+ @octokit ||= Octokit::Client.new(access_token: octokit_token)
38
45
  end
39
46
 
47
+ # @param octokit [Octokit::Client]
48
+ # @return [Octokit::Client]
40
49
  def self.octokit=(octokit)
41
50
  @octokit = octokit
42
51
  end
43
52
 
53
+ # @return [String] the API Key for the Octokit client
54
+ def self.octokit_token
55
+ @octokit_token ||= ENV["GITHUB_TOKEN"]
56
+ end
57
+
58
+ # @param new_token [String] the API Key for the Octokit client
59
+ def self.octokit_token=(new_token)
60
+ @octokit_token = new_token
61
+ end
62
+
63
+ # Internal graphql client.
64
+ # API Key defaults to ENV["GITHUB_TOKEN"]
65
+ # @return [GHX::GraphqlClient]
44
66
  def self.graphql
45
- @graphql ||= GHX::GraphqlClient.new(ENV["GITHUB_GRAPHQL_TOKEN"])
67
+ @graphql ||= GHX::GraphqlClient.new(graphql_token)
46
68
  end
47
69
 
70
+ # @param graphql [GHX::GraphqlClient]
71
+ # @return [GHX::GraphqlClient]
48
72
  def self.graphql=(graphql)
49
73
  @graphql = graphql
50
74
  end
51
75
 
76
+ # @return [String] the API Key for the GraphQL client
77
+ def self.graphql_token
78
+ @graphql_token ||= ENV["GITHUB_GRAPHQL_TOKEN"]
79
+ end
80
+
81
+ # @param new_token [String] the API Key for the GraphQL client
82
+ # @return [String]
83
+ def self.graphql_token=(new_token)
84
+ @graphql_token = new_token
85
+ end
86
+
87
+ # Internal graphql client.
88
+ # API Key defaults to ENV["GITHUB_TOKEN"]
89
+ # @return [GHX::RestClient]
52
90
  def self.rest_client
53
- @rest_client ||= GHX::RestClient.new(ENV["GITHUB_TOKEN"])
91
+ @rest_client ||= GHX::RestClient.new(rest_client_token)
54
92
  end
55
93
 
94
+ # @param rest_client [GHX::RestClient]
95
+ # @return [GHX::RestClient]
56
96
  def self.rest_client=(rest_client)
57
97
  @rest_client = rest_client
58
98
  end
99
+
100
+ # @return [String] the API Key for the REST client
101
+ def self.rest_client_token
102
+ @rest_client_token ||= ENV["GITHUB_TOKEN"]
103
+ end
104
+
105
+ # @param new_token [String] the API Key for the REST client
106
+ # @return [String]
107
+ def self.rest_client_token=(new_token)
108
+ @rest_client_token = new_token
109
+ end
59
110
  end
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module GHX
2
- VERSION = "0.2.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ghx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - CompanyCam
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-21 00:00:00.000000000 Z
11
+ date: 2024-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: octokit
@@ -106,6 +106,7 @@ files:
106
106
  - lib/ghx/dependabot/alert.rb
107
107
  - lib/ghx/dependabot/package.rb
108
108
  - lib/ghx/dependabot/security_vulnerability.rb
109
+ - lib/ghx/errors.rb
109
110
  - lib/ghx/graphql_client.rb
110
111
  - lib/ghx/issue.rb
111
112
  - lib/ghx/project.rb