Trouble Fetching GitHub Pull Requests by Date Range in Java Using OkHttp

158 Views Asked by At

I'm working on a Java program to retrieve pull requests from a GitHub repository within a specified date range using OkHttp and the GitHub API. However, I'm encountering issues where the code doesn't seem to filter pull requests correctly based on the date range.

I'm using OkHttp to make a GET request to the GitHub API to fetch pull requests from a specific repository.

I want to filter the pull requests based on their creation date, and I'm using the 'created' parameter in the API URL to specify the date range. The dates are correctly formatted in ISO 8601 format ('yyyy-MM-dd').

Despite setting the date range, the API response doesn't seem to be filtering the pull requests as expected. I'm still receiving pull requests outside the specified date range.

package ConsumeGithubAPI;

import com.google.gson.*;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import java.io.IOException;

public class ConsumeGithubAPI {
    public static void main(String[] args) {
        JsonArray pullRequests = getPullRequests("-Owner-", "-reponame-", "2022-06-01", "2022-07-10");
        String formattedOutput = formatOutput(pullRequests);
        System.out.println(formattedOutput);
    }

    public static JsonArray getPullRequests(String owner, String repositoryName, String startDate, String endDate) {

        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("https://api.github.com/repos/" + owner + "/" + repositoryName + "/pulls" +
                        "?state=all&per_page=100&page=1" +
                        "&since=" + startDate + "T00:00:00Z" +
                        "&until=" + endDate + "T23:59:59Z")
                .addHeader("Authorization", "-token-")
                .build();
        JsonArray modifiedPRs = new JsonArray();
        try {
            Response response = client.newCall(request).execute();
            String responseBody = response.body().string();

            JsonArray pullRequests = JsonParser.parseString(responseBody).getAsJsonArray();

            for (JsonElement pR : pullRequests) {
                JsonObject prObject = pR.getAsJsonObject();
                JsonObject prData = new JsonObject();
                prData.addProperty("id", prObject.get("id").getAsBigInteger());
                prData.addProperty("user", prObject.get("user").getAsJsonObject().get("login").getAsString());
                prData.addProperty("title", prObject.get("title").getAsString());
                prData.addProperty("state", prObject.get("state").getAsString());
                prData.addProperty("created_at", prObject.get("created_at").getAsString());
                modifiedPRs.add(prData);

            }
            response.close();
            return modifiedPRs;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return modifiedPRs;
    }

    private static String formatOutput(JsonArray jsonArray) {
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        return gson.toJson(jsonArray);
    }
}

What I've tried:

I've checked the date formatting to ensure it's correct. I've verified that the repository exists and contains pull requests within the date range. I've reviewed the GitHub API documentation to confirm the correct parameter usage.

1

There are 1 best solutions below

0
dani-vta On

The request List pull requests does not provide the query parameters since and until. That's why it is returning pull requests that don't fall within the given range. The only query parameters allowed are: state, head, base, sort, direction, per_page and page. See the documentation below:

https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#list-pull-requests

I think you might be mixing up the request with List repositories for the authenticated user, which instead accepts the query parameters since and after and allows you to filter repositories for their update date.

https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#list-repositories-for-the-authenticated-user

It seems from the documentation that there are no requests that allow you to filter pull requests by their creation date. The only thing you could do is get the pull requests of a repository and then filter them manually.

Your code could look something like this:

public class ConsumeGithubAPI {

    static final DateTimeFormatter GITHUB_DATE_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssz");
    static final String CONFIG = "auth.properties";


    public static void main(String[] args) throws IOException {
        JsonArray pullRequests = getPullRequests("-Owner-", "-reponame-", "2022-06-01", "2022-07-10");
        String formattedOutput = formatOutput(pullRequests);
        System.out.println(formattedOutput);
    }

    public static JsonArray getPullRequests(String owner, String repositoryName, String startDate, String endDate) throws IOException {
        Properties prop = new Properties();

        try {
            //Reading the authorization token from a config file
            InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(CONFIG);
            if (Objects.isNull(stream)) {
                System.err.printf("Configuration file %s couldn't be found among the program's resources...\n", CONFIG);
                return null;
            }
            prop.load(stream);
        } catch (SecurityException ex) {
            System.err.printf("Caller does not have the RuntimePermission: %s\n", ex.getLocalizedMessage());
            return null;
        } catch (IOException ex) {
            System.err.printf("Couldn't read properties: %s\n", ex.getLocalizedMessage());
            return null;
        }

        //Parameterizing the URL building (using actual variables would be better as it achieves actual parameterization, this snippet only shows how to  build URLs with HttpUrl)
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(new HttpUrl.Builder()
                        .scheme("https")
                        .host("api.github.com")
                        .addPathSegment("repos")
                        .addPathSegment(owner)
                        .addPathSegment(repositoryName)
                        .addPathSegment("pulls")
                        .addQueryParameter("state", "all")
                        .addQueryParameter("per_page", "100")
                        .addQueryParameter("page", "1")
                        .build())
                .addHeader("Authorization", "Bearer " + prop.get("auth"))
                .build();

        //Parsing the response
        JsonArray modifiedPRs = new JsonArray();
        try (Response response = client.newCall(request).execute()) {
            String responseBody = response.body().string();
            JsonArray pullRequests = JsonParser.parseString(responseBody).getAsJsonArray();

            //Employing the LocalDateTime classes to better handle date confrontations
            LocalDateTime tempDateTime;
            LocalDateTime startDateTime = LocalDate.parse(startDate, DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay();
            LocalDateTime endDateTime = LocalDate.parse(endDate, DateTimeFormatter.ISO_LOCAL_DATE).plusDays(1).atStartOfDay();

            for (JsonElement pR : pullRequests) {
                JsonObject prObject = pR.getAsJsonObject();

                //Reading the creation date of the current pull request
                tempDateTime = LocalDateTime.parse(prObject.get("created_at").getAsString(), GITHUB_DATE_TIME_FORMAT);

                //Here we assume that the range boundaries are included.
                //The end date has been converted to the next given date to better cover (and include) every hour of the original end date.
                //Skipping the pull request if its creation date/time is lower than the start date or greater/equal than the date following end.
                if (tempDateTime.isBefore(startDateTime) || tempDateTime.isEqual(endDateTime) || tempDateTime.isAfter(endDateTime)) {
                    continue;
                }

                JsonObject prData = new JsonObject();
                prData.addProperty("id", prObject.get("id").getAsBigInteger());
                prData.addProperty("user", prObject.get("user").getAsJsonObject().get("login").getAsString());
                prData.addProperty("title", prObject.get("title").getAsString());
                prData.addProperty("state", prObject.get("state").getAsString());
                prData.addProperty("created_at", prObject.get("created_at").getAsString());
                modifiedPRs.add(prData);
            }
        }

        return modifiedPRs;
    }

    private static String formatOutput(JsonArray jsonArray) {
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        return gson.toJson(jsonArray);
    }
}

I've also added a full example with the properties file on my GitHub.

https://github.com/daniele-aveta/GitHubAPIGetModifiedPRs