captive-stack-detector 0.12.4 → 0.12.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b90c2a1855bd23b857f4f142a0c674795992d33a98512e4b7a1cbcfb7db5df7f
4
- data.tar.gz: 49a6d7ae837f68ed2e0995fcb8623249ceb93168ddac120108c5b032c93afff5
3
+ metadata.gz: e5c9cf6e0559903b9b472715ed1d425903be96cdf7ca09c4689a66f63df7b19f
4
+ data.tar.gz: 7146a542cf6d2887063172c47a0d8f85251d3e7e02062969c8ee04882c321398
5
5
  SHA512:
6
- metadata.gz: d430ba6a7b0077093dff4a48d756b106e5f47c64f8fe981d7fbf18c5c0c89035ff8dd045e6b2da56d9705f607ab0d0a626e67247f72aa51771fb4c1b5b972c1f
7
- data.tar.gz: a89e85828b1be7b804c4ef860ddc7664a3354e8c78c719714c3cd16229a0eca4d85f1084d3be6248d16a5f706d8e87d7b0a83642c2551390c90d04db75ad50e9
6
+ metadata.gz: d2162dfa8b2aa58308fb3523677fba79ffba3cd7abb7fa980bd2466408bc8347519845ec93bb83b8d751b308e504488c4f2edc56a2147132634ef288de5e78b1
7
+ data.tar.gz: 65b1daea44aa2172b74e215d3d6fd55b87e94ae6dc5115657605dee8ee880dbc5e4f0b2f04db139348cab9c34883a33d07a131e32fe5377db6256368531de625
@@ -5,9 +5,14 @@ require "uri"
5
5
  require "base64"
6
6
  require "json"
7
7
  require_relative "github_tree"
8
+ require_relative "types"
9
+ require_relative "github_response"
8
10
 
9
11
  module CaptiveStackDetector
10
12
  class GithubApiClient
13
+ # Un corps illisible (JSON invalide ou sans le champ attendu) vaut une absence.
14
+ UNREADABLE = [ JSON::ParserError, NoMethodError, TypeError ].freeze
15
+
11
16
  def initialize(token, repo)
12
17
  @token = token
13
18
  @repo = repo
@@ -18,7 +23,7 @@ module CaptiveStackDetector
18
23
  return nil unless body
19
24
 
20
25
  Base64.decode64(JSON.parse(body)["content"]).force_encoding("utf-8")
21
- rescue StandardError
26
+ rescue *UNREADABLE
22
27
  nil
23
28
  end
24
29
 
@@ -27,7 +32,7 @@ module CaptiveStackDetector
27
32
  return [] unless body
28
33
 
29
34
  GithubTree.new(body).files_in(dir)
30
- rescue StandardError
35
+ rescue *UNREADABLE
31
36
  []
32
37
  end
33
38
 
@@ -35,9 +40,10 @@ module CaptiveStackDetector
35
40
 
36
41
  def get(path)
37
42
  uri = URI("https://api.github.com/repos/#{@repo}/#{path}")
38
- req = Net::HTTP::Get.new(uri, "Authorization" => "Bearer #{@token}", "Accept" => "application/vnd.github+json")
39
- res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
40
- res.body if res.is_a?(Net::HTTPSuccess)
43
+ GithubResponse.body(Net::HTTP.get_response(uri, "Authorization" => "Bearer #{@token}",
44
+ "Accept" => "application/vnd.github+json"))
45
+ rescue SystemCallError, IOError, SocketError, Timeout::Error, OpenSSL::SSL::SSLError => e
46
+ raise SourceUnavailable.new(:network, detail: e.message)
41
47
  end
42
48
  end
43
49
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require_relative "types"
5
+
6
+ module CaptiveStackDetector
7
+ # Ce que veut dire une réponse de l'API GitHub : un corps, une absence, ou un refus nommé.
8
+ # Change avec la façon dont GitHub signale ses erreurs, pas avec ce que l'on y lit.
9
+ module GithubResponse
10
+ # 404 : fichier absent ; 409 : dépôt vide. Tout autre échec vient de GitHub, pas du dépôt.
11
+ ABSENT = [ "404", "409" ].freeze
12
+ REFUSALS = { "401" => :unauthorized, "429" => :rate_limited }.freeze
13
+
14
+ def self.body(res)
15
+ return res.body if res.is_a?(Net::HTTPSuccess)
16
+ return nil if ABSENT.include?(res.code)
17
+
18
+ raise SourceUnavailable.new(refusal_kind(res), status: res.code.to_i)
19
+ end
20
+
21
+ # GitHub signale un quota épuisé par un 403 ou un 429, avec x-ratelimit-remaining à 0.
22
+ def self.refusal_kind(res)
23
+ return :rate_limited if res["x-ratelimit-remaining"] == "0"
24
+
25
+ REFUSALS.fetch(res.code) { res.is_a?(Net::HTTPServerError) ? :server_error : :forbidden }
26
+ end
27
+ end
28
+ end
@@ -26,4 +26,17 @@ module CaptiveStackDetector
26
26
  super(reason&.to_s || "unsupported stack")
27
27
  end
28
28
  end
29
+
30
+ # GitHub n'a pas laissé lire le dépôt, ce qui ne dit rien de sa stack. `kind` dit pourquoi,
31
+ # pour que l'appelant l'explique : :unauthorized (jeton refusé), :rate_limited (quota épuisé),
32
+ # :forbidden (accès refusé), :server_error (panne GitHub), :network (pas de réponse).
33
+ class SourceUnavailable < StandardError
34
+ attr_reader :kind, :status
35
+
36
+ def initialize(kind = :network, status: nil, detail: nil)
37
+ @kind = kind
38
+ @status = status
39
+ super(detail || "GitHub illisible : #{kind}#{" (#{status})" if status}")
40
+ end
41
+ end
29
42
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CaptiveStackDetector
4
- VERSION = "0.12.4"
4
+ VERSION = "0.12.5"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: captive-stack-detector
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.4
4
+ version: 0.12.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Captive Studio
@@ -29,6 +29,7 @@ files:
29
29
  - lib/captive_stack_detector/gem_package_map.rb
30
30
  - lib/captive_stack_detector/gemfile_analyzer.rb
31
31
  - lib/captive_stack_detector/github_api_client.rb
32
+ - lib/captive_stack_detector/github_response.rb
32
33
  - lib/captive_stack_detector/github_tree.rb
33
34
  - lib/captive_stack_detector/js_env_detector.rb
34
35
  - lib/captive_stack_detector/js_env_files.rb