Class: Entitlements::Service::GitHub

Inherits:
Object
  • Object
show all
Includes:
Contracts::Core
Defined in:
lib/entitlements/service/github.rb

Constant Summary collapse

C =
::Contracts
MAX_GRAPHQL_RESULTS =

This is a limitation of the GitHub API

100
MAX_GRAPHQL_RETRIES =

Retries to smooth over transient network blips

3
WAIT_BETWEEN_GRAPHQL_RETRIES =
1

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(addr: nil, org:, token:, ou:) ⇒ GitHub

Returns a new instance of GitHub.



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/entitlements/service/github.rb', line 36

def initialize(addr: nil, org:, token:, ou:)
  # Save some parameters for the connection but don't actually connect yet.
  @addr = addr
  @org = org
  @token = token
  @ou = ou

  # This is a global cache across all invocations of this object. GitHub membership
  # need to be obtained only one time per organization, but might be used multiple times.
  Entitlements.cache[:github_pending_members] ||= {}
  Entitlements.cache[:github_org_members] ||= {}
end

Instance Attribute Details

#addrObject (readonly)

Returns the value of attribute addr.



20
21
22
# File 'lib/entitlements/service/github.rb', line 20

def addr
  @addr
end

#orgObject (readonly)

Returns the value of attribute org.



20
21
22
# File 'lib/entitlements/service/github.rb', line 20

def org
  @org
end

#ouObject (readonly)

Returns the value of attribute ou.



20
21
22
# File 'lib/entitlements/service/github.rb', line 20

def ou
  @ou
end

#tokenObject (readonly)

Returns the value of attribute token.



20
21
22
# File 'lib/entitlements/service/github.rb', line 20

def token
  @token
end

Instance Method Details

#enterprise?Boolean

Returns:

  • (Boolean)


93
94
95
96
# File 'lib/entitlements/service/github.rb', line 93

def enterprise?
  meta = octokit.github_meta
  meta.key? :installed_version
end

#identifierObject



55
56
57
58
59
60
61
62
63
64
# File 'lib/entitlements/service/github.rb', line 55

def identifier
  @identifier ||= begin
    if addr.nil?
      "github.com"
    else
      u = URI(addr)
      u.host
    end
  end
end

#invalidate_org_members_predictive_cacheObject



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/entitlements/service/github.rb', line 134

def invalidate_org_members_predictive_cache
  # If the entry was not from the predictive cache in the first place, just return.
  # This really should not get called if that's the case, but regardless, we don't
  # want to pointlessly hit the API twice.
  return unless org_members_from_predictive_cache?

  # The entry did come from the predictive cache. Invalidate the entry, clear local
  # caches, and re-read the data from the API.
  Entitlements.logger.debug "Invalidating cache entries for cn=(admin|member),#{ou}"
  Entitlements::Data::Groups::Cached.invalidate("cn=admin,#{ou}")
  Entitlements::Data::Groups::Cached.invalidate("cn=member,#{ou}")
  Entitlements.cache[:github_org_members].delete(org_signature)
  org_members
  nil
end

#org_membersObject



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/entitlements/service/github.rb', line 74

def org_members
  Entitlements.cache[:github_org_members][org_signature] ||= begin
    roles = Entitlements::Backend::GitHubOrg::ORGANIZATION_ROLES.invert

    # Some basic stats are helpful for debugging
    data, cache = members_and_roles_from_graphql_or_cache
    result = data.map { |username, role| [username, roles.fetch(role)] }.to_h
    admin_count = result.count { |_, role| role == "admin" }
    member_count = result.count { |_, role| role == "member" }
    Entitlements.logger.debug "Currently #{org} has #{admin_count} admin(s) and #{member_count} member(s)"

    { cache: cache, value: result }
  end

  Entitlements.cache[:github_org_members][org_signature][:value]
end

#org_members_from_predictive_cache?Boolean

Returns:

  • (Boolean)


122
123
124
125
# File 'lib/entitlements/service/github.rb', line 122

def org_members_from_predictive_cache?
  org_members # Force this to be read if for some reason it has not been yet.
  Entitlements.cache[:github_org_members][org_signature][:cache] || false
end

#pending_membersObject



105
106
107
108
109
110
111
112
113
# File 'lib/entitlements/service/github.rb', line 105

def pending_members
  Entitlements.cache[:github_pending_members][org_signature] ||= begin
    # ghes does not support org invites
    return Set.new if enterprise?
    pm = pending_members_from_graphql
    Entitlements.logger.debug "Currently #{org} has #{pm.size} pending member(s)"
    pm
  end
end