Skip to content

Commit

Permalink
Merge branch '3.0.x' into 3.1.x
Browse files Browse the repository at this point in the history
Closes gh-2344
  • Loading branch information
marcusdacoregio committed Jul 13, 2023
2 parents 50fa05a + f154bf5 commit 140008e
Show file tree
Hide file tree
Showing 12 changed files with 854 additions and 0 deletions.
19 changes: 19 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ buildscript {
}

apply plugin: 'io.spring.convention.root'
apply plugin: 'org.springframework.security.update-dependencies'

group = 'org.springframework.session'
description = 'Spring Session'
Expand All @@ -46,3 +47,21 @@ nohttp {
source.exclude "spring-session-docs/.gradle/nodejs/**"
source.exclude "spring-session-docs/modules/ROOT/examples/**/build/**"
}

updateDependenciesSettings {
gitHub {
organization = "spring-projects"
repository = "spring-session"
}
dependencyExcludes {
majorVersionBump()
minorVersionBump()
alphaBetaVersions()
snapshotVersions()
}
addFiles({
return [
project.file("gradle/dependency-management.gradle")
]
})
}
5 changes: 5 additions & 0 deletions buildSrc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id "java-gradle-plugin"
id "java"
id "groovy"
id 'com.apollographql.apollo' version '2.4.5'
}

sourceCompatibility = JavaVersion.VERSION_11
Expand Down Expand Up @@ -46,6 +47,10 @@ gradlePlugin {
id = "org.springframework.propdeps"
implementationClass = "org.springframework.gradle.propdeps.PropDepsPlugin"
}
updateDependencies {
id = "org.springframework.security.update-dependencies"
implementationClass = "org.springframework.security.convention.versions.UpdateDependenciesPlugin"
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mutation CreateIssueInput($assigneeId: ID!, $labelIds: [ID!], $milestoneId: ID!, $repositoryId: ID!, $title: String!) {
createIssue(input: {assigneeIds: [$assigneeId], labelIds: $labelIds, milestoneId: $milestoneId, projectIds: [], repositoryId: $repositoryId, title: $title}) {
issue {
number
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
query FindCreateIssueInput($owner: String!, $name: String!, $labelQuery: String, $milestoneName: String) {
repository(owner: $owner, name: $name) {
id
labels(query: $labelQuery, first: 1) {
nodes {
id
name
}
}
milestones(query: $milestoneName, states: [OPEN], first: 1) {
nodes {
id
title
}
}
}
viewer {
id
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
query RateLimit {
rateLimit {
limit
cost
remaining
resetAt
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2019-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.security.convention.versions;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Scanner;

class CommandLineUtils {
static void runCommand(File dir, String... args) {
try {
Process process = new ProcessBuilder()
.directory(dir)
.command(args)
.start();
writeLinesTo(process.getInputStream(), System.out);
writeLinesTo(process.getErrorStream(), System.out);
if (process.waitFor() != 0) {
new RuntimeException("Failed to run " + Arrays.toString(args));
}
} catch (IOException | InterruptedException e) {
throw new RuntimeException("Failed to run " + Arrays.toString(args), e);
}
}

private static void writeLinesTo(InputStream input, PrintStream out) {
Scanner scanner = new Scanner(input);
while(scanner.hasNextLine()) {
out.println(scanner.nextLine());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2019-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.security.convention.versions;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.function.Function;

class FileUtils {
static void replaceFileText(File file, Function<String, String> replaceText) {
String buildFileText = readString(file);
String updatedBuildFileText = replaceText.apply(buildFileText);
writeString(file, updatedBuildFileText);
}

static String readString(File file) {
try {
byte[] bytes = Files.readAllBytes(file.toPath());
return new String(bytes);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}

private static void writeString(File file, String text) {
try {
Files.write(file.toPath(), text.getBytes());
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package org.springframework.security.convention.versions;

import java.io.IOException;
import java.time.Duration;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import com.apollographql.apollo.ApolloCall;
import com.apollographql.apollo.ApolloClient;
import com.apollographql.apollo.api.Input;
import com.apollographql.apollo.api.Response;
import com.apollographql.apollo.exception.ApolloException;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.jetbrains.annotations.NotNull;
import reactor.core.publisher.Mono;
import reactor.util.retry.RetrySpec;

public class GitHubApi {

private final ApolloClient apolloClient;

public GitHubApi(String githubToken) {
if (githubToken == null) {
throw new IllegalArgumentException("githubToken is required. You can set it using -PgitHubAccessToken=");
}
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
clientBuilder.addInterceptor(new AuthorizationInterceptor(githubToken));
this.apolloClient = ApolloClient.builder()
.serverUrl("https://api.github.com/graphql")
.okHttpClient(clientBuilder.build())
.build();
}

public Mono<FindCreateIssueResult> findCreateIssueInput(String owner, String name, String milestone) {
String label = "\"type: dependency-upgrade\"";
FindCreateIssueInputQuery findCreateIssueInputQuery = new FindCreateIssueInputQuery(owner, name, Input.optional(label), Input.optional(milestone));
return Mono.create( sink -> this.apolloClient.query(findCreateIssueInputQuery)
.enqueue(new ApolloCall.Callback<>() {
@Override
public void onResponse(@NotNull Response<FindCreateIssueInputQuery.Data> response) {
if (response.hasErrors()) {
sink.error(new RuntimeException(response.getErrors().stream().map(e -> e.getMessage()).collect(Collectors.joining(" "))));
} else {
FindCreateIssueInputQuery.Data data = response.getData();
FindCreateIssueInputQuery.Repository repository = data.repository();
List<String> labels = repository.labels().nodes().stream().map(FindCreateIssueInputQuery.Node::id).collect(Collectors.toList());
if (labels.isEmpty()) {
sink.error(new IllegalArgumentException("Could not find label for " + label));
return;
}
Optional<String> firstMilestoneId = repository.milestones().nodes().stream().map(FindCreateIssueInputQuery.Node1::id).findFirst();
if (!firstMilestoneId.isPresent()) {
sink.error(new IllegalArgumentException("Could not find OPEN milestone id for " + milestone));
return;
}
String milestoneId = firstMilestoneId.get();
String repositoryId = repository.id();
String assigneeId = data.viewer().id();
sink.success(new FindCreateIssueResult(repositoryId, labels, milestoneId, assigneeId));
}
}

@Override
public void onFailure(@NotNull ApolloException e) {
sink.error(e);
}
}));
}

public static class FindCreateIssueResult {
private final String repositoryId;
private final List<String> labelIds;
private final String milestoneId;
private final String assigneeId;

public FindCreateIssueResult(String repositoryId, List<String> labelIds, String milestoneId, String assigneeId) {
this.repositoryId = repositoryId;
this.labelIds = labelIds;
this.milestoneId = milestoneId;
this.assigneeId = assigneeId;
}

public String getRepositoryId() {
return repositoryId;
}

public List<String> getLabelIds() {
return labelIds;
}

public String getMilestoneId() {
return milestoneId;
}

public String getAssigneeId() {
return assigneeId;
}
}

public Mono<RateLimitQuery.RateLimit> findRateLimit() {
return Mono.create( sink -> this.apolloClient.query(new RateLimitQuery())
.enqueue(new ApolloCall.Callback<>() {
@Override
public void onResponse(@NotNull Response<RateLimitQuery.Data> response) {
if (response.hasErrors()) {
sink.error(new RuntimeException(response.getErrors().stream().map(e -> e.getMessage()).collect(Collectors.joining(" "))));
} else {
sink.success(response.getData().rateLimit());
}
}

@Override
public void onFailure(@NotNull ApolloException e) {
sink.error(e);
}
}));
}

public Mono<Integer> createIssue(String repositoryId, String title, List<String> labelIds, String milestoneId, String assigneeId) {
CreateIssueInputMutation createIssue = new CreateIssueInputMutation.Builder()
.repositoryId(repositoryId)
.title(title)
.labelIds(labelIds)
.milestoneId(milestoneId)
.assigneeId(assigneeId)
.build();
return Mono.create( sink -> this.apolloClient.mutate(createIssue)
.enqueue(new ApolloCall.Callback<>() {
@Override
public void onResponse(@NotNull Response<CreateIssueInputMutation.Data> response) {
if (response.hasErrors()) {
String message = response.getErrors().stream().map(e -> e.getMessage() + " " + e.getCustomAttributes() + " " + e.getLocations()).collect(Collectors.joining(" "));
if (message.contains("was submitted too quickly")) {
sink.error(new SubmittedTooQuick(message));
} else {
sink.error(new RuntimeException(message));
}
} else {
sink.success(response.getData().createIssue().issue().number());
}
}

@Override
public void onFailure(@NotNull ApolloException e) {
sink.error(e);
}
}))
.retryWhen(
RetrySpec.fixedDelay(3, Duration.ofMinutes(1))
.filter(SubmittedTooQuick.class::isInstance)
.doBeforeRetry(r -> System.out.println("Pausing for 1 minute and then retrying due to receiving \"submitted too quickly\" error from GitHub API"))
)
.cast(Integer.class);
}

public static class SubmittedTooQuick extends RuntimeException {
public SubmittedTooQuick(String message) {
super(message);
}
}

private static class AuthorizationInterceptor implements Interceptor {

private final String token;

public AuthorizationInterceptor(String token) {
this.token = token;
}

@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("Authorization", "Bearer " + this.token).build();
return chain.proceed(request);
}
}
}
Loading

0 comments on commit 140008e

Please sign in to comment.