Skip to content

Commit f71a83a

Browse files
fix: make gerrit repo fetching paginated (#114)
* fix: make gerrit repo fetching paginated In some cases gerrit will limit the number of projects returned by /projects endpoint, forcing the client to paginate their request to get all projects. This fulfills this requirement to get all projects * Add some more metadata repo projects to ignore list --------- Co-authored-by: Brendan Kellam <[email protected]>
1 parent 77198bd commit f71a83a

File tree

2 files changed

+30
-14
lines changed

2 files changed

+30
-14
lines changed

packages/backend/src/gerrit.ts

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface GerritWebLink {
2323

2424
const logger = createLogger('Gerrit');
2525

26-
export const getGerritReposFromConfig = async (config: GerritConfig, ctx: AppContext) => {
26+
export const getGerritReposFromConfig = async (config: GerritConfig, ctx: AppContext): Promise<GitRepository[]> => {
2727

2828
const url = config.url.endsWith('/') ? config.url : `${config.url}/`;
2929
const hostname = new URL(config.url).hostname;
@@ -35,6 +35,8 @@ export const getGerritReposFromConfig = async (config: GerritConfig, ctx: AppCon
3535
// exclude "All-Projects" and "All-Users" projects
3636
delete projects['All-Projects'];
3737
delete projects['All-Users'];
38+
delete projects['All-Avatars']
39+
delete projects['All-Archived-Projects']
3840

3941
logger.debug(`Fetched ${Object.keys(projects).length} projects in ${durationMs}ms.`);
4042

@@ -90,20 +92,35 @@ export const getGerritReposFromConfig = async (config: GerritConfig, ctx: AppCon
9092
};
9193

9294
const fetchAllProjects = async (url: string): Promise<GerritProjects> => {
93-
9495
const projectsEndpoint = `${url}projects/`;
95-
logger.debug(`Fetching projects from Gerrit at ${projectsEndpoint}...`);
96-
const response = await fetch(projectsEndpoint);
96+
let allProjects: GerritProjects = {};
97+
let start = 0; // Start offset for pagination
98+
let hasMoreProjects = true;
9799

98-
if (!response.ok) {
99-
throw new Error(`Failed to fetch projects from Gerrit: ${response.statusText}`);
100-
}
100+
while (hasMoreProjects) {
101+
const endpointWithParams = `${projectsEndpoint}?S=${start}`;
102+
logger.debug(`Fetching projects from Gerrit at ${endpointWithParams}`);
103+
104+
const response = await fetch(endpointWithParams);
105+
if (!response.ok) {
106+
throw new Error(`Failed to fetch projects from Gerrit: ${response.statusText}`);
107+
}
101108

102-
const text = await response.text();
109+
const text = await response.text();
110+
const jsonText = text.replace(")]}'\n", ''); // Remove XSSI protection prefix
111+
const data: GerritProjects = JSON.parse(jsonText);
112+
113+
// Merge the current batch of projects with allProjects
114+
Object.assign(allProjects, data);
115+
116+
// Check if there are more projects to fetch
117+
hasMoreProjects = Object.values(data).some(
118+
(project) => (project as any)._more_projects === true
119+
);
120+
121+
// Update the offset based on the number of projects in the current response
122+
start += Object.keys(data).length;
123+
}
103124

104-
// Gerrit prepends ")]}'\n" to prevent XSSI attacks; remove it
105-
// https://gerrit-review.googlesource.com/Documentation/rest-api.html
106-
const jsonText = text.replace(")]}'\n", '');
107-
const data = JSON.parse(jsonText);
108-
return data;
125+
return allProjects;
109126
};

packages/backend/src/schemas/v2.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,6 @@ export interface GerritConfig {
192192
*/
193193
projects?: string[];
194194
};
195-
revisions?: GitRevisions;
196195
}
197196
export interface LocalConfig {
198197
/**

0 commit comments

Comments
 (0)