lib/shipit/github_app.rb in shipit-engine-0.29.0 vs lib/shipit/github_app.rb in shipit-engine-0.30.0

- old
+ new

@@ -7,28 +7,40 @@ def from_github(github_response) new(github_response.token, github_response.expires_at) end end + attr_reader :expires_at, :refresh_at + def to_s @token end def initialize(token, expires_at) @token = token @expires_at = expires_at + + # This needs to be lower than the token's lifetime, but higher than the cache expiry setting. + @refresh_at = expires_at - GITHUB_TOKEN_REFRESH_WINDOW end def blank? - @expires_at.past? + # Old tokens missing @refresh_at may be used upon deploy, so we should auto-correct for now. + # TODO: Remove this assignment at a later date. + @refresh_at ||= @expires_at - GITHUB_TOKEN_REFRESH_WINDOW + @refresh_at.past? end end DOMAIN = 'github.com'.freeze AuthenticationFailed = Class.new(StandardError) API_STATUS_ID = 'brv1bkgrwx7q'.freeze + GITHUB_EXPECTED_TOKEN_LIFETIME = 60.minutes + GITHUB_TOKEN_RAILS_CACHE_LIFETIME = 50.minutes + GITHUB_TOKEN_REFRESH_WINDOW = GITHUB_EXPECTED_TOKEN_LIFETIME - GITHUB_TOKEN_RAILS_CACHE_LIFETIME - 2.minutes + attr_reader :oauth_teams, :domain, :bot_login def initialize(config) super() @config = (config || {}).with_indifferent_access @@ -77,17 +89,25 @@ @token = @token.presence || synchronize { @token.presence || fetch_new_token } @token.to_s end def fetch_new_token - Rails.cache.fetch('github:integration:access-token', expires_in: 50.minutes, race_condition_ttl: 10.minutes) do + # Rails can add 5 minutes to the cache entry expiration time when any TTL is provided, + # so our TTL setting can be lower, and TTL + expires_in should be lower than the GitHub token expiration. + Rails.cache.fetch( + 'github:integration:access-token', + expires_in: GITHUB_TOKEN_RAILS_CACHE_LIFETIME, + race_condition_ttl: 4.minutes, + ) do response = new_client(bearer_token: authentication_payload).create_app_installation_access_token( installation_id, accept: 'application/vnd.github.machine-man-preview+json', ) token = Token.from_github(response) raise AuthenticationFailed if token.blank? + Rails.logger.info("Created GitHub access token ending #{token.to_s[-5..-1]}, expires at #{token.expires_at}"\ + " and will be refreshed at #{token&.refresh_at}") token end end def oauth? @@ -118,15 +138,24 @@ def api_endpoint url('/api/v3/') if enterprise? end + def web_endpoint + url if enterprise? + end + def enterprise? domain != DOMAIN end def new_client(options = {}) - options.reverse_merge(api_endpoint: api_endpoint) if api_endpoint + if enterprise? + options = options.reverse_merge( + api_endpoint: api_endpoint, + web_endpoint: web_endpoint, + ) + end client = Octokit::Client.new(options) client.middleware = faraday_stack client end