bundler-alive 0.1.6 → 0.1.7

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: c3e48b8f0f5a030f9b537e4150f6b10e5bdf3ed709cde30162d2030b3292cbc6
4
- data.tar.gz: dff1d8579c996eeb24c599e2a40ba48b778d2939af8e80f3da94ed133a4ac0b5
3
+ metadata.gz: 4fb0738fac56612f49d0fcc2dadf41f00caa5c34b8e49923185326f3cc6ab744
4
+ data.tar.gz: e89352dbbdec31b5e82e4f42135113d1c464441bcc0d4443709e24437fffb87f
5
5
  SHA512:
6
- metadata.gz: 94d793718656beddd079aaa083fe501b2775a8b658d361b19d5c56906abba39551dd6f84628904c98235db7bc381028fb3ce261bb09178d00154ea3f682e2757
7
- data.tar.gz: 4e4977e62794f2f9cd403187c4d60063788f8589ddef358beb2ba49827b65b7b3be6c64d563489b0c90938fe94f02b98af88fdf6bc93f29ea12bdc29ffc399a5
6
+ metadata.gz: 6692e5114833643c5038b41a8bbff0282837b4e70c05449f76cc810e499751a3f7f8585f5360f31b503376662e6a91f6617a335e59686a9841af65a2917b0d2f
7
+ data.tar.gz: 393f54894aabd833bd0249a54cfab165bbcacb6a9d10cae9ab446b6e81a92c9de83f5e0fc25d38327999b7c2e06fa902a730bbec5eb04b37a476af0067b882c4
@@ -53,4 +53,18 @@ gems:
53
53
  thrift:
54
54
  url: https://github.com/szechyjs/thrift-gem
55
55
  vmstat:
56
- url: https://github.com/threez/ruby-vmstat
56
+ url: https://github.com/threez/ruby-vmstat
57
+ mongoid-rspec:
58
+ url: https://github.com/mongoid/mongoid-rspec
59
+ rack-test:
60
+ url: https://github.com/rack/rack-test
61
+ jmespath:
62
+ url: https://github.com/jmespath/jmespath.rb
63
+ slack-notifier:
64
+ url: https://github.com/slack-notifier/slack-notifier
65
+ ipaddress:
66
+ url: https://github.com/ipaddress-gem/ipaddress
67
+ fog-powerdns:
68
+ url: https://github.com/fog/fog-powerdns
69
+ html_tokenizer:
70
+ url: https://github.com/EiNSTeiN-/html_tokenizer
data/.rspec CHANGED
@@ -1,5 +1,4 @@
1
1
  --format documentation
2
2
  --color
3
- --warnings
4
3
  --require spec_helper
5
4
  --backtrace
data/README.md CHANGED
@@ -5,14 +5,14 @@
5
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/a79d53257bc5e93842f6/maintainability)](https://codeclimate.com/github/kyoshidajp/bundler-alive/maintainability)
6
6
  [![Test Coverage](https://api.codeclimate.com/v1/badges/a79d53257bc5e93842f6/test_coverage)](https://codeclimate.com/github/kyoshidajp/bundler-alive/test_coverage)
7
7
 
8
- `bunder-alive` checks if gems in a RubyGem's `Gemfile.lock` are active.
8
+ `bundler-alive` checks if gems in a RubyGem's `Gemfile.lock` are active.
9
9
 
10
- Currently GitHub.com and GitLab.com are supported as a source code repository. If the source code repository is archived, then reports as not alive.
10
+ Currently, GitHub.com and GitLab.com are supported as a source code repository. If the source code repository is archived, then reports as not alive.
11
11
 
12
12
  ## Installation
13
13
 
14
14
  ```
15
- $ gem install bunlder-alive
15
+ $ gem install bundler-alive
16
16
  ```
17
17
 
18
18
  ## Usage
@@ -41,26 +41,29 @@ Default `Gemfile.lock` location is in your current directory. You can specify it
41
41
  $ bundle-alive -G /path/to/Gemfile.lock
42
42
  ```
43
43
 
44
- ## GitLab Access Token
44
+ ## Access Token
45
45
 
46
- When gems are in GitLab.com repository, you MUST set environment variable `BUNDLER_ALIVE_GITLAB_TOKEN`. See the document [Personal access tokens](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html).
46
+ You MUST set environment variables to access source code repository services.
47
47
 
48
- ## Exceeding rate limit
48
+ | Repository service | ENV variable |
49
+ | ------- |---- |
50
+ | GitHub | [`BUNDLER_ALIVE_GITHUB_TOKEN`](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) |
51
+ | GitLab | [`BUNDLER_ALIVE_GITLAB_TOKEN`](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) |
49
52
 
50
- In some cases, the following error may be output.
53
+ ## Ignore gems
54
+
55
+ You can ignore certain gems.
51
56
 
52
57
  ```
53
- Too many requested! Retry later.
58
+ $ bundle-alive -i journey rubocop-junit-formatter
54
59
  ```
55
60
 
56
- In this case, setting [GitHub Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) as `BUNDLER_ALIVE_GITHUB_TOKEN` environment variable may alleviate the error.
61
+ ## Following redirect on RubyGems.org
57
62
 
58
- ## Ignore gems
59
-
60
- You can ignore certain gems.
63
+ The URL for some gems in RubyGems.org may have changed. You can follow the URL (default: doesn't follow).
61
64
 
62
65
  ```
63
- $ bundle-alive -i journey rubocop-junit-formatter
66
+ $ bundle-alive --follow_redirect
64
67
  ```
65
68
 
66
69
  ## Specifying repository URL
data/gemspec.yml CHANGED
@@ -8,7 +8,7 @@ homepage: https://github.com/kyoshidajp/bundler-alive
8
8
  metadata:
9
9
  homepage_uri: https://github.com/kyoshidajp/bundler-alive
10
10
  source_code_uri: https://github.com/kyoshidajp/bundler-alive
11
- changelog_uri: https://github.com/kyoshidajp/bundler-alive
11
+ changelog_uri: https://github.com/kyoshidajp/bundler-alive/commits/main
12
12
 
13
13
  required_ruby_version: ">= 2.6.0"
14
14
  bindir: bin
@@ -16,7 +16,7 @@ require_paths: lib
16
16
 
17
17
  dependencies:
18
18
  faraday:
19
- octokit:
19
+ graphql-client:
20
20
  rake:
21
21
  thor:
22
22
  gitlab:
@@ -17,6 +17,7 @@ module Bundler
17
17
 
18
18
  desc "check [DIR]", "Checks the Gemfile.lock"
19
19
  method_option :ignore, type: :array, aliases: "-i", default: []
20
+ method_option :follow_redirect, type: :boolean, aliases: "-r"
20
21
  method_option :gemfile_lock, type: :string, aliases: "-G",
21
22
  default: "Gemfile.lock"
22
23
  method_option :config, type: :string, aliases: "-c", default: ".bundler-alive.yml"
@@ -49,7 +50,10 @@ module Bundler
49
50
  end
50
51
 
51
52
  def initialize_doctor
52
- Doctor.new(options[:gemfile_lock], options[:config], options[:ignore])
53
+ Doctor.new(lock_file: options[:gemfile_lock],
54
+ config_file: options[:config],
55
+ ignore_gems: options[:ignore],
56
+ follow_redirect: options[:follow_redirect])
53
57
  rescue Bundler::GemfileLockNotFound
54
58
  exit 1
55
59
  end
@@ -21,13 +21,16 @@ module Bundler
21
21
  #
22
22
  # A new instance of `GemApiClient`
23
23
  #
24
- # @param [String] config_path
24
+ # @param [String] :config_path
25
+ # @param [Boolean] :follow_redirect
26
+ # Follow redirect URL in gems
25
27
  #
26
28
  # @return [GemApiClient]
27
29
  #
28
- def initialize(config_path = nil)
30
+ def initialize(config_path: nil, follow_redirect: false)
29
31
  @error_messages = []
30
32
  @config_gems = get_config_gems(config_path)
33
+ @follow_redirect = follow_redirect
31
34
 
32
35
  freeze
33
36
  end
@@ -53,7 +56,7 @@ module Bundler
53
56
 
54
57
  private
55
58
 
56
- attr_accessor :error_messages, :config_gems
59
+ attr_accessor :error_messages, :config_gems, :follow_redirect
57
60
 
58
61
  def api_url(gem_name)
59
62
  "https://rubygems.org/api/v1/gems/#{gem_name}.json"
@@ -122,6 +125,8 @@ module Bundler
122
125
  end
123
126
 
124
127
  def url_via_redirect(url)
128
+ return url unless follow_redirect
129
+
125
130
  response = connection.head(url)
126
131
  return response.headers["location"] if response.status == 301
127
132
 
@@ -1,15 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "octokit"
4
3
  require "json"
5
4
 
6
5
  module Bundler
7
6
  module Alive
8
7
  module Client
9
8
  #
10
- # API Client for GitHub API
9
+ # API Client for GitHub GraphQL API
11
10
  #
12
- # @see https://docs.github.com/en/rest/search#search-repositories
11
+ # @see https://docs.github.com/en/graphql
13
12
  #
14
13
  module GithubApi
15
14
  # Environment variable name of GitHub Access Token
@@ -17,27 +16,10 @@ module Bundler
17
16
 
18
17
  # Separator of query condition
19
18
  QUERY_CONDITION_SEPARATOR = " "
19
+ private_constant :QUERY_CONDITION_SEPARATOR
20
20
 
21
- # Number of attempts to request after too many requests
22
- RETRIES_ON_TOO_MANY_REQUESTS = 3
23
-
24
- #
25
- # Interval second when retrying request
26
- #
27
- # @note
28
- # This is an empirical value and should
29
- # refer to response of Rate Limit API
30
- #
31
- # @see
32
- # https://docs.github.com/en/rest/overview/resources-in-the-rest-api#checking-your-rate-limit-status
33
- RETRY_INTERVAL_SEC_ON_TOO_MANY_REQUESTS = 120
34
-
35
- #
36
21
  # Max number of conditional operator at once
37
- #
38
- # @see https://docs.github.com/en/rest/search#limitations-on-query-length
39
- QUERY_MAX_OPERATORS_AT_ONCE = 6
40
-
22
+ QUERY_MAX_OPERATORS_AT_ONCE = 50
41
23
  private_constant :QUERY_MAX_OPERATORS_AT_ONCE
42
24
 
43
25
  def self.extended(base)
@@ -49,12 +31,15 @@ module Bundler
49
31
  end
50
32
 
51
33
  #
52
- # Creates a GitHub client
34
+ # Creates a GraphQL client
53
35
  #
54
- # @return [Octokit::Client]
36
+ # @return [GraphQL::Client]
55
37
  #
56
38
  def create_client
57
- Octokit::Client.new(access_token: ENV.fetch(ACCESS_TOKEN_ENV_NAME, nil))
39
+ require_relative "github_graphql"
40
+ extend GithubGraphql
41
+
42
+ GithubGraphql::CLIENT
58
43
  end
59
44
 
60
45
  #
@@ -111,7 +96,7 @@ module Bundler
111
96
  alive_status = if repository.nil?
112
97
  Status::ALIVE_UNKNOWN
113
98
  else
114
- repository["archived"]
99
+ repository["isArchived"]
115
100
  end
116
101
  name_with_status[url.gem_name] = alive_status
117
102
  end
@@ -126,21 +111,24 @@ module Bundler
126
111
  # @return [Sawyer::Resource|nil]
127
112
  def find_repository_from_repositories(url:, repositories:)
128
113
  repositories.find do |repository|
129
- slug(url.url) == repository["full_name"]
114
+ # e.g.) tod's URL is https://github.com/JackC/tod
115
+ # but, the `nameWithOwner` is `jacks/tod`
116
+ slug(url.url).downcase == repository["nameWithOwner"].downcase
130
117
  end
131
118
  end
132
119
 
133
120
  #
134
- # Search query of repositories
121
+ # Search query of repositories (includes forked)
135
122
  #
136
123
  # @param [Array<RepositoryUrl>] urls
137
124
  #
138
125
  # @return [String]
139
126
  #
140
127
  def search_query(urls)
141
- urls.map do |url|
128
+ repository_query = urls.map do |url|
142
129
  "repo:#{slug(url.url)}"
143
130
  end.join(QUERY_CONDITION_SEPARATOR)
131
+ "#{repository_query} fork:true"
144
132
  end
145
133
 
146
134
  #
@@ -148,18 +136,12 @@ module Bundler
148
136
  #
149
137
  # @param [String] query
150
138
  #
151
- # @raise [Octokit::TooManyRequests]
152
- # when too many requested to GitHub.com
153
- # @raise [SourceCodeClient::SearchRepositoryError]
154
- # when Error without `Octokit::TooManyRequests`
155
- #
156
139
  # @return [Array<Sawyer::Resource>|nil]
157
140
  #
158
141
  def search_repositories(query)
159
- result = @client.search_repositories(query)
160
- result[:items]
161
- rescue Octokit::TooManyRequests => e
162
- raise e
142
+ result = @client.query(GithubGraphql::Query,
143
+ variables: { var_query: query, var_first: QUERY_MAX_OPERATORS_AT_ONCE })
144
+ result.data.search.nodes.map(&:to_h)
163
145
  rescue StandardError => e
164
146
  @error_messages << e.message
165
147
  []
@@ -167,21 +149,6 @@ module Bundler
167
149
 
168
150
  def search_repositories_with_retry(query)
169
151
  search_repositories(query)
170
- rescue Octokit::TooManyRequests
171
- if @retries_on_too_many_requests < RETRIES_ON_TOO_MANY_REQUESTS
172
- @retries_on_too_many_requests += 1
173
- sleep_with_message
174
- retry
175
- end
176
-
177
- @rate_limit_exceeded = true
178
- []
179
- end
180
-
181
- def sleep_with_message
182
- puts "Too many requested to GitHub. Sleep #{RETRY_INTERVAL_SEC_ON_TOO_MANY_REQUESTS} sec."
183
- sleep RETRY_INTERVAL_SEC_ON_TOO_MANY_REQUESTS
184
- puts "Retry request (#{@retries_on_too_many_requests}/#{RETRIES_ON_TOO_MANY_REQUESTS})"
185
152
  end
186
153
 
187
154
  #
@@ -192,7 +159,13 @@ module Bundler
192
159
  # @return [String]
193
160
  #
194
161
  def slug(repository_url)
195
- Octokit::Repository.from_url(repository_url).slug.gsub(/\.git/, "")
162
+ # from https://github.com/octokit/octokit.rb/blob/v4.22.0/lib/octokit/repository.rb#L12-L17
163
+ github_slug = URI.parse(repository_url).path[1..]
164
+ .gsub(%r{^repos/}, "")
165
+ .split("/", 3)[0..1]
166
+ .join("/")
167
+
168
+ github_slug.gsub(/\.git/, "")
196
169
  end
197
170
  end
198
171
  end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/client"
4
+ require "graphql/client/http"
5
+
6
+ module Bundler
7
+ module Alive
8
+ module Client
9
+ # GitHub GraphQL Module
10
+ module GithubGraphql
11
+ #
12
+ # Access token isn't set error
13
+ #
14
+ # @see https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token
15
+ #
16
+ class AccessTokenNotFoundError < StandardError
17
+ def initialize(_message = nil)
18
+ message = "Environment variable #{ACCESS_TOKEN_ENV_NAME} is not set."\
19
+ " Need to set GitHub Personal Access Token to be authenticated at GitHub GraphQL API."\
20
+ " See: https://docs.github.com/en/graphql/guides/forming-calls-with-graphql#the-graphql-endpoint"
21
+ super(message)
22
+ end
23
+ end
24
+
25
+ # Environment variable name of GitHub Access Token
26
+ ACCESS_TOKEN_ENV_NAME = "BUNDLER_ALIVE_GITHUB_TOKEN"
27
+
28
+ # GraphQL API endpoint
29
+ # @see https://docs.github.com/en/graphql/guides/forming-calls-with-graphql#the-graphql-endpoint
30
+ ENDPOINT = "https://api.github.com/graphql"
31
+ private_constant :ENDPOINT
32
+
33
+ QUERY = <<~QUERY
34
+ query($var_query: String!, $var_first: Int!) {
35
+ search(
36
+ query: $var_query
37
+ type: REPOSITORY
38
+ first: $var_first
39
+ ) {
40
+ repositoryCount
41
+ nodes {
42
+ ... on Repository {
43
+ isArchived
44
+ nameWithOwner
45
+ isMirror
46
+ }
47
+ }
48
+ }
49
+ }
50
+ QUERY
51
+ private_constant :QUERY
52
+
53
+ HTTP = GraphQL::Client::HTTP.new(ENDPOINT) do
54
+ def headers(_context)
55
+ token = ENV.fetch(ACCESS_TOKEN_ENV_NAME, nil)
56
+ raise AccessTokenNotFoundError if token.nil?
57
+
58
+ {
59
+ "Authorization" => "Bearer #{token}"
60
+ }
61
+ end
62
+ end
63
+ private_constant :HTTP
64
+
65
+ if File.exist?(SCHEMA_PATH)
66
+ SCHEMA = GraphQL::Client.load_schema(SCHEMA_PATH)
67
+ else
68
+ SCHEMA = GraphQL::Client.load_schema(HTTP)
69
+ Dir.mkdir(USER_PATH) unless Dir.exist?(USER_PATH)
70
+ GraphQL::Client.dump_schema(SCHEMA, SCHEMA_PATH)
71
+ end
72
+ private_constant :SCHEMA
73
+
74
+ # GraphQL client
75
+ CLIENT = GraphQL::Client.new(schema: SCHEMA, execute: HTTP)
76
+
77
+ # query
78
+ Query = CLIENT.parse(QUERY)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -45,7 +45,7 @@ module Bundler
45
45
  #
46
46
  # Creates a GitLab client
47
47
  #
48
- # @return [Octokit::Client]
48
+ # @return [Gitlab::Client]
49
49
  #
50
50
  def create_client
51
51
  access_token = ENV.fetch(ACCESS_TOKEN_ENV_NAME, nil)
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler"
4
- require "octokit"
5
4
 
6
5
  module Bundler
7
6
  module Alive
@@ -12,13 +11,14 @@ module Bundler
12
11
  #
13
12
  # A new instance of Doctor
14
13
  #
15
- # @param [String] lock_file lock file of gem
16
- # @param [String] config_file config file
17
- # @param [Array<String>] ignore_gems ignore gems
14
+ # @param [String] :lock_file # lock file of gem
15
+ # @param [String] :config_file # config file
16
+ # @param [Array<String>] :ignore_gems ignore gems
17
+ # @param [Boolean] :follow_redirect Follow redirect URL in gems
18
18
  #
19
- def initialize(lock_file, config_file, ignore_gems)
19
+ def initialize(lock_file:, config_file:, ignore_gems:, follow_redirect: false)
20
20
  @lock_file = lock_file
21
- @gem_client = Client::GemsApiClient.new(config_file)
21
+ @gem_client = Client::GemsApiClient.new(config_path: config_file, follow_redirect: follow_redirect)
22
22
  @ignore_gems = ignore_gems
23
23
  @result = nil
24
24
  @rate_limit_exceeded = false
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Bundler
4
4
  module Alive
5
- VERSION = "0.1.6"
5
+ VERSION = "0.1.7"
6
6
  end
7
7
  end
data/lib/bundler/alive.rb CHANGED
@@ -1,5 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ module Bundler
4
+ module Alive
5
+ USER_PATH = File.expand_path(File.join(Gem.user_home, ".local", "share", "bundler-alive"))
6
+ SCHEMA_PATH = File.join(USER_PATH, "schema.json")
7
+ end
8
+ end
9
+
3
10
  require_relative "alive/version"
4
11
  require_relative "alive/doctor"
5
12
  require_relative "alive/source_code_repository"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundler-alive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katsuhiko YOSHIDA
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-22 00:00:00.000000000 Z
11
+ date: 2022-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: octokit
28
+ name: graphql-client
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -209,6 +209,7 @@ files:
209
209
  - lib/bundler/alive/client/gems_api_client.rb
210
210
  - lib/bundler/alive/client/gems_api_response.rb
211
211
  - lib/bundler/alive/client/github_api.rb
212
+ - lib/bundler/alive/client/github_graphql.rb
212
213
  - lib/bundler/alive/client/gitlab_api.rb
213
214
  - lib/bundler/alive/client/source_code_client.rb
214
215
  - lib/bundler/alive/doctor.rb
@@ -225,7 +226,7 @@ licenses: []
225
226
  metadata:
226
227
  homepage_uri: https://github.com/kyoshidajp/bundler-alive
227
228
  source_code_uri: https://github.com/kyoshidajp/bundler-alive
228
- changelog_uri: https://github.com/kyoshidajp/bundler-alive
229
+ changelog_uri: https://github.com/kyoshidajp/bundler-alive/commits/main
229
230
  rubygems_mfa_required: 'true'
230
231
  post_install_message:
231
232
  rdoc_options: []