Skip to content

Commit b61d674

Browse files
committed
feat(ci): move in code for posting comment, generalized to any provider
1 parent d81b3ac commit b61d674

File tree

3 files changed

+113
-28
lines changed

3 files changed

+113
-28
lines changed

packages/ci/src/lib/comment.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import fs from 'node:fs/promises';
2+
import type { Logger, ProviderAPIClient } from './models';
3+
4+
export async function commentOnPR(
5+
mdPath: string,
6+
api: ProviderAPIClient,
7+
logger: Logger,
8+
): Promise<number> {
9+
const markdown = await fs.readFile(mdPath, 'utf8');
10+
const identifier = `<!-- generated by code-pushup/github-action -->`;
11+
const body = truncateBody(
12+
`${markdown}\n\n${identifier}\n`,
13+
api.maxCommentChars,
14+
logger,
15+
);
16+
17+
const comments = await api.listComments();
18+
logger.debug(`Fetched ${comments.length} comments for pull request`);
19+
20+
const prevComment = comments.find(comment =>
21+
comment.body.includes(identifier),
22+
);
23+
logger.debug(
24+
prevComment
25+
? `Found previous comment ${prevComment.id} from Code PushUp`
26+
: 'Previous Code PushUp comment not found',
27+
);
28+
29+
if (prevComment) {
30+
const updatedComment = await api.updateComment(prevComment.id, body);
31+
logger.debug(`Updated body of comment ${updatedComment.url}`);
32+
return updatedComment.id;
33+
}
34+
35+
const createdComment = await api.createComment(body);
36+
logger.debug(`Created new comment ${createdComment.url}`);
37+
return createdComment.id;
38+
}
39+
40+
function truncateBody(body: string, max: number, logger: Logger): string {
41+
const truncateWarning = '...*[Comment body truncated]*';
42+
if (body.length > max) {
43+
logger.warn(`Comment body is too long. Truncating to ${max} characters.`);
44+
return body.slice(0, max - truncateWarning.length) + truncateWarning;
45+
}
46+
return body;
47+
}

packages/ci/src/lib/models.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,17 @@ export type GitRefs = {
2121
};
2222

2323
export type ProviderAPIClient = {
24+
maxCommentChars: number;
2425
downloadReportArtifact: () => Promise<string>;
25-
fetchComments: () => Promise<{ id: number; body: string }[]>;
26-
updateComment: (id: number, body: string) => Promise<void>;
27-
createComment: (body: string) => Promise<void>;
26+
listComments: () => Promise<Comment[]>;
27+
updateComment: (id: number, body: string) => Promise<Comment>;
28+
createComment: (body: string) => Promise<Comment>;
29+
};
30+
31+
export type Comment = {
32+
id: number;
33+
body: string;
34+
url: string;
2835
};
2936

3037
export type GitBranch = {

packages/ci/src/lib/monorepo/list-projects.ts

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import { glob } from 'glob';
22
import { join } from 'node:path';
3-
import type { Settings } from '../models';
3+
import type { Logger, Settings } from '../models';
44
import { detectMonorepoTool } from './detect-tool';
55
import { getToolHandler } from './handlers';
66
import { listPackages } from './packages';
77
import type { MonorepoHandlerOptions, ProjectConfig } from './tools';
88

9-
// eslint-disable-next-line max-lines-per-function
109
export async function listMonorepoProjects(
1110
settings: Settings,
1211
): Promise<ProjectConfig[]> {
@@ -41,33 +40,19 @@ export async function listMonorepoProjects(
4140
}
4241

4342
if (settings.projects) {
44-
const directories = await glob(
45-
settings.projects.map(path => path.replace(/\/$/, '/')),
46-
{ cwd: options.cwd },
47-
);
48-
logger.info(
49-
`Found ${
50-
directories.length
51-
} project folders matching "${settings.projects.join(
52-
', ',
53-
)}" from configuration`,
54-
);
55-
logger.debug(`Projects: ${directories.join(', ')}`);
56-
return directories.toSorted().map(directory => ({
57-
name: directory,
43+
return listProjectsByGlobs({
44+
patterns: settings.projects,
45+
cwd: options.cwd,
5846
bin: settings.bin,
59-
directory: join(options.cwd, directory),
60-
}));
47+
logger,
48+
});
6149
}
6250

63-
const packages = await listPackages(options.cwd);
64-
logger.info(`Found ${packages.length} NPM packages in repository`);
65-
logger.debug(`Projects: ${packages.map(({ name }) => name).join(', ')}`);
66-
return packages.map(({ name, directory }) => ({
67-
name,
51+
return listProjectsByNpmPackages({
52+
cwd: options.cwd,
6853
bin: settings.bin,
69-
directory,
70-
}));
54+
logger,
55+
});
7156
}
7257

7358
function createMonorepoHandlerOptions(
@@ -88,3 +73,49 @@ function createMonorepoHandlerOptions(
8873
}),
8974
};
9075
}
76+
77+
async function listProjectsByGlobs(args: {
78+
patterns: string[];
79+
cwd: string;
80+
bin: string;
81+
logger: Logger;
82+
}): Promise<ProjectConfig[]> {
83+
const { patterns, cwd, bin, logger } = args;
84+
85+
const directories = await glob(
86+
patterns.map(path => path.replace(/\/$/, '/')),
87+
{ cwd },
88+
);
89+
90+
logger.info(
91+
`Found ${directories.length} project folders matching "${patterns.join(
92+
', ',
93+
)}" from configuration`,
94+
);
95+
logger.debug(`Projects: ${directories.join(', ')}`);
96+
97+
return directories.toSorted().map(directory => ({
98+
name: directory,
99+
bin,
100+
directory: join(cwd, directory),
101+
}));
102+
}
103+
104+
async function listProjectsByNpmPackages(args: {
105+
cwd: string;
106+
bin: string;
107+
logger: Logger;
108+
}): Promise<ProjectConfig[]> {
109+
const { cwd, bin, logger } = args;
110+
111+
const packages = await listPackages(cwd);
112+
113+
logger.info(`Found ${packages.length} NPM packages in repository`);
114+
logger.debug(`Projects: ${packages.map(({ name }) => name).join(', ')}`);
115+
116+
return packages.map(({ name, directory }) => ({
117+
name,
118+
bin,
119+
directory,
120+
}));
121+
}

0 commit comments

Comments
 (0)