Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.finos.gitproxy.db.model.PushQuery;
import org.finos.gitproxy.db.model.PushRecord;
import org.finos.gitproxy.db.model.PushStatus;
import org.finos.gitproxy.db.model.PushSummary;

/**
* Storage abstraction for push records. Implementations exist for in-memory, JDBC (H2, SQLite, Postgres), and MongoDB.
Expand All @@ -28,6 +29,30 @@ public interface PushStore {
/** Query pushes with optional filters. */
List<PushRecord> find(PushQuery query);

/**
* Return lightweight summary projections for the list view. Omits all child collections (steps, commits,
* attestation). Default implementation delegates to {@link #find} and projects in memory; JDBC override uses a lean
* SELECT.
*/
default List<PushSummary> findSummaries(PushQuery query) {
return find(query).stream()
.map(r -> PushSummary.builder()
.id(r.getId())
.status(r.getStatus())
.url(r.getUrl())
.upstreamUrl(r.getUpstreamUrl())
.project(r.getProject())
.repoName(r.getRepoName())
.branch(r.getBranch())
.commitTo(r.getCommitTo())
.author(r.getAuthor())
.user(r.getUser())
.resolvedUser(r.getResolvedUser())
.timestamp(r.getTimestamp())
.build())
.toList();
}

/** Delete a push record and all associated data. */
void delete(String id);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,39 @@ public List<PushRecord> find(PushQuery query) {
return results;
}

@Override
public List<PushSummary> findSummaries(PushQuery query) {
MapSqlParameterSource params = new MapSqlParameterSource();
String where = buildWhere(query, params);
String sql =
"SELECT id, status, url, upstream_url, project, repo_name, branch, commit_to, author, push_user, resolved_user, timestamp"
+ " FROM push_records" + where
+ " ORDER BY timestamp " + (query.isNewestFirst() ? "DESC" : "ASC")
+ " LIMIT :limit OFFSET :offset";
params.addValue("limit", query.getLimit());
params.addValue("offset", query.getOffset());
return jdbc.query(
sql,
params,
(rs, rowNum) -> PushSummary.builder()
.id(rs.getString("id"))
.status(PushStatus.valueOf(rs.getString("status")))
.url(rs.getString("url"))
.upstreamUrl(rs.getString("upstream_url"))
.project(rs.getString("project"))
.repoName(rs.getString("repo_name"))
.branch(rs.getString("branch"))
.commitTo(rs.getString("commit_to"))
.author(rs.getString("author"))
.user(rs.getString("push_user"))
.resolvedUser(rs.getString("resolved_user"))
.timestamp(
rs.getTimestamp("timestamp") != null
? rs.getTimestamp("timestamp").toInstant()
: null)
.build());
}

@Override
public List<RepoPushSummary> summarizeByRepo() {
return jdbc.query(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.finos.gitproxy.db.model;

import java.time.Instant;
import lombok.Builder;
import lombok.Value;

/**
* Lightweight projection of a push record for list views. Omits all {@link PushStep}, {@link PushCommit}, and
* {@link Attestation} data to keep list-endpoint responses small.
*/
@Value
@Builder
public class PushSummary {
String id;
PushStatus status;
String url;
String upstreamUrl;
String project;
String repoName;
String branch;
String commitTo;
String author;
String user;
String resolvedUser;
Instant timestamp;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.finos.gitproxy.db.model.PushRecord;
import org.finos.gitproxy.db.model.PushStatus;
import org.finos.gitproxy.db.model.PushStep;
import org.finos.gitproxy.db.model.PushSummary;
import org.finos.gitproxy.db.model.StepStatus;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -349,6 +350,50 @@ void find_bySearch_matchesProjectAndRepoName() {
assertEquals("widget-service", byRepo.get(0).getRepoName());
}

// ---- findSummaries ----

@Test
void findSummaries_returnsProjectionWithoutChildCollections() {
PushRecord saved = PushRecord.builder()
.commitTo("abc123")
.branch("refs/heads/main")
.repoName("repo")
.project("acme")
.upstreamUrl("https://github.com/acme/repo.git")
.author("Alice")
.user("alice")
.resolvedUser("alice")
.status(PushStatus.FORWARDED)
.build();
store.save(saved);

List<PushSummary> summaries = store.findSummaries(PushQuery.builder().build());

assertEquals(1, summaries.size());
PushSummary s = summaries.get(0);
assertEquals(saved.getId(), s.getId());
assertEquals(PushStatus.FORWARDED, s.getStatus());
assertEquals("https://github.com/acme/repo.git", s.getUpstreamUrl());
assertEquals("refs/heads/main", s.getBranch());
assertEquals("abc123", s.getCommitTo());
assertEquals("Alice", s.getAuthor());
assertEquals("alice", s.getUser());
assertEquals("alice", s.getResolvedUser());
assertNotNull(s.getTimestamp());
}

@Test
void findSummaries_filtersApplied() {
store.save(record("a", "refs/heads/main", "repoA"));
store.save(record("b", "refs/heads/main", "repoB"));

List<PushSummary> results =
store.findSummaries(PushQuery.builder().repoName("repoA").build());

assertEquals(1, results.size());
assertEquals("repoA", results.get(0).getRepoName());
}

// ---- initialize idempotency ----

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.finos.gitproxy.db.model.PushRecord;
import org.finos.gitproxy.db.model.PushStatus;
import org.finos.gitproxy.db.model.PushStep;
import org.finos.gitproxy.db.model.PushSummary;
import org.finos.gitproxy.jetty.config.AttestationQuestion;
import org.finos.gitproxy.jetty.config.GitProxyConfig;
import org.finos.gitproxy.jetty.reload.ConfigHolder;
Expand Down Expand Up @@ -55,7 +56,7 @@ private static String resolveReviewer(Map<String, String> body) {
*/
@Operation(operationId = "listPushes", summary = "List push records")
@GetMapping
public List<PushRecord> list(
public List<PushSummary> list(
@RequestParam(required = false) String status,
@RequestParam(required = false) String project,
@RequestParam(required = false) String repo,
Expand All @@ -82,7 +83,7 @@ public List<PushRecord> list(
if (user != null && !user.isBlank()) query.user(user);
if (search != null && !search.isBlank()) query.search(search);

return pushStore.find(query.build());
return pushStore.findSummaries(query.build());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ private void loginAs(String username, boolean admin, boolean selfCertify) {
class List_ {
@Test
void noFilters_delegatesToStore() {
when(pushStore.find(any())).thenReturn(java.util.List.of());
when(pushStore.findSummaries(any())).thenReturn(java.util.List.of());
var result = controller.list(null, null, null, null, null, 50, 0, true);
assertEquals(0, result.size());
verify(pushStore).find(argThat(q -> q.getLimit() == 50 && q.getOffset() == 0));
verify(pushStore).findSummaries(argThat(q -> q.getLimit() == 50 && q.getOffset() == 0));
}

@Test
Expand All @@ -115,9 +115,9 @@ void invalidStatus_throws400() {

@Test
void validStatus_passedToQuery() {
when(pushStore.find(any())).thenReturn(java.util.List.of());
when(pushStore.findSummaries(any())).thenReturn(java.util.List.of());
controller.list("PENDING", null, null, null, null, 50, 0, true);
verify(pushStore).find(argThat(q -> q.getStatus() == PushStatus.PENDING));
verify(pushStore).findSummaries(argThat(q -> q.getStatus() == PushStatus.PENDING));
}
}

Expand Down
Loading