Skip to content

Commit d424294

Browse files
committed
Continue building out tooling around paging
1 parent 9706647 commit d424294

File tree

15 files changed

+234
-12
lines changed

15 files changed

+234
-12
lines changed

src/main/java/org/sourcelab/buildkite/api/client/request/BuildFilters.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,30 @@ public PageOptions getPageOptions() {
127127
return pageOptions;
128128
}
129129

130+
public String getOrgIdSlug() {
131+
return orgIdSlug;
132+
}
133+
134+
public boolean hasOrgIdSlug() {
135+
return orgIdSlug != null;
136+
}
137+
138+
public String getPipelineIdSlug() {
139+
return pipelineIdSlug;
140+
}
141+
142+
public boolean hasPipelineIdSlug() {
143+
return hasOrgIdSlug() && pipelineIdSlug != null;
144+
}
145+
146+
public Long getBuildNumber() {
147+
return buildNumber;
148+
}
149+
150+
public boolean hasBuildNumber() {
151+
return hasPipelineIdSlug() && buildNumber != null;
152+
}
153+
130154
@Override
131155
public String toString() {
132156
return "BuildRequestOptions{"

src/main/java/org/sourcelab/buildkite/api/client/request/ListBuildsRequest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ public ListBuildsRequest(final BuildFilters filters) {
4141

4242
@Override
4343
public String getPath() {
44+
// TODO need to urlencode these?
45+
if (filters.hasBuildNumber()) {
46+
return "/v2/organizations/" + filters.getOrgIdSlug() + "/pipelines/" + filters.getPipelineIdSlug() + "/builds/" + filters.getBuildNumber();
47+
} else if (filters.hasPipelineIdSlug()) {
48+
return "/v2/organizations/" + filters.getOrgIdSlug() + "/pipelines/" + filters.getPipelineIdSlug() + "/builds";
49+
} else if (filters.hasOrgIdSlug()) {
50+
return "/v2/organizations/" + filters.getOrgIdSlug() + "/builds";
51+
}
4452
return "/v2/builds";
4553
}
4654

src/main/java/org/sourcelab/buildkite/api/client/request/PageOptions.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
* Paging options.
2626
*/
2727
public class PageOptions {
28-
private final int page;
28+
private final long page;
2929
private final int perPage;
3030

3131
private static final PageOptions DEFAULT = new PageOptions(1, 30);
@@ -43,7 +43,7 @@ public static PageOptions getDefault() {
4343
* @param page Which page to request.
4444
* @param perPage How many entries per page.
4545
*/
46-
public PageOptions(int page, int perPage) {
46+
public PageOptions(long page, int perPage) {
4747
if (page < 0) {
4848
page = 1;
4949
}
@@ -90,7 +90,7 @@ public static PageOptions fromUrl(final String url) {
9090
return new PageOptions(page, perPage);
9191
}
9292

93-
public int getPage() {
93+
public long getPage() {
9494
return page;
9595
}
9696

src/main/java/org/sourcelab/buildkite/api/client/request/Request.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
import java.io.IOException;
2525
import java.util.Collections;
26-
import java.util.Map;
2726

2827
/**
2928
* Defines an API request.

src/main/java/org/sourcelab/buildkite/api/client/response/ListBuildsResponse.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ public List<Build> getBuilds() {
6868
return builds;
6969
}
7070

71+
/**
72+
* The total number of builds found.
73+
* @return The total number of builds found.
74+
*/
75+
public int countBuilds() {
76+
return getBuilds().size();
77+
}
78+
7179
/**
7280
* Get all build Ids.
7381
* @return All build ids.

src/main/java/org/sourcelab/buildkite/api/client/response/PagingLinks.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
package org.sourcelab.buildkite.api.client.response;
1919

20+
import org.sourcelab.buildkite.api.client.request.PageOptions;
21+
2022
/**
2123
* Represents the 'Link' header for paging results.
2224
*/
@@ -108,6 +110,19 @@ public String getLastUrl() {
108110
return lastUrl;
109111
}
110112

113+
/**
114+
* If the Last Page URL is populated, calculate the total number of entries.
115+
* @return If the Last Page URL is populated, calculate the total number of entries.
116+
* @throws IllegalStateException If the Last Url is not defined.
117+
*/
118+
public long getTotalNumberOfEntries() {
119+
if (!hasLastUrl()) {
120+
throw new IllegalStateException("Last Url is not defined, cannot determine total number of entries.");
121+
}
122+
final PageOptions pageOptions = PageOptions.fromUrl(getLastUrl());
123+
return ((long) pageOptions.getPage()) * ((long) pageOptions.getPerPage());
124+
}
125+
111126
@Override
112127
public String toString() {
113128
return "LinkHeader{"

src/main/java/org/sourcelab/buildkite/api/client/response/parser/JacksonFactory.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import com.fasterxml.jackson.databind.DeserializationFeature;
2121
import com.fasterxml.jackson.databind.ObjectMapper;
2222
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
23-
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
2423
import com.fasterxml.jackson.databind.type.MapType;
2524
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
2625

src/main/java/org/sourcelab/buildkite/api/client/response/parser/ListBuildsResponseParser.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@
1818
package org.sourcelab.buildkite.api.client.response.parser;
1919

2020
import com.fasterxml.jackson.core.JsonProcessingException;
21+
import org.slf4j.Logger;
22+
import org.slf4j.LoggerFactory;
2123
import org.sourcelab.buildkite.api.client.http.HttpResult;
2224
import org.sourcelab.buildkite.api.client.request.ListBuildsRequest;
2325
import org.sourcelab.buildkite.api.client.response.Build;
24-
import org.sourcelab.buildkite.api.client.response.PagingLinks;
2526
import org.sourcelab.buildkite.api.client.response.ListBuildsResponse;
27+
import org.sourcelab.buildkite.api.client.response.PagingLinks;
2628

2729
import java.util.Arrays;
2830

2931
public class ListBuildsResponseParser implements ResponseParser<ListBuildsResponse> {
32+
private static final Logger logger = LoggerFactory.getLogger(ListBuildsResponseParser.class);
3033
private final ListBuildsRequest originalRequest;
3134

3235
public ListBuildsResponseParser(final ListBuildsRequest originalRequest) {
@@ -35,7 +38,7 @@ public ListBuildsResponseParser(final ListBuildsRequest originalRequest) {
3538

3639
@Override
3740
public ListBuildsResponse parseResponse(final HttpResult result) throws JsonProcessingException {
38-
41+
logger.info(result.getContent());
3942
final PagingLinks pagingLinks;
4043
if (result.getHttpHeaders().hasHeader("Link")) {
4144
// Parse out the link header.

src/main/java/org/sourcelab/buildkite/api/client/response/parser/ListEmojisResponseParser.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,8 @@
1919

2020
import org.sourcelab.buildkite.api.client.http.HttpResult;
2121
import org.sourcelab.buildkite.api.client.response.Emoji;
22-
import org.sourcelab.buildkite.api.client.response.PingResponse;
2322

2423
import java.io.IOException;
25-
import java.util.ArrayList;
2624
import java.util.Arrays;
2725
import java.util.List;
2826
import java.util.stream.Collectors;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* Copyright 2023 SourceLab.org https://github.com/SourceLabOrg/Buildkite-Api-Client
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5+
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
6+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
7+
* persons to whom the Software is furnished to do so, subject to the following conditions:
8+
*
9+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
10+
* Software.
11+
*
12+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13+
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
14+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
15+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16+
*/
17+
18+
package org.sourcelab.buildkite.api.client.util;
19+
20+
import org.sourcelab.buildkite.api.client.BuildkiteClient;
21+
import org.sourcelab.buildkite.api.client.request.BuildFilters;
22+
import org.sourcelab.buildkite.api.client.request.ListBuildsRequest;
23+
import org.sourcelab.buildkite.api.client.request.PageOptions;
24+
import org.sourcelab.buildkite.api.client.response.Build;
25+
import org.sourcelab.buildkite.api.client.response.ListBuildsResponse;
26+
27+
import java.util.ArrayList;
28+
import java.util.List;
29+
30+
/**
31+
* Collection of Utilities for common access patterns that consists of multiple
32+
* requests to the Buildkite REST Api.
33+
*/
34+
public class BuildkiteClientUtils {
35+
36+
/**
37+
* Helper method to retrieve the N **newest** builds given the supplied search criteria.
38+
* The results will be ordered from NEWEST to OLDEST.
39+
*
40+
* @param numberOfBuilds How many builds to retrieve, (artificially) limited to max of 100.
41+
* @param filters Search criteria.
42+
* @param client The BuildkiteClient to execute the requests against.
43+
* @return List of Builds sorted from NEWEST to OLDEST.
44+
*/
45+
public static List<Build> retrieveNewestBuilds(final int numberOfBuilds, final BuildFilters filters, final BuildkiteClient client) {
46+
// Create request
47+
final ListBuildsRequest request = new ListBuildsRequest(filters);
48+
request.updatePageOptions(new PageOptions(1, 1));
49+
50+
// Retrieve first entry only, to determine how many total entries there are.
51+
final ListBuildsResponse lookupResponse = client.executeRequest(request);
52+
final long totalNumberOfEntries = lookupResponse.getPagingLinks().getTotalNumberOfEntries();
53+
54+
/**
55+
* Assumption is that we can only pull at max, the last 100 entries as that is the maximum that
56+
* the API can return in a single request.
57+
* This method could be updated pretty easily to support larger numbers, submit a PR :)
58+
*/
59+
final long pageNumber = totalNumberOfEntries / numberOfBuilds;
60+
request.updatePageOptions(new PageOptions(pageNumber, numberOfBuilds));
61+
62+
// Execute the request for the correct page of results.
63+
final ListBuildsResponse response = client.executeRequest(request);
64+
65+
// But the results are still sorted in oldest to newest, we want newest to oldest, so reverse the order
66+
// before returning.
67+
final List<Build> reversed = new ArrayList<>(response.getBuilds());
68+
return reversed;
69+
}
70+
}

0 commit comments

Comments
 (0)