projectpulse-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +73 -0
- package/bin/projectpulse-mcp.js +2 -0
- package/dist/github/client.d.ts +3 -0
- package/dist/github/client.d.ts.map +1 -0
- package/dist/github/client.js +10 -0
- package/dist/github/client.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/scoring/health-score.d.ts +16 -0
- package/dist/scoring/health-score.d.ts.map +1 -0
- package/dist/scoring/health-score.js +80 -0
- package/dist/scoring/health-score.js.map +1 -0
- package/dist/scoring/health-score.test.d.ts +2 -0
- package/dist/scoring/health-score.test.d.ts.map +1 -0
- package/dist/scoring/health-score.test.js +209 -0
- package/dist/scoring/health-score.test.js.map +1 -0
- package/dist/tools/analyze-code-scanning.d.ts +12 -0
- package/dist/tools/analyze-code-scanning.d.ts.map +1 -0
- package/dist/tools/analyze-code-scanning.js +44 -0
- package/dist/tools/analyze-code-scanning.js.map +1 -0
- package/dist/tools/analyze-code-scanning.test.d.ts +2 -0
- package/dist/tools/analyze-code-scanning.test.d.ts.map +1 -0
- package/dist/tools/analyze-code-scanning.test.js +62 -0
- package/dist/tools/analyze-code-scanning.test.js.map +1 -0
- package/dist/tools/analyze-dependencies.d.ts +13 -0
- package/dist/tools/analyze-dependencies.d.ts.map +1 -0
- package/dist/tools/analyze-dependencies.js +31 -0
- package/dist/tools/analyze-dependencies.js.map +1 -0
- package/dist/tools/analyze-dependencies.test.d.ts +2 -0
- package/dist/tools/analyze-dependencies.test.d.ts.map +1 -0
- package/dist/tools/analyze-dependencies.test.js +65 -0
- package/dist/tools/analyze-dependencies.test.js.map +1 -0
- package/dist/tools/check-ci-status.d.ts +13 -0
- package/dist/tools/check-ci-status.d.ts.map +1 -0
- package/dist/tools/check-ci-status.js +32 -0
- package/dist/tools/check-ci-status.js.map +1 -0
- package/dist/tools/check-ci-status.test.d.ts +2 -0
- package/dist/tools/check-ci-status.test.d.ts.map +1 -0
- package/dist/tools/check-ci-status.test.js +90 -0
- package/dist/tools/check-ci-status.test.js.map +1 -0
- package/dist/tools/get-health-score.d.ts +12 -0
- package/dist/tools/get-health-score.d.ts.map +1 -0
- package/dist/tools/get-health-score.js +47 -0
- package/dist/tools/get-health-score.js.map +1 -0
- package/dist/tools/get-health-score.test.d.ts +2 -0
- package/dist/tools/get-health-score.test.d.ts.map +1 -0
- package/dist/tools/get-health-score.test.js +93 -0
- package/dist/tools/get-health-score.test.js.map +1 -0
- package/dist/tools/get-repo-health.d.ts +12 -0
- package/dist/tools/get-repo-health.d.ts.map +1 -0
- package/dist/tools/get-repo-health.js +49 -0
- package/dist/tools/get-repo-health.js.map +1 -0
- package/dist/tools/get-repo-health.test.d.ts +2 -0
- package/dist/tools/get-repo-health.test.d.ts.map +1 -0
- package/dist/tools/get-repo-health.test.js +80 -0
- package/dist/tools/get-repo-health.test.js.map +1 -0
- package/dist/types/health.d.ts +16 -0
- package/dist/types/health.d.ts.map +1 -0
- package/dist/types/health.js +2 -0
- package/dist/types/health.js.map +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +7 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-code-scanning.test.js","sourceRoot":"","sources":["../../src/tools/analyze-code-scanning.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export declare function executeAnalyzeDependencies({ owner, repo, severity }: {
|
|
3
|
+
owner: string;
|
|
4
|
+
repo: string;
|
|
5
|
+
severity?: string;
|
|
6
|
+
}): Promise<{
|
|
7
|
+
content: {
|
|
8
|
+
type: "text";
|
|
9
|
+
text: string;
|
|
10
|
+
}[];
|
|
11
|
+
}>;
|
|
12
|
+
export declare function registerAnalyzeDependencies(server: McpServer): void;
|
|
13
|
+
//# sourceMappingURL=analyze-dependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-dependencies.d.ts","sourceRoot":"","sources":["../../src/tools/analyze-dependencies.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AASpE,wBAAsB,0BAA0B,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;GAkB7H;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CASnE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getOctokit } from "../github/client.js";
|
|
3
|
+
const inputSchema = z.object({
|
|
4
|
+
owner: z.string().describe("GitHub repository owner"),
|
|
5
|
+
repo: z.string().describe("GitHub repository name"),
|
|
6
|
+
severity: z.enum(["critical", "high", "medium", "low"]).optional()
|
|
7
|
+
});
|
|
8
|
+
export async function executeAnalyzeDependencies({ owner, repo, severity }) {
|
|
9
|
+
const { data } = await getOctokit().dependabot.listAlertsForRepo({ owner, repo });
|
|
10
|
+
const result = data.map((alert) => ({
|
|
11
|
+
summary: alert.security_advisory.summary,
|
|
12
|
+
severity: alert.security_advisory.severity,
|
|
13
|
+
package_name: alert.dependency.package?.name,
|
|
14
|
+
state: alert.state,
|
|
15
|
+
html_url: alert.html_url
|
|
16
|
+
}));
|
|
17
|
+
const filtered = severity ? result.filter((alert) => alert.severity === severity) : result;
|
|
18
|
+
return {
|
|
19
|
+
content: [{
|
|
20
|
+
type: "text",
|
|
21
|
+
text: JSON.stringify(filtered, null, 2)
|
|
22
|
+
}]
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function registerAnalyzeDependencies(server) {
|
|
26
|
+
server.registerTool("analyze_dependencies", {
|
|
27
|
+
description: "Get Dependabot alerts for a GitHub repository",
|
|
28
|
+
inputSchema
|
|
29
|
+
}, executeAnalyzeDependencies);
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=analyze-dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-dependencies.js","sourceRoot":"","sources":["../../src/tools/analyze-dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IACzB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IACrD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IACnD,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE;CACrE,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAsD;IAC1H,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,UAAU,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAChC,OAAO,EAAE,KAAK,CAAC,iBAAiB,CAAC,OAAO;QACxC,QAAQ,EAAE,KAAK,CAAC,iBAAiB,CAAC,QAAQ;QAC1C,YAAY,EAAE,KAAK,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI;QAC5C,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;KAC3B,CAAC,CAAC,CAAC;IAEJ,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAE3F,OAAO;QACH,OAAO,EAAE,CAAC;gBACN,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;aAC1C,CAAC;KACL,CAAC;AACN,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,MAAiB;IACzD,MAAM,CAAC,YAAY,CACf,sBAAsB,EACtB;QACI,WAAW,EAAE,+CAA+C;QAC5D,WAAW;KACd,EACD,0BAA0B,CAC7B,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-dependencies.test.d.ts","sourceRoot":"","sources":["../../src/tools/analyze-dependencies.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { getOctokit } from '../github/client.js';
|
|
3
|
+
import { executeAnalyzeDependencies } from './analyze-dependencies.js';
|
|
4
|
+
vi.mock('../github/client.js');
|
|
5
|
+
describe('executeAnalyzeDependencies', () => {
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
vi.resetAllMocks();
|
|
8
|
+
});
|
|
9
|
+
const mockAlerts = [
|
|
10
|
+
{
|
|
11
|
+
security_advisory: { summary: 'Critical bug', severity: 'critical' },
|
|
12
|
+
dependency: { package: { name: 'lodash' } },
|
|
13
|
+
state: 'open',
|
|
14
|
+
html_url: 'https://github.com/advisory/1'
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
security_advisory: { summary: 'High bug', severity: 'high' },
|
|
18
|
+
dependency: { package: { name: 'express' } },
|
|
19
|
+
state: 'fixed',
|
|
20
|
+
html_url: 'https://github.com/advisory/2'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
security_advisory: { summary: 'Another High bug', severity: 'high' },
|
|
24
|
+
dependency: { package: { name: 'react' } },
|
|
25
|
+
state: 'open',
|
|
26
|
+
html_url: 'https://github.com/advisory/3'
|
|
27
|
+
}
|
|
28
|
+
];
|
|
29
|
+
it('should return all dependencies if no severity is provided', async () => {
|
|
30
|
+
const mockListAlerts = vi.fn().mockResolvedValue({ data: mockAlerts });
|
|
31
|
+
vi.mocked(getOctokit).mockReturnValue({
|
|
32
|
+
dependabot: { listAlertsForRepo: mockListAlerts }
|
|
33
|
+
});
|
|
34
|
+
const result = await executeAnalyzeDependencies({ owner: 'test', repo: 'repo' });
|
|
35
|
+
expect(mockListAlerts).toHaveBeenCalledWith({ owner: 'test', repo: 'repo' });
|
|
36
|
+
expect(result.content).toHaveLength(1);
|
|
37
|
+
expect(result.content[0].type).toBe('text');
|
|
38
|
+
const parsedText = JSON.parse(result.content[0].text);
|
|
39
|
+
expect(parsedText).toHaveLength(3);
|
|
40
|
+
expect(parsedText[0].severity).toBe('critical');
|
|
41
|
+
expect(parsedText[1].severity).toBe('high');
|
|
42
|
+
expect(parsedText[2].severity).toBe('high');
|
|
43
|
+
});
|
|
44
|
+
it('should return filtered dependencies if severity is provided', async () => {
|
|
45
|
+
const mockListAlerts = vi.fn().mockResolvedValue({ data: mockAlerts });
|
|
46
|
+
vi.mocked(getOctokit).mockReturnValue({
|
|
47
|
+
dependabot: { listAlertsForRepo: mockListAlerts }
|
|
48
|
+
});
|
|
49
|
+
const result = await executeAnalyzeDependencies({ owner: 'test', repo: 'repo', severity: 'high' });
|
|
50
|
+
const parsedText = JSON.parse(result.content[0].text);
|
|
51
|
+
expect(parsedText).toHaveLength(2);
|
|
52
|
+
expect(parsedText[0].package_name).toBe('express');
|
|
53
|
+
expect(parsedText[1].package_name).toBe('react');
|
|
54
|
+
});
|
|
55
|
+
it('should throw an error if API fails', async () => {
|
|
56
|
+
const mockListAlerts = vi.fn().mockRejectedValue(new Error('API Error'));
|
|
57
|
+
vi.mocked(getOctokit).mockReturnValue({
|
|
58
|
+
dependabot: { listAlertsForRepo: mockListAlerts }
|
|
59
|
+
});
|
|
60
|
+
await expect(executeAnalyzeDependencies({ owner: 'test', repo: 'repo' }))
|
|
61
|
+
.rejects
|
|
62
|
+
.toThrow('API Error');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=analyze-dependencies.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-dependencies.test.js","sourceRoot":"","sources":["../../src/tools/analyze-dependencies.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export declare function executeCheckCiStatus({ owner, repo, limit }: {
|
|
3
|
+
owner: string;
|
|
4
|
+
repo: string;
|
|
5
|
+
limit: number;
|
|
6
|
+
}): Promise<{
|
|
7
|
+
content: {
|
|
8
|
+
type: "text";
|
|
9
|
+
text: string;
|
|
10
|
+
}[];
|
|
11
|
+
}>;
|
|
12
|
+
export declare function registerCheckCiStatus(server: McpServer): void;
|
|
13
|
+
//# sourceMappingURL=check-ci-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-ci-status.d.ts","sourceRoot":"","sources":["../../src/tools/check-ci-status.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AASpE,wBAAsB,oBAAoB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;;;;;GAkBhH;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAS7D"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getOctokit } from "../github/client.js";
|
|
3
|
+
const inputSchema = z.object({
|
|
4
|
+
owner: z.string().describe("GitHub repository owner"),
|
|
5
|
+
repo: z.string().describe("GitHub repository name"),
|
|
6
|
+
limit: z.number().min(1).max(30).default(10).describe("Number of runs to return"),
|
|
7
|
+
});
|
|
8
|
+
export async function executeCheckCiStatus({ owner, repo, limit }) {
|
|
9
|
+
const { data } = await getOctokit().actions.listWorkflowRunsForRepo({ owner, repo, per_page: limit });
|
|
10
|
+
const result = data.workflow_runs.map((run) => ({
|
|
11
|
+
name: run.name,
|
|
12
|
+
status: run.status,
|
|
13
|
+
conclusion: run.conclusion,
|
|
14
|
+
head_branch: run.head_branch,
|
|
15
|
+
created_at: run.created_at,
|
|
16
|
+
updated_at: run.updated_at,
|
|
17
|
+
html_url: run.html_url,
|
|
18
|
+
}));
|
|
19
|
+
return {
|
|
20
|
+
content: [{
|
|
21
|
+
type: "text",
|
|
22
|
+
text: JSON.stringify(result, null, 2),
|
|
23
|
+
}],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function registerCheckCiStatus(server) {
|
|
27
|
+
server.registerTool("check_ci_status", {
|
|
28
|
+
description: "Get recent CI/CD workflow runs for a GitHub repository",
|
|
29
|
+
inputSchema,
|
|
30
|
+
}, executeCheckCiStatus);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=check-ci-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-ci-status.js","sourceRoot":"","sources":["../../src/tools/check-ci-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IACzB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IACrD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IACnD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,0BAA0B,CAAC;CACpF,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAkD;IAC7G,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,UAAU,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IACtG,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC5C,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,QAAQ,EAAE,GAAG,CAAC,QAAQ;KACzB,CAAC,CAAC,CAAC;IAEJ,OAAO;QACH,OAAO,EAAE,CAAC;gBACN,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;aACxC,CAAC;KACL,CAAC;AACN,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACnD,MAAM,CAAC,YAAY,CACf,iBAAiB,EACjB;QACI,WAAW,EAAE,wDAAwD;QACrE,WAAW;KACd,EACD,oBAAoB,CACvB,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-ci-status.test.d.ts","sourceRoot":"","sources":["../../src/tools/check-ci-status.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { getOctokit } from '../github/client.js';
|
|
3
|
+
import { executeCheckCiStatus } from './check-ci-status.js';
|
|
4
|
+
vi.mock('../github/client.js');
|
|
5
|
+
describe('executeCheckCiStatus', () => {
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
vi.resetAllMocks();
|
|
8
|
+
});
|
|
9
|
+
it('should return recent workflow runs', async () => {
|
|
10
|
+
const mockListRuns = vi.fn().mockResolvedValue({
|
|
11
|
+
data: {
|
|
12
|
+
workflow_runs: [
|
|
13
|
+
{
|
|
14
|
+
name: 'CI',
|
|
15
|
+
status: 'completed',
|
|
16
|
+
conclusion: 'success',
|
|
17
|
+
head_branch: 'main',
|
|
18
|
+
created_at: '2023-10-01T00:00:00Z',
|
|
19
|
+
updated_at: '2023-10-01T00:05:00Z',
|
|
20
|
+
html_url: 'https://github.com/test/repo/actions/runs/1',
|
|
21
|
+
id: 123
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'CI',
|
|
25
|
+
status: 'completed',
|
|
26
|
+
conclusion: 'failure',
|
|
27
|
+
head_branch: 'feature-branch',
|
|
28
|
+
created_at: '2023-10-02T00:00:00Z',
|
|
29
|
+
updated_at: '2023-10-02T00:05:00Z',
|
|
30
|
+
html_url: 'https://github.com/test/repo/actions/runs/2',
|
|
31
|
+
id: 124
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
vi.mocked(getOctokit).mockReturnValue({
|
|
37
|
+
actions: { listWorkflowRunsForRepo: mockListRuns }
|
|
38
|
+
});
|
|
39
|
+
const result = await executeCheckCiStatus({ owner: 'test', repo: 'repo', limit: 10 });
|
|
40
|
+
expect(mockListRuns).toHaveBeenCalledWith({ owner: 'test', repo: 'repo', per_page: 10 });
|
|
41
|
+
expect(result.content).toHaveLength(1);
|
|
42
|
+
expect(result.content[0].type).toBe('text');
|
|
43
|
+
const parsedText = JSON.parse(result.content[0].text);
|
|
44
|
+
expect(parsedText).toEqual([
|
|
45
|
+
{
|
|
46
|
+
name: 'CI',
|
|
47
|
+
status: 'completed',
|
|
48
|
+
conclusion: 'success',
|
|
49
|
+
head_branch: 'main',
|
|
50
|
+
created_at: '2023-10-01T00:00:00Z',
|
|
51
|
+
updated_at: '2023-10-01T00:05:00Z',
|
|
52
|
+
html_url: 'https://github.com/test/repo/actions/runs/1'
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'CI',
|
|
56
|
+
status: 'completed',
|
|
57
|
+
conclusion: 'failure',
|
|
58
|
+
head_branch: 'feature-branch',
|
|
59
|
+
created_at: '2023-10-02T00:00:00Z',
|
|
60
|
+
updated_at: '2023-10-02T00:05:00Z',
|
|
61
|
+
html_url: 'https://github.com/test/repo/actions/runs/2'
|
|
62
|
+
}
|
|
63
|
+
]);
|
|
64
|
+
});
|
|
65
|
+
it('should handle empty workflow runs', async () => {
|
|
66
|
+
const mockListRuns = vi.fn().mockResolvedValue({
|
|
67
|
+
data: {
|
|
68
|
+
workflow_runs: []
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
vi.mocked(getOctokit).mockReturnValue({
|
|
72
|
+
actions: { listWorkflowRunsForRepo: mockListRuns }
|
|
73
|
+
});
|
|
74
|
+
const result = await executeCheckCiStatus({ owner: 'test', repo: 'empty-repo', limit: 5 });
|
|
75
|
+
expect(mockListRuns).toHaveBeenCalledWith({ owner: 'test', repo: 'empty-repo', per_page: 5 });
|
|
76
|
+
const parsedText = JSON.parse(result.content[0].text);
|
|
77
|
+
expect(parsedText).toEqual([]);
|
|
78
|
+
});
|
|
79
|
+
it('should throw error if API fails', async () => {
|
|
80
|
+
const error = new Error('API Error');
|
|
81
|
+
const mockListRuns = vi.fn().mockRejectedValue(error);
|
|
82
|
+
vi.mocked(getOctokit).mockReturnValue({
|
|
83
|
+
actions: { listWorkflowRunsForRepo: mockListRuns }
|
|
84
|
+
});
|
|
85
|
+
await expect(executeCheckCiStatus({ owner: 'test', repo: 'error-repo', limit: 10 }))
|
|
86
|
+
.rejects
|
|
87
|
+
.toThrow('API Error');
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
//# sourceMappingURL=check-ci-status.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-ci-status.test.js","sourceRoot":"","sources":["../../src/tools/check-ci-status.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export declare function executeGetHealthScore({ owner, repo }: {
|
|
3
|
+
owner: string;
|
|
4
|
+
repo: string;
|
|
5
|
+
}): Promise<{
|
|
6
|
+
content: {
|
|
7
|
+
type: "text";
|
|
8
|
+
text: string;
|
|
9
|
+
}[];
|
|
10
|
+
}>;
|
|
11
|
+
export declare function registerGetHealthScore(server: McpServer): void;
|
|
12
|
+
//# sourceMappingURL=get-health-score.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-health-score.d.ts","sourceRoot":"","sources":["../../src/tools/get-health-score.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAgBpE,wBAAsB,qBAAqB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;;;;;GAuC3F;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAS9D"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getOctokit } from "../github/client.js";
|
|
3
|
+
import { calculateCiScore, calculateFreshnessScore, calculateSecurityScore, calculateCommunityScore, calculateMaintenanceScore, calculateHealthScore, } from "../scoring/health-score.js";
|
|
4
|
+
const inputSchema = z.object({
|
|
5
|
+
owner: z.string().describe("GitHub repository owner"),
|
|
6
|
+
repo: z.string().describe("GitHub repository name"),
|
|
7
|
+
});
|
|
8
|
+
export async function executeGetHealthScore({ owner, repo }) {
|
|
9
|
+
const octokit = getOctokit();
|
|
10
|
+
const [repoData, runsData] = await Promise.all([
|
|
11
|
+
octokit.repos.get({ owner, repo }),
|
|
12
|
+
octokit.actions.listWorkflowRunsForRepo({ owner, repo, per_page: 10 }),
|
|
13
|
+
]);
|
|
14
|
+
let alertCounts = { critical: 0, high: 0, medium: 0, low: 0 };
|
|
15
|
+
try {
|
|
16
|
+
const { data: alerts } = await octokit.dependabot.listAlertsForRepo({ owner, repo });
|
|
17
|
+
for (const alert of alerts) {
|
|
18
|
+
const sev = alert.security_advisory.severity;
|
|
19
|
+
if (sev in alertCounts)
|
|
20
|
+
alertCounts[sev]++;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Dependabot not enabled or no access — keep zeros
|
|
25
|
+
}
|
|
26
|
+
const categories = {
|
|
27
|
+
ci: calculateCiScore(runsData.data.workflow_runs),
|
|
28
|
+
freshness: calculateFreshnessScore(repoData.data.pushed_at ?? new Date().toISOString()),
|
|
29
|
+
security: calculateSecurityScore(alertCounts),
|
|
30
|
+
community: calculateCommunityScore(repoData.data.open_issues_count, repoData.data.forks_count),
|
|
31
|
+
maintenance: calculateMaintenanceScore(repoData.data.license !== null, repoData.data.description !== null, repoData.data.archived),
|
|
32
|
+
};
|
|
33
|
+
const report = calculateHealthScore(`${owner}/${repo}`, categories);
|
|
34
|
+
return {
|
|
35
|
+
content: [{
|
|
36
|
+
type: "text",
|
|
37
|
+
text: JSON.stringify(report, null, 2),
|
|
38
|
+
}],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export function registerGetHealthScore(server) {
|
|
42
|
+
server.registerTool("get_health_score", {
|
|
43
|
+
description: "Calculate a 0-100 health score for a GitHub repository with grade (A-F), category breakdown, and improvement suggestions",
|
|
44
|
+
inputSchema,
|
|
45
|
+
}, executeGetHealthScore);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=get-health-score.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-health-score.js","sourceRoot":"","sources":["../../src/tools/get-health-score.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EACH,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,yBAAyB,EACzB,oBAAoB,GACvB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IACzB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IACrD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;CACtD,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAmC;IACxF,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC3C,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAClC,OAAO,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;KACzE,CAAC,CAAC;IAEH,IAAI,WAAW,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAC9D,IAAI,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACrF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,KAAK,CAAC,iBAAiB,CAAC,QAAoC,CAAC;YACzE,IAAI,GAAG,IAAI,WAAW;gBAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACL,mDAAmD;IACvD,CAAC;IAED,MAAM,UAAU,GAAG;QACf,EAAE,EAAE,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAoB,CAAC;QACxD,SAAS,EAAE,uBAAuB,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACvF,QAAQ,EAAE,sBAAsB,CAAC,WAAW,CAAC;QAC7C,SAAS,EAAE,uBAAuB,CAAC,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC;QAC9F,WAAW,EAAE,yBAAyB,CAClC,QAAQ,CAAC,IAAI,CAAC,OAAO,KAAK,IAAI,EAC9B,QAAQ,CAAC,IAAI,CAAC,WAAW,KAAK,IAAI,EAClC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CACzB;KACJ,CAAC;IAEF,MAAM,MAAM,GAAG,oBAAoB,CAAC,GAAG,KAAK,IAAI,IAAI,EAAE,EAAE,UAAU,CAAC,CAAC;IAEpE,OAAO;QACH,OAAO,EAAE,CAAC;gBACN,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;aACxC,CAAC;KACL,CAAC;AACN,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAiB;IACpD,MAAM,CAAC,YAAY,CACf,kBAAkB,EAClB;QACI,WAAW,EAAE,0HAA0H;QACvI,WAAW;KACd,EACD,qBAAqB,CACxB,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-health-score.test.d.ts","sourceRoot":"","sources":["../../src/tools/get-health-score.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { getOctokit } from '../github/client.js';
|
|
3
|
+
import { executeGetHealthScore } from './get-health-score.js';
|
|
4
|
+
vi.mock('../github/client.js');
|
|
5
|
+
describe('executeGetHealthScore', () => {
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
vi.resetAllMocks();
|
|
8
|
+
});
|
|
9
|
+
it('should calculate health score successfully with dependabot alerts', async () => {
|
|
10
|
+
const mockReposGet = vi.fn().mockResolvedValue({
|
|
11
|
+
data: {
|
|
12
|
+
pushed_at: '2023-10-01T00:00:00Z',
|
|
13
|
+
open_issues_count: 5,
|
|
14
|
+
forks_count: 10,
|
|
15
|
+
license: { spdx_id: 'MIT' },
|
|
16
|
+
description: 'test repo',
|
|
17
|
+
archived: false
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const mockListRuns = vi.fn().mockResolvedValue({
|
|
21
|
+
data: {
|
|
22
|
+
workflow_runs: [{ conclusion: 'success' }]
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const mockListAlerts = vi.fn().mockResolvedValue({
|
|
26
|
+
data: [
|
|
27
|
+
{ security_advisory: { severity: 'critical' } },
|
|
28
|
+
{ security_advisory: { severity: 'high' } }
|
|
29
|
+
]
|
|
30
|
+
});
|
|
31
|
+
vi.mocked(getOctokit).mockReturnValue({
|
|
32
|
+
repos: { get: mockReposGet },
|
|
33
|
+
actions: { listWorkflowRunsForRepo: mockListRuns },
|
|
34
|
+
dependabot: { listAlertsForRepo: mockListAlerts }
|
|
35
|
+
});
|
|
36
|
+
const result = await executeGetHealthScore({ owner: 'test', repo: 'repo' });
|
|
37
|
+
expect(mockReposGet).toHaveBeenCalledWith({ owner: 'test', repo: 'repo' });
|
|
38
|
+
expect(mockListRuns).toHaveBeenCalledWith({ owner: 'test', repo: 'repo', per_page: 10 });
|
|
39
|
+
expect(mockListAlerts).toHaveBeenCalledWith({ owner: 'test', repo: 'repo' });
|
|
40
|
+
expect(result.content).toHaveLength(1);
|
|
41
|
+
expect(result.content[0].type).toBe('text');
|
|
42
|
+
const parsedText = JSON.parse(result.content[0].text);
|
|
43
|
+
expect(parsedText.repo).toBe('test/repo');
|
|
44
|
+
expect(parsedText.score).toBeTypeOf('number');
|
|
45
|
+
expect(parsedText.grade).toBeTypeOf('string');
|
|
46
|
+
// Ensure dependabot parsing worked:
|
|
47
|
+
expect(parsedText.breakdown.security.detail).toContain('1 critical');
|
|
48
|
+
expect(parsedText.breakdown.security.detail).toContain('1 high');
|
|
49
|
+
});
|
|
50
|
+
it('should calculate health score successfully even if dependabot fails', async () => {
|
|
51
|
+
const mockReposGet = vi.fn().mockResolvedValue({
|
|
52
|
+
data: {
|
|
53
|
+
pushed_at: '2023-10-01T00:00:00Z',
|
|
54
|
+
open_issues_count: 5,
|
|
55
|
+
forks_count: 10,
|
|
56
|
+
license: { spdx_id: 'MIT' },
|
|
57
|
+
description: 'test repo',
|
|
58
|
+
archived: false
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
const mockListRuns = vi.fn().mockResolvedValue({
|
|
62
|
+
data: {
|
|
63
|
+
workflow_runs: [{ conclusion: 'success' }]
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
// Simulating 404 or disabled dependabot
|
|
67
|
+
const mockListAlerts = vi.fn().mockRejectedValue(new Error('Not Found'));
|
|
68
|
+
vi.mocked(getOctokit).mockReturnValue({
|
|
69
|
+
repos: { get: mockReposGet },
|
|
70
|
+
actions: { listWorkflowRunsForRepo: mockListRuns },
|
|
71
|
+
dependabot: { listAlertsForRepo: mockListAlerts }
|
|
72
|
+
});
|
|
73
|
+
const result = await executeGetHealthScore({ owner: 'test', repo: 'repo' });
|
|
74
|
+
const parsedText = JSON.parse(result.content[0].text);
|
|
75
|
+
expect(parsedText.repo).toBe('test/repo');
|
|
76
|
+
// If dependabot fails, it should assume 0 alerts
|
|
77
|
+
expect(parsedText.breakdown.security.detail).toContain('0 critical');
|
|
78
|
+
expect(parsedText.breakdown.security.detail).toContain('0 high');
|
|
79
|
+
});
|
|
80
|
+
it('should fail if repos.get fails', async () => {
|
|
81
|
+
const mockReposGet = vi.fn().mockRejectedValue(new Error('API Error'));
|
|
82
|
+
const mockListRuns = vi.fn().mockResolvedValue({ data: { workflow_runs: [] } });
|
|
83
|
+
vi.mocked(getOctokit).mockReturnValue({
|
|
84
|
+
repos: { get: mockReposGet },
|
|
85
|
+
actions: { listWorkflowRunsForRepo: mockListRuns },
|
|
86
|
+
dependabot: { listAlertsForRepo: vi.fn() }
|
|
87
|
+
});
|
|
88
|
+
await expect(executeGetHealthScore({ owner: 'test', repo: 'error-repo' }))
|
|
89
|
+
.rejects
|
|
90
|
+
.toThrow('API Error');
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
//# sourceMappingURL=get-health-score.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-health-score.test.js","sourceRoot":"","sources":["../../src/tools/get-health-score.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export declare function executeGetRepoHealth({ owner, repo }: {
|
|
3
|
+
owner: string;
|
|
4
|
+
repo: string;
|
|
5
|
+
}): Promise<{
|
|
6
|
+
content: {
|
|
7
|
+
type: "text";
|
|
8
|
+
text: string;
|
|
9
|
+
}[];
|
|
10
|
+
}>;
|
|
11
|
+
export declare function registerGetRepoHealth(server: McpServer): void;
|
|
12
|
+
//# sourceMappingURL=get-repo-health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-repo-health.d.ts","sourceRoot":"","sources":["../../src/tools/get-repo-health.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAQpE,wBAAsB,oBAAoB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;;;;;GAkC1F;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAS7D"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getOctokit } from "../github/client.js";
|
|
3
|
+
const inputSchema = z.object({
|
|
4
|
+
owner: z.string().describe("GitHub repository owner"),
|
|
5
|
+
repo: z.string().describe("GitHub repository name")
|
|
6
|
+
});
|
|
7
|
+
export async function executeGetRepoHealth({ owner, repo }) {
|
|
8
|
+
try {
|
|
9
|
+
const { data } = await getOctokit().repos.get({ owner, repo });
|
|
10
|
+
return {
|
|
11
|
+
content: [{
|
|
12
|
+
type: "text",
|
|
13
|
+
text: JSON.stringify({
|
|
14
|
+
full_name: data.full_name,
|
|
15
|
+
description: data.description,
|
|
16
|
+
stargazers_count: data.stargazers_count,
|
|
17
|
+
open_issues_count: data.open_issues_count,
|
|
18
|
+
language: data.language,
|
|
19
|
+
license: data.license ? data.license.spdx_id : null,
|
|
20
|
+
pushed_at: data.pushed_at,
|
|
21
|
+
default_branch: data.default_branch,
|
|
22
|
+
archived: data.archived,
|
|
23
|
+
forks_count: data.forks_count
|
|
24
|
+
}, null, 2),
|
|
25
|
+
}]
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (error.status === 404) {
|
|
30
|
+
return {
|
|
31
|
+
content: [{
|
|
32
|
+
type: "text",
|
|
33
|
+
text: JSON.stringify({
|
|
34
|
+
error: "Repository not found",
|
|
35
|
+
details: error.message
|
|
36
|
+
}, null, 2),
|
|
37
|
+
}]
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
throw error; //-> will be caught by MCP server
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function registerGetRepoHealth(server) {
|
|
44
|
+
server.registerTool("get_repo_health", {
|
|
45
|
+
description: "Get health information for a GitHub repository",
|
|
46
|
+
inputSchema
|
|
47
|
+
}, executeGetRepoHealth);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=get-repo-health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-repo-health.js","sourceRoot":"","sources":["../../src/tools/get-repo-health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IACzB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IACrD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;CACtD,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAmC;IACvF,IAAI,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,OAAO;YACH,OAAO,EAAE,CAAC;oBACN,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACjB,SAAS,EAAE,IAAI,CAAC,SAAS;wBACzB,WAAW,EAAE,IAAI,CAAC,WAAW;wBAC7B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;wBACvC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;wBACzC,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;wBACnD,SAAS,EAAE,IAAI,CAAC,SAAS;wBACzB,cAAc,EAAE,IAAI,CAAC,cAAc;wBACnC,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,WAAW,EAAE,IAAI,CAAC,WAAW;qBAChC,EAAE,IAAI,EAAE,CAAC,CAAC;iBACd,CAAC;SACL,CAAC;IACN,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAK,KAA6B,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAChD,OAAO;gBACH,OAAO,EAAE,CAAC;wBACN,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACjB,KAAK,EAAE,sBAAsB;4BAC7B,OAAO,EAAG,KAAe,CAAC,OAAO;yBACpC,EAAE,IAAI,EAAE,CAAC,CAAC;qBACd,CAAC;aACL,CAAC;QACN,CAAC;QACD,MAAM,KAAK,CAAC,CAAC,iCAAiC;IAClD,CAAC;AACL,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACnD,MAAM,CAAC,YAAY,CACf,iBAAiB,EACjB;QACI,WAAW,EAAE,gDAAgD;QAC7D,WAAW;KACd,EACD,oBAAoB,CACvB,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-repo-health.test.d.ts","sourceRoot":"","sources":["../../src/tools/get-repo-health.test.ts"],"names":[],"mappings":""}
|