paginate common app pipeline history by repository
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { Controller, Get } from '@nestjs/common';
|
import { Controller, Get, Param, Query } from '@nestjs/common';
|
||||||
|
|
||||||
import { WoodpeckerService } from './woodpecker.service';
|
import { WoodpeckerService } from './woodpecker.service';
|
||||||
|
|
||||||
@@ -10,4 +10,16 @@ export class WoodpeckerController {
|
|||||||
listRepos() {
|
listRepos() {
|
||||||
return this.woodpeckerService.listRepos();
|
return this.woodpeckerService.listRepos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('repos/:repoId/pipelines')
|
||||||
|
listRepoPipelines(
|
||||||
|
@Param('repoId') repoId: string,
|
||||||
|
@Query('page') page?: string,
|
||||||
|
@Query('limit') limit?: string,
|
||||||
|
) {
|
||||||
|
return this.woodpeckerService.listRepoPipelines(repoId, {
|
||||||
|
page: Number(page) || 1,
|
||||||
|
limit: Number(limit) || 5,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,32 @@ export class WoodpeckerService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async listRepoPipelines(repoId: string, input: { page?: number; limit?: number }) {
|
||||||
|
this.assertToken();
|
||||||
|
|
||||||
|
const page = Math.max(1, input.page || 1);
|
||||||
|
const limit = Math.min(50, Math.max(1, input.limit || 5));
|
||||||
|
const body = await this.request<unknown>(
|
||||||
|
`/api/repos/${encodeURIComponent(repoId)}/pipelines?page=${page}&limit=${limit + 1}`,
|
||||||
|
);
|
||||||
|
const rows = Array.isArray(body)
|
||||||
|
? body
|
||||||
|
: isRecord(body) && Array.isArray(body.pipelines)
|
||||||
|
? body.pipelines
|
||||||
|
: [];
|
||||||
|
const pipelines = rows
|
||||||
|
.filter(isRecord)
|
||||||
|
.slice(0, limit)
|
||||||
|
.map((pipeline) => normalizePipeline(pipeline));
|
||||||
|
|
||||||
|
return {
|
||||||
|
page,
|
||||||
|
pageSize: limit,
|
||||||
|
hasNext: rows.length > limit,
|
||||||
|
pipelines,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private async getLatestPipeline(repo: WoodpeckerRepo): Promise<WoodpeckerPipeline> {
|
private async getLatestPipeline(repo: WoodpeckerRepo): Promise<WoodpeckerPipeline> {
|
||||||
const embeddedPipeline = getPipeline(repo);
|
const embeddedPipeline = getPipeline(repo);
|
||||||
if (getPipelineTime(embeddedPipeline) > 0) return embeddedPipeline;
|
if (getPipelineTime(embeddedPipeline) > 0) return embeddedPipeline;
|
||||||
@@ -91,23 +117,39 @@ export class WoodpeckerService {
|
|||||||
function normalizeRepo(repo: WoodpeckerRepo, pipeline = getPipeline(repo), baseUrl = '') {
|
function normalizeRepo(repo: WoodpeckerRepo, pipeline = getPipeline(repo), baseUrl = '') {
|
||||||
const createdAt = getPipelineTime(pipeline);
|
const createdAt = getPipelineTime(pipeline);
|
||||||
const repository = getString(repo.full_name) || getString(repo.fullName) || joinRepoName(repo) || getString(repo.name) || '-';
|
const repository = getString(repo.full_name) || getString(repo.fullName) || joinRepoName(repo) || getString(repo.name) || '-';
|
||||||
const commitSha = getCommitSha(pipeline);
|
const normalizedPipeline = normalizePipeline(pipeline);
|
||||||
const durationSeconds = getPipelineDurationSeconds(pipeline);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: `${getString(repo.id) || repository}-${getString(pipeline.id) || getString(pipeline.number) || createdAt}`,
|
id: `${getString(repo.id) || repository}-${normalizedPipeline.id || normalizedPipeline.number || createdAt}`,
|
||||||
|
repoId: getString(repo.id) || null,
|
||||||
repository,
|
repository,
|
||||||
message: getString(pipeline.message) || getString(pipeline.title) || getString(pipeline.event) || '-',
|
number: normalizedPipeline.number,
|
||||||
branch: getString(pipeline.branch) || '-',
|
message: normalizedPipeline.message,
|
||||||
commitSha,
|
branch: normalizedPipeline.branch,
|
||||||
durationSeconds,
|
commitSha: normalizedPipeline.commitSha,
|
||||||
status: getString(pipeline.status) || '-',
|
durationSeconds: normalizedPipeline.durationSeconds,
|
||||||
|
status: normalizedPipeline.status,
|
||||||
createdAt,
|
createdAt,
|
||||||
ciUrl: baseUrl || null,
|
ciUrl: baseUrl || null,
|
||||||
url: getString(repo.link_url) || getString(repo.forge_url) || getString(repo.url) || null,
|
url: getString(repo.link_url) || getString(repo.forge_url) || getString(repo.url) || null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizePipeline(pipeline: WoodpeckerPipeline) {
|
||||||
|
const createdAt = getPipelineTime(pipeline);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: getString(pipeline.id) || getString(pipeline.number) || String(createdAt || ''),
|
||||||
|
number: getNumber(pipeline.number),
|
||||||
|
message: getString(pipeline.message) || getString(pipeline.title) || getString(pipeline.event) || '-',
|
||||||
|
branch: getString(pipeline.branch) || '-',
|
||||||
|
commitSha: getCommitSha(pipeline),
|
||||||
|
durationSeconds: getPipelineDurationSeconds(pipeline),
|
||||||
|
status: getString(pipeline.status) || '-',
|
||||||
|
createdAt,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function getPipeline(repo: WoodpeckerRepo): WoodpeckerPipeline {
|
function getPipeline(repo: WoodpeckerRepo): WoodpeckerPipeline {
|
||||||
const pipeline = repo.last_pipeline ?? repo.pipeline;
|
const pipeline = repo.last_pipeline ?? repo.pipeline;
|
||||||
return isRecord(pipeline) ? pipeline : {};
|
return isRecord(pipeline) ? pipeline : {};
|
||||||
@@ -161,6 +203,11 @@ function getString(value: unknown) {
|
|||||||
return typeof value === 'string' || typeof value === 'number' ? String(value) : '';
|
return typeof value === 'string' || typeof value === 'number' ? String(value) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getNumber(value: unknown) {
|
||||||
|
const number = typeof value === 'number' ? value : typeof value === 'string' ? Number(value) : NaN;
|
||||||
|
return Number.isFinite(number) ? number : null;
|
||||||
|
}
|
||||||
|
|
||||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||||
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user