public async Task <string> GetTokenForInstallationAsync(long installationId) { if (TryGetCachedToken(installationId, out AccessToken cachedToken)) { _logger.LogInformation($"Cached token obtained for GitHub installation {installationId}. Expires at {cachedToken.ExpiresAt}."); return(cachedToken.Token); } return(await _retry.RetryAsync( async() => { string jwt = _tokens.GetAppToken(); var appClient = new Octokit.GitHubClient(_gitHubClientOptions.Value.ProductHeader) { Credentials = new Credentials(jwt, AuthenticationType.Bearer) }; AccessToken token = await appClient.GitHubApps.CreateInstallationToken(installationId); _logger.LogInformation($"New token obtained for GitHub installation {installationId}. Expires at {token.ExpiresAt}."); UpdateTokenCache(installationId, token); return token.Token; }, ex => _logger.LogError(ex, $"Failed to get a github token for installation id {installationId}, retrying"), ex => ex is ApiException && ((ApiException)ex).StatusCode == HttpStatusCode.InternalServerError)); }
public async Task <long> GetInstallationId(string repositoryUrl) { string[] segments = new Uri(repositoryUrl, UriKind.Absolute).Segments; string org = segments[segments.Length - 2].TrimEnd('/').ToLowerInvariant(); if (HasCachedValue(org, out long installation)) { return(installation); } await _sem.WaitAsync(); try { if (HasCachedValue(org, out installation)) { return(installation); } _log.LogInformation("No cached installation token found for {org}", org); ImmutableDictionary <string, long> .Builder newCache = ImmutableDictionary.CreateBuilder <string, long>(); string appToken = _tokens.GetAppToken(); var client = new GitHubAppsClient( new ApiConnection( new Connection(_options.Value.ProductHeader) { Credentials = new Credentials(appToken, AuthenticationType.Bearer) } ) ); foreach (Installation i in await client.GetAllInstallationsForCurrent()) { string installedOrg = i.Account.Login.ToLowerInvariant(); _log.LogInformation("Found installation token for {org}, with id {id}", installedOrg, i.Id); newCache.Add(installedOrg, i.Id); } foreach (string key in _cache.Keys) { // Anything we had before but don't have now has been uninstalled, remove it if (newCache.TryAdd(key, 0)) { _log.LogInformation("Removed uninstalled org {org}", key); } } // If the current thing wasn't in this list, it's not installed, record that so when they ask again in // a few seconds, we don't have to re-query GitHub if (newCache.TryAdd(org, 0)) { _log.LogInformation("Removed uninstalled, but requested org {org}", org); } Interlocked.Exchange(ref _cache, newCache.ToImmutable()); _lastCached = DateTimeOffset.UtcNow; return(_cache[org]); } finally { _sem.Release(); } }