Skip to content

Commit

Permalink
Add asAppScopedClient() function for convenience
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchhentgesspotify committed Sep 11, 2024
1 parent 7cf19e5 commit 178662d
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/main/java/com/spotify/github/async/Async.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

package com.spotify.github.async;

import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Stream;

import static java.util.stream.StreamSupport.stream;
Expand All @@ -34,4 +36,19 @@ public static <T> Stream<T> streamFromPaginatingIterable(final Iterable<AsyncPag
return stream(iterable.spliterator(), false)
.flatMap(page -> stream(page.spliterator(), false));
}

public static <T> CompletableFuture<T> exceptionallyCompose(
final CompletableFuture<T> future, final Function<Throwable, CompletableFuture<T>> handler) {

return future
.handle(
(result, throwable) -> {
if (throwable != null) {
return handler.apply(throwable);
} else {
return CompletableFuture.completedFuture(result);
}
})
.thenCompose(Function.identity());
}
}
35 changes: 35 additions & 0 deletions src/main/java/com/spotify/github/v3/clients/GitHubClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@

import com.fasterxml.jackson.core.type.TypeReference;
import com.spotify.github.Tracer;
import com.spotify.github.async.Async;
import com.spotify.github.jackson.Json;
import com.spotify.github.v3.Team;
import com.spotify.github.v3.User;
import com.spotify.github.v3.checks.AccessToken;
import com.spotify.github.v3.checks.Installation;
import com.spotify.github.v3.comment.Comment;
import com.spotify.github.v3.exceptions.ReadOnlyRepositoryException;
import com.spotify.github.v3.exceptions.RequestNotOkException;
Expand All @@ -53,6 +55,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
Expand All @@ -71,6 +74,7 @@
public class GitHubClient {

private static final int EXPIRY_MARGIN_IN_MINUTES = 5;
private static final int HTTP_NOT_FOUND = 404;

private Tracer tracer = NoopTracer.INSTANCE;

Expand Down Expand Up @@ -367,6 +371,37 @@ public GitHubClient withScopeForInstallationId(final int installationId) {
installationId);
}

/**
* This is for clients authenticated as a GitHub App: when performing operations,
* the "installation" of the App must be specified.
* This returns a {@code GitHubClient} that has been scoped to the
* user's/organization's installation of the app, if any.
*/
public CompletionStage<Optional<GitHubClient>> asAppScopedClient(final String owner) {
return Async.exceptionallyCompose(this
.createOrganisationClient(owner)
.createGithubAppClient()
.getInstallation()
.thenApply(Installation::id), e -> {
if (e.getCause() instanceof RequestNotOkException && ((RequestNotOkException) e).statusCode() == HTTP_NOT_FOUND) {
return this
.createUserClient(owner)
.createGithubAppClient()
.getUserInstallation()
.thenApply(Installation::id);
}
return CompletableFuture.failedFuture(e);
})
.thenApply(id -> Optional.of(this.withScopeForInstallationId(id)))
.exceptionally(
e -> {
if (e.getCause() instanceof RequestNotOkException && ((RequestNotOkException) e).statusCode() == HTTP_NOT_FOUND) {
return Optional.empty();
}
throw new RuntimeException(e);
});
}

public GitHubClient withTracer(final Tracer tracer) {
this.tracer = tracer;
return this;
Expand Down

0 comments on commit 178662d

Please sign in to comment.