comfy-pr 0.2.24 → 0.2.26
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/README.md +247 -225
- package/index.ts +6 -0
- package/next-env.d.ts +5 -5
- package/package.json +52 -25
- package/src/Authors.ts +42 -48
- package/src/CMNodes.ts +60 -60
- package/src/CNRepos.ts +78 -74
- package/src/CRNodes.ts +27 -27
- package/src/CRPulls.ts +4 -4
- package/src/EmailTasks.ts +101 -0
- package/src/FORK_OWNER.ts +5 -5
- package/src/FORK_PREFIX.ts +5 -5
- package/src/FollowRules.ts +25 -25
- package/src/GIT_USEREMAIL.ts +5 -5
- package/src/GIT_USERNAME.ts +9 -9
- package/src/GithubIssueComments.ts +3 -3
- package/src/PushedBranch.ts +3 -3
- package/src/Totals.ts +24 -9
- package/src/TrackingPRs.ts +12 -12
- package/src/WorkerInstances.ts +89 -89
- package/src/addCommentAction.ts +73 -65
- package/src/analyzePullsStatus.ts +219 -170
- package/src/analyzeTotals.test.ts +5 -5
- package/src/analyzeTotals.ts +118 -118
- package/src/bypassRepos.spec.ts +10 -0
- package/src/bypassRepos.ts +8 -0
- package/src/checkComfyActivated.ts +39 -39
- package/src/checkPRsFailures.ts +18 -0
- package/src/cli.ts +40 -40
- package/src/clone_modify_push_Branches.ts +21 -21
- package/src/createComfyRegistryPRsFromCandidates.ts +55 -55
- package/src/createComfyRegistryPullRequests.ts +32 -22
- package/src/createGithubForkForRepo.ts +54 -37
- package/src/createGithubPullRequest.ts +157 -94
- package/src/createIssueComment.ts +34 -29
- package/src/fetchCMNodes.ts +22 -22
- package/src/fetchComfyRegistryNodes.ts +11 -11
- package/src/fetchCurrentGeoInfo.ts +6 -6
- package/src/fetchRelatedPullWithComments.ts +15 -15
- package/src/fetchRepoDescriptionMap.ts +15 -15
- package/src/followRuleSchema.ts +79 -76
- package/src/getActivatedShell.ts +18 -18
- package/src/getBranchWorkingDir.ts +16 -16
- package/src/getRepoWorkingDir.ts +5 -5
- package/src/ghUser.ts +9 -6
- package/src/index.ts +26 -22
- package/src/initializeFollowRules.ts +26 -26
- package/src/makePublishBranch.ts +58 -58
- package/src/makeTomlBranch.ts +53 -53
- package/src/makeUpdateTomlLicenseBranch.ts +245 -0
- package/src/matchRelatedPulls.ts +47 -60
- package/src/muteInstances.ts +16 -16
- package/src/parseIssueUrl.ts +6 -6
- package/src/parseOwnerRepo.ts +33 -33
- package/src/parsePullUrl.ts +6 -6
- package/src/parsePullsState.ts +6 -6
- package/src/parseTitleBodyOfMarkdown.ts +8 -8
- package/src/postSlackMessage.ts +21 -21
- package/src/preload.ts +30 -30
- package/src/pullStatusFollowSchema.ts +12 -12
- package/src/readTemplateTitle.ts +11 -11
- package/src/sendEmailAction.ts +56 -0
- package/src/sendGmail.ts +105 -0
- package/src/showFollowRuleSet.ts +12 -12
- package/src/summaryLastPullComment.ts +8 -8
- package/src/tomlFillDescription.ts +17 -17
- package/src/updateAuthors.ts +7 -7
- package/src/updateAuthorsForGithub.ts +54 -50
- package/src/updateAuthorsFromCNRepo.ts +30 -30
- package/src/updateCMNodesDuplicationWarnings.ts +56 -56
- package/src/updateCMRepos.ts +27 -27
- package/src/updateCNRepos.ts +58 -58
- package/src/updateCNReposCRPullsComments.ts +40 -40
- package/src/updateCNReposInfo.ts +58 -57
- package/src/updateCNReposPRCandidate.ts +85 -85
- package/src/updateCNReposPulls.ts +31 -28
- package/src/updateCNReposPullsDashboard.ts +49 -49
- package/src/updateCNReposRelatedPulls.ts +25 -25
- package/src/updateCRNodes.ts +50 -50
- package/src/updateCRRepos.ts +26 -26
- package/src/updateComfyTotals.ts +43 -43
- package/src/updateFollowRuleSet.ts +136 -127
- package/src/updateOutdatedPullsTemplates.ts +165 -160
- package/src/updateSlackMessages.ts +43 -43
- package/tailwind.config.ts +75 -20
package/src/updateCNRepos.ts
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
import { updateCMNodes } from "./CMNodes";
|
|
2
|
-
import { getWorkerInstance } from "./WorkerInstances";
|
|
3
|
-
import { createComfyRegistryPRsFromCandidates } from "./createComfyRegistryPRsFromCandidates";
|
|
4
|
-
import { notifySlack } from "./slack/notifySlack";
|
|
5
|
-
import { updateCMRepos } from "./updateCMRepos";
|
|
6
|
-
import { updateCNReposCRPullsComments } from "./updateCNReposCRPullsComments";
|
|
7
|
-
import { updateCNReposInfo } from "./updateCNReposInfo";
|
|
8
|
-
import { updateCNReposPRCandidate } from "./updateCNReposPRCandidate";
|
|
9
|
-
import { updateCNReposPulls } from "./updateCNReposPulls";
|
|
10
|
-
import { updateCNRepoPullsDashboard } from "./updateCNReposPullsDashboard";
|
|
11
|
-
import { updateCNReposRelatedPulls } from "./updateCNReposRelatedPulls";
|
|
12
|
-
import { updateCRNodes } from "./updateCRNodes";
|
|
13
|
-
import { updateCRRepos } from "./updateCRRepos";
|
|
14
|
-
import { updateComfyTotals } from "./updateComfyTotals";
|
|
15
|
-
import { updateOutdatedPullsTemplates } from "./updateOutdatedPullsTemplates";
|
|
16
|
-
import { tLog } from "./utils/tLog";
|
|
17
|
-
|
|
18
|
-
if (import.meta.main) {
|
|
19
|
-
await getWorkerInstance("Updating CNRepos");
|
|
20
|
-
// await cacheHealthReport();
|
|
21
|
-
await updateCNRepos();
|
|
22
|
-
// updateCNReposPRTasks
|
|
23
|
-
// await scanCNRepoThenPRs();
|
|
24
|
-
// await pMap(candidates, (e) => updateCNRepoPRStatus(e.repository), { concurrency: 4 });
|
|
25
|
-
// candidates
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export async function updateCNRepos() {
|
|
29
|
-
await Promise.all([
|
|
30
|
-
tLog("Report Worker Status", async () => {
|
|
31
|
-
const worker = await getWorkerInstance("ComfyPR Bot Running");
|
|
32
|
-
const workerInfo = `${worker.geo.countryCode}/${worker.geo.region}/${worker.geo.city}`;
|
|
33
|
-
const msg = `COMFY-PR BOT RUNNING ${new Date().toISOString()}\nWorker: ${workerInfo}`;
|
|
34
|
-
return [await notifySlack(msg, { unique: true, silent: true })];
|
|
35
|
-
}),
|
|
36
|
-
// stage 1: get repos
|
|
37
|
-
await tLog("Update Nodes from ComfyUI Manager", updateCMNodes),
|
|
38
|
-
await tLog("Update Repos from ComfyUI Manager", updateCMRepos),
|
|
39
|
-
await tLog("Update Nodes from ComfyRegistry", updateCRNodes),
|
|
40
|
-
await tLog("Update Repos from ComfyRegistry", updateCRRepos),
|
|
41
|
-
// stage 2: update repo info & pulls
|
|
42
|
-
await tLog("Update CNRepos for Repo Infos", updateCNReposInfo),
|
|
43
|
-
await tLog("Update CNRepos for Github Pulls", updateCNReposPulls),
|
|
44
|
-
await tLog("Update Pulls Dashboard", updateCNRepoPullsDashboard),
|
|
45
|
-
// stage 3: update related pulls and comments
|
|
46
|
-
await tLog("Update CNRepos for Related Pulls", updateCNReposRelatedPulls),
|
|
47
|
-
await tLog("Update Outdated Pulls Templates", updateOutdatedPullsTemplates),
|
|
48
|
-
// stage 4: update related comments
|
|
49
|
-
await tLog("Update CNRepos for Related Comments", updateCNReposCRPullsComments),
|
|
50
|
-
// stage 5: mark and create PRs
|
|
51
|
-
await tLog("Update CNRepos PR Candidates", updateCNReposPRCandidate),
|
|
52
|
-
await tLog("Create ComfyRegistry PRs", createComfyRegistryPRsFromCandidates),
|
|
53
|
-
// final
|
|
54
|
-
await tLog("Update Comfy Totals", updateComfyTotals),
|
|
55
|
-
]);
|
|
56
|
-
|
|
57
|
-
console.log("All repo updated");
|
|
58
|
-
}
|
|
1
|
+
import { updateCMNodes } from "./CMNodes";
|
|
2
|
+
import { getWorkerInstance } from "./WorkerInstances";
|
|
3
|
+
import { createComfyRegistryPRsFromCandidates } from "./createComfyRegistryPRsFromCandidates";
|
|
4
|
+
import { notifySlack } from "./slack/notifySlack";
|
|
5
|
+
import { updateCMRepos } from "./updateCMRepos";
|
|
6
|
+
import { updateCNReposCRPullsComments } from "./updateCNReposCRPullsComments";
|
|
7
|
+
import { updateCNReposInfo } from "./updateCNReposInfo";
|
|
8
|
+
import { updateCNReposPRCandidate } from "./updateCNReposPRCandidate";
|
|
9
|
+
import { updateCNReposPulls } from "./updateCNReposPulls";
|
|
10
|
+
import { updateCNRepoPullsDashboard } from "./updateCNReposPullsDashboard";
|
|
11
|
+
import { updateCNReposRelatedPulls } from "./updateCNReposRelatedPulls";
|
|
12
|
+
import { updateCRNodes } from "./updateCRNodes";
|
|
13
|
+
import { updateCRRepos } from "./updateCRRepos";
|
|
14
|
+
import { updateComfyTotals } from "./updateComfyTotals";
|
|
15
|
+
import { updateOutdatedPullsTemplates } from "./updateOutdatedPullsTemplates";
|
|
16
|
+
import { tLog } from "./utils/tLog";
|
|
17
|
+
|
|
18
|
+
if (import.meta.main) {
|
|
19
|
+
await getWorkerInstance("Updating CNRepos");
|
|
20
|
+
// await cacheHealthReport();
|
|
21
|
+
await updateCNRepos();
|
|
22
|
+
// updateCNReposPRTasks
|
|
23
|
+
// await scanCNRepoThenPRs();
|
|
24
|
+
// await pMap(candidates, (e) => updateCNRepoPRStatus(e.repository), { concurrency: 4 });
|
|
25
|
+
// candidates
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function updateCNRepos() {
|
|
29
|
+
await Promise.all([
|
|
30
|
+
tLog("Report Worker Status", async () => {
|
|
31
|
+
const worker = await getWorkerInstance("ComfyPR Bot Running");
|
|
32
|
+
const workerInfo = `${worker.geo.countryCode}/${worker.geo.region}/${worker.geo.city}`;
|
|
33
|
+
const msg = `COMFY-PR BOT RUNNING ${new Date().toISOString()}\nWorker: ${workerInfo}`;
|
|
34
|
+
return [await notifySlack(msg, { unique: true, silent: true })];
|
|
35
|
+
}),
|
|
36
|
+
// stage 1: get repos
|
|
37
|
+
await tLog("Update Nodes from ComfyUI Manager", updateCMNodes),
|
|
38
|
+
await tLog("Update Repos from ComfyUI Manager", updateCMRepos),
|
|
39
|
+
await tLog("Update Nodes from ComfyRegistry", updateCRNodes),
|
|
40
|
+
await tLog("Update Repos from ComfyRegistry", updateCRRepos),
|
|
41
|
+
// stage 2: update repo info & pulls
|
|
42
|
+
await tLog("Update CNRepos for Repo Infos", updateCNReposInfo),
|
|
43
|
+
await tLog("Update CNRepos for Github Pulls", updateCNReposPulls),
|
|
44
|
+
await tLog("Update Pulls Dashboard", updateCNRepoPullsDashboard),
|
|
45
|
+
// stage 3: update related pulls and comments
|
|
46
|
+
await tLog("Update CNRepos for Related Pulls", updateCNReposRelatedPulls),
|
|
47
|
+
await tLog("Update Outdated Pulls Templates", updateOutdatedPullsTemplates),
|
|
48
|
+
// stage 4: update related comments
|
|
49
|
+
await tLog("Update CNRepos for Related Comments", updateCNReposCRPullsComments),
|
|
50
|
+
// stage 5: mark and create PRs
|
|
51
|
+
await tLog("Update CNRepos PR Candidates", updateCNReposPRCandidate),
|
|
52
|
+
await tLog("Create ComfyRegistry PRs", createComfyRegistryPRsFromCandidates),
|
|
53
|
+
// final
|
|
54
|
+
await tLog("Update Comfy Totals", updateComfyTotals),
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
console.log("All repo updated");
|
|
58
|
+
}
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import pMap from "p-map";
|
|
2
|
-
import { CNRepos, type CRPull } from "./CNRepos";
|
|
3
|
-
import { $fresh, $stale } from "./db";
|
|
4
|
-
// import { $filaten } from "./db";
|
|
5
|
-
// import { $pipeline } from "./db/$pipeline";
|
|
6
|
-
import { $filaten } from "@/packages/mongodb-pipeline-ts/$filaten";
|
|
7
|
-
import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
|
|
8
|
-
import { TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
9
|
-
import { getWorkerInstance } from "./WorkerInstances";
|
|
10
|
-
import { fetchIssueComments } from "./gh/fetchIssueComments";
|
|
11
|
-
|
|
12
|
-
if (import.meta.main) {
|
|
13
|
-
await getWorkerInstance("updateCNReposCRPullsComments");
|
|
14
|
-
await updateCNReposCRPullsComments();
|
|
15
|
-
console.log("All done");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function updateCNReposCRPullsComments() {
|
|
19
|
-
return await pMap(
|
|
20
|
-
$pipeline(CNRepos)
|
|
21
|
-
.unwind("$crPulls.data")
|
|
22
|
-
.match($filaten({ crPulls: { mtime: $fresh("7d"), data: { comments: { mtime: $stale("1d") } } } }))
|
|
23
|
-
.set($filaten({ "crPulls.data": { repository: "$repository" } }))
|
|
24
|
-
.replaceRoot({ newRoot: "$crPulls.data" })
|
|
25
|
-
.aggregate(),
|
|
26
|
-
async (data) => {
|
|
27
|
-
const { repository, pull } = data as unknown as { repository: string } & CRPull;
|
|
28
|
-
const html_url = pull.html_url;
|
|
29
|
-
const comments = await fetchIssueComments(repository, pull).then(TaskOK).catch(TaskError);
|
|
30
|
-
return [
|
|
31
|
-
await CNRepos.findOneAndUpdate(
|
|
32
|
-
$filaten({ repository, crPulls: { data: { pull: { html_url } } } }),
|
|
33
|
-
{ $set: { "crPulls.data.$.comments": comments } },
|
|
34
|
-
{ upsert: true, returnDocument: "after" },
|
|
35
|
-
),
|
|
36
|
-
];
|
|
37
|
-
},
|
|
38
|
-
{ concurrency: 2 },
|
|
39
|
-
);
|
|
40
|
-
}
|
|
1
|
+
import pMap from "p-map";
|
|
2
|
+
import { CNRepos, type CRPull } from "./CNRepos";
|
|
3
|
+
import { $fresh, $stale } from "./db";
|
|
4
|
+
// import { $filaten } from "./db";
|
|
5
|
+
// import { $pipeline } from "./db/$pipeline";
|
|
6
|
+
import { $filaten } from "@/packages/mongodb-pipeline-ts/$filaten";
|
|
7
|
+
import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
|
|
8
|
+
import { TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
9
|
+
import { getWorkerInstance } from "./WorkerInstances";
|
|
10
|
+
import { fetchIssueComments } from "./gh/fetchIssueComments";
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
await getWorkerInstance("updateCNReposCRPullsComments");
|
|
14
|
+
await updateCNReposCRPullsComments();
|
|
15
|
+
console.log("All done");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function updateCNReposCRPullsComments() {
|
|
19
|
+
return await pMap(
|
|
20
|
+
$pipeline(CNRepos)
|
|
21
|
+
.unwind("$crPulls.data")
|
|
22
|
+
.match($filaten({ crPulls: { mtime: $fresh("7d"), data: { comments: { mtime: $stale("1d") } } } }))
|
|
23
|
+
.set($filaten({ "crPulls.data": { repository: "$repository" } }))
|
|
24
|
+
.replaceRoot({ newRoot: "$crPulls.data" })
|
|
25
|
+
.aggregate(),
|
|
26
|
+
async (data) => {
|
|
27
|
+
const { repository, pull } = data as unknown as { repository: string } & CRPull;
|
|
28
|
+
const html_url = pull.html_url;
|
|
29
|
+
const comments = await fetchIssueComments(repository, pull).then(TaskOK).catch(TaskError);
|
|
30
|
+
return [
|
|
31
|
+
await CNRepos.findOneAndUpdate(
|
|
32
|
+
$filaten({ repository, crPulls: { data: { pull: { html_url } } } }),
|
|
33
|
+
{ $set: { "crPulls.data.$.comments": comments } },
|
|
34
|
+
{ upsert: true, returnDocument: "after" },
|
|
35
|
+
),
|
|
36
|
+
];
|
|
37
|
+
},
|
|
38
|
+
{ concurrency: 2 },
|
|
39
|
+
);
|
|
40
|
+
}
|
package/src/updateCNReposInfo.ts
CHANGED
|
@@ -1,57 +1,58 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { match } from "ts-pattern";
|
|
4
|
-
import { $OK, TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
5
|
-
import { CNRepos } from "./CNRepos";
|
|
6
|
-
import { getWorkerInstance } from "./WorkerInstances";
|
|
7
|
-
import { $filaten, $stale } from "./db";
|
|
8
|
-
import { gh } from "./gh";
|
|
9
|
-
import { parseUrlRepoOwner } from "./parseOwnerRepo";
|
|
10
|
-
import { tLog } from "./utils/tLog";
|
|
11
|
-
|
|
12
|
-
if (import.meta.main) {
|
|
13
|
-
await getWorkerInstance("updateCNReposInfo");
|
|
14
|
-
await tLog("updateCNReposInfo", updateCNReposInfo);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function updateCNReposInfo() {
|
|
18
|
-
await CNRepos.createIndex($filaten({ info: { mtime: 1 } }));
|
|
19
|
-
return await
|
|
20
|
-
CNRepos.find($filaten({ info: { mtime: $stale("1d") } }))
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
.
|
|
27
|
-
.then(
|
|
28
|
-
.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
console.log(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
repository
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
1
|
+
import { dissoc } from "rambda";
|
|
2
|
+
import sflow from "sflow";
|
|
3
|
+
import { match } from "ts-pattern";
|
|
4
|
+
import { $OK, TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
5
|
+
import { CNRepos } from "./CNRepos";
|
|
6
|
+
import { getWorkerInstance } from "./WorkerInstances";
|
|
7
|
+
import { $filaten, $stale } from "./db";
|
|
8
|
+
import { gh } from "./gh";
|
|
9
|
+
import { parseUrlRepoOwner } from "./parseOwnerRepo";
|
|
10
|
+
import { tLog } from "./utils/tLog";
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
await getWorkerInstance("updateCNReposInfo");
|
|
14
|
+
await tLog("updateCNReposInfo", updateCNReposInfo);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function updateCNReposInfo() {
|
|
18
|
+
await CNRepos.createIndex($filaten({ info: { mtime: 1 } }));
|
|
19
|
+
return await sflow(
|
|
20
|
+
CNRepos.find($filaten({ info: { mtime: $stale("1d") } }))
|
|
21
|
+
).pMap(
|
|
22
|
+
async (repo) => {
|
|
23
|
+
const { repository } = repo;
|
|
24
|
+
console.log("[INFO] Fetching meta info from " + repository);
|
|
25
|
+
const _info = await gh.repos
|
|
26
|
+
.get({ ...parseUrlRepoOwner(repository) })
|
|
27
|
+
.then(({ data }) => data)
|
|
28
|
+
.then(TaskOK)
|
|
29
|
+
.catch(TaskError);
|
|
30
|
+
// Handle renamed repos
|
|
31
|
+
const { info, url } = await match(_info)
|
|
32
|
+
.with($OK, async (info) => {
|
|
33
|
+
const url = info.data.html_url;
|
|
34
|
+
if (url === repository) return { info, url: repository };
|
|
35
|
+
|
|
36
|
+
// console.log(info.data.use_squash_pr_title_as_default)
|
|
37
|
+
console.log("[INFO] Migrating renamed repo: \nfrom: ", repository + "\n to: " + url);
|
|
38
|
+
// migrate data into new CNRepo
|
|
39
|
+
await CNRepos.updateOne(
|
|
40
|
+
{ repository: url },
|
|
41
|
+
{
|
|
42
|
+
$set: {
|
|
43
|
+
...dissoc("_id", { ...(await CNRepos.findOneAndDelete({ repository })) }),
|
|
44
|
+
repository: url,
|
|
45
|
+
oldUrls: { $addToSet: repository },
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{ upsert: true },
|
|
49
|
+
);
|
|
50
|
+
return { info, url };
|
|
51
|
+
})
|
|
52
|
+
.otherwise((info) => ({ info, url: repository }));
|
|
53
|
+
|
|
54
|
+
return await CNRepos.updateOne({ repository: url }, { $set: { info } }, { upsert: true });
|
|
55
|
+
},
|
|
56
|
+
{ concurrency: 2 },
|
|
57
|
+
).toArray();
|
|
58
|
+
}
|
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
|
|
2
|
-
import pMap from "p-map";
|
|
3
|
-
import { peekYaml } from "peek-log";
|
|
4
|
-
import { match } from "ts-pattern";
|
|
5
|
-
import { $OK, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
6
|
-
import { CNRepos } from "./CNRepos";
|
|
7
|
-
import { $filaten, $fresh, $stale } from "./db";
|
|
8
|
-
import { updateCNReposPulls } from "./updateCNReposPulls";
|
|
9
|
-
import { updateCNReposRelatedPulls } from "./updateCNReposRelatedPulls";
|
|
10
|
-
import { tLog } from "./utils/tLog";
|
|
11
|
-
if (import.meta.main) {
|
|
12
|
-
console.log(await updateCNReposPRCandidate());
|
|
13
|
-
// show candidates
|
|
14
|
-
// console.log(
|
|
15
|
-
// YAML.stringify(
|
|
16
|
-
// await CNRepos.find($filaten({ candidate: { data: { $eq: true } } }))
|
|
17
|
-
// .map((e) => ({
|
|
18
|
-
// // candidate: match(e.candidate)
|
|
19
|
-
// // .with($OK, (e) => e)
|
|
20
|
-
// // .otherwise(() => DIE("")).data,
|
|
21
|
-
// repo: e.repository + "/pulls?q=",
|
|
22
|
-
// }))
|
|
23
|
-
// .toArray(),
|
|
24
|
-
// ),
|
|
25
|
-
// );
|
|
26
|
-
tLog("updateCNReposPulls", updateCNReposPulls);
|
|
27
|
-
tLog("updateCNReposRelatedPulls", updateCNReposRelatedPulls);
|
|
28
|
-
|
|
29
|
-
await CNRepos.createIndex("crPulls.mtime");
|
|
30
|
-
// show candidates
|
|
31
|
-
peekYaml(
|
|
32
|
-
await $pipeline(CNRepos)
|
|
33
|
-
.match(
|
|
34
|
-
$filaten({
|
|
35
|
-
crPulls: { mtime: $stale("7d") },
|
|
36
|
-
// info: { mtime: $fresh("7d"), data: { private: false, archived: false } },
|
|
37
|
-
// createdPulls: { mtime: $stale("7d"), data: { $exists: false } },
|
|
38
|
-
}),
|
|
39
|
-
)
|
|
40
|
-
.aggregate()
|
|
41
|
-
.map((e) => ({
|
|
42
|
-
repo: e.repository + "/pulls?q=",
|
|
43
|
-
pulls: match(e.pulls)
|
|
44
|
-
.with($OK, ({ data }) => data)
|
|
45
|
-
.otherwise(() => null)?.length,
|
|
46
|
-
crPulls: match(e.crPulls)
|
|
47
|
-
.with($OK, ({ data }) => data)
|
|
48
|
-
.otherwise(() => null)?.length,
|
|
49
|
-
}))
|
|
50
|
-
.toArray(),
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export async function updateCNReposPRCandidate() {
|
|
55
|
-
return await pMap(
|
|
56
|
-
$pipeline(CNRepos)
|
|
57
|
-
.match(
|
|
58
|
-
$filaten({
|
|
59
|
-
crPulls: { mtime: $fresh("1d"), ...$OK },
|
|
60
|
-
// info: { mtime: $fresh("7d"), ...$OK, data: { private: false, archived: false } },
|
|
61
|
-
info: { mtime: $fresh("7d"), ...$OK },
|
|
62
|
-
// createdPulls: { state: { $ne: "ok" }, mtime: $stale("5m") },
|
|
63
|
-
candidate: { mtime: $stale("1d") },
|
|
64
|
-
}),
|
|
65
|
-
)
|
|
66
|
-
.aggregate(),
|
|
67
|
-
async (repo) => {
|
|
68
|
-
const crPulls = match(repo.crPulls)
|
|
69
|
-
.with($OK, (e) => e.data)
|
|
70
|
-
.otherwise(() => null)!;
|
|
71
|
-
const info = match(repo.info)
|
|
72
|
-
.with($OK, (e) => e.data)
|
|
73
|
-
.otherwise(() => null)!;
|
|
74
|
-
|
|
75
|
-
const isCandidate = !info.private && !info.archived && crPulls.length === 0;
|
|
76
|
-
const candidate = TaskOK(isCandidate);
|
|
77
|
-
|
|
78
|
-
// silent
|
|
79
|
-
// if (isCandidate)
|
|
80
|
-
// await notifySlackLinks("Found new PR candidate", [repo.repository]);
|
|
81
|
-
await CNRepos.updateOne({ repository: repo.repository }, { $set: { candidate } });
|
|
82
|
-
return repo;
|
|
83
|
-
},
|
|
84
|
-
);
|
|
85
|
-
}
|
|
1
|
+
import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
|
|
2
|
+
import pMap from "p-map";
|
|
3
|
+
import { peekYaml } from "peek-log";
|
|
4
|
+
import { match } from "ts-pattern";
|
|
5
|
+
import { $OK, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
6
|
+
import { CNRepos } from "./CNRepos";
|
|
7
|
+
import { $filaten, $fresh, $stale } from "./db";
|
|
8
|
+
import { updateCNReposPulls } from "./updateCNReposPulls";
|
|
9
|
+
import { updateCNReposRelatedPulls } from "./updateCNReposRelatedPulls";
|
|
10
|
+
import { tLog } from "./utils/tLog";
|
|
11
|
+
if (import.meta.main) {
|
|
12
|
+
console.log(await updateCNReposPRCandidate());
|
|
13
|
+
// show candidates
|
|
14
|
+
// console.log(
|
|
15
|
+
// YAML.stringify(
|
|
16
|
+
// await CNRepos.find($filaten({ candidate: { data: { $eq: true } } }))
|
|
17
|
+
// .map((e) => ({
|
|
18
|
+
// // candidate: match(e.candidate)
|
|
19
|
+
// // .with($OK, (e) => e)
|
|
20
|
+
// // .otherwise(() => DIE("")).data,
|
|
21
|
+
// repo: e.repository + "/pulls?q=",
|
|
22
|
+
// }))
|
|
23
|
+
// .toArray(),
|
|
24
|
+
// ),
|
|
25
|
+
// );
|
|
26
|
+
tLog("updateCNReposPulls", updateCNReposPulls);
|
|
27
|
+
tLog("updateCNReposRelatedPulls", updateCNReposRelatedPulls);
|
|
28
|
+
|
|
29
|
+
await CNRepos.createIndex("crPulls.mtime");
|
|
30
|
+
// show candidates
|
|
31
|
+
peekYaml(
|
|
32
|
+
await $pipeline(CNRepos)
|
|
33
|
+
.match(
|
|
34
|
+
$filaten({
|
|
35
|
+
crPulls: { mtime: $stale("7d") },
|
|
36
|
+
// info: { mtime: $fresh("7d"), data: { private: false, archived: false } },
|
|
37
|
+
// createdPulls: { mtime: $stale("7d"), data: { $exists: false } },
|
|
38
|
+
}),
|
|
39
|
+
)
|
|
40
|
+
.aggregate()
|
|
41
|
+
.map((e) => ({
|
|
42
|
+
repo: e.repository + "/pulls?q=",
|
|
43
|
+
pulls: match(e.pulls)
|
|
44
|
+
.with($OK, ({ data }) => data)
|
|
45
|
+
.otherwise(() => null)?.length,
|
|
46
|
+
crPulls: match(e.crPulls)
|
|
47
|
+
.with($OK, ({ data }) => data)
|
|
48
|
+
.otherwise(() => null)?.length,
|
|
49
|
+
}))
|
|
50
|
+
.toArray(),
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function updateCNReposPRCandidate() {
|
|
55
|
+
return await pMap(
|
|
56
|
+
$pipeline(CNRepos)
|
|
57
|
+
.match(
|
|
58
|
+
$filaten({
|
|
59
|
+
crPulls: { mtime: $fresh("1d"), ...$OK },
|
|
60
|
+
// info: { mtime: $fresh("7d"), ...$OK, data: { private: false, archived: false } },
|
|
61
|
+
info: { mtime: $fresh("7d"), ...$OK },
|
|
62
|
+
// createdPulls: { state: { $ne: "ok" }, mtime: $stale("5m") },
|
|
63
|
+
candidate: { mtime: $stale("1d") },
|
|
64
|
+
}),
|
|
65
|
+
)
|
|
66
|
+
.aggregate(),
|
|
67
|
+
async (repo) => {
|
|
68
|
+
const crPulls = match(repo.crPulls)
|
|
69
|
+
.with($OK, (e) => e.data)
|
|
70
|
+
.otherwise(() => null)!;
|
|
71
|
+
const info = match(repo.info)
|
|
72
|
+
.with($OK, (e) => e.data)
|
|
73
|
+
.otherwise(() => null)!;
|
|
74
|
+
|
|
75
|
+
const isCandidate = !info.private && !info.archived && crPulls.length === 0;
|
|
76
|
+
const candidate = TaskOK(isCandidate);
|
|
77
|
+
|
|
78
|
+
// silent
|
|
79
|
+
// if (isCandidate)
|
|
80
|
+
// await notifySlackLinks("Found new PR candidate", [repo.repository]);
|
|
81
|
+
await CNRepos.updateOne({ repository: repo.repository }, { $set: { candidate } });
|
|
82
|
+
return repo;
|
|
83
|
+
},
|
|
84
|
+
);
|
|
85
|
+
}
|
|
@@ -1,28 +1,31 @@
|
|
|
1
|
-
import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
|
|
2
|
-
import
|
|
3
|
-
import { match } from "ts-pattern";
|
|
4
|
-
import { $OK, TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
5
|
-
import { CNRepos } from "./CNRepos";
|
|
6
|
-
import { $filaten, $stale } from "./db";
|
|
7
|
-
import { fetchGithubPulls } from "./gh/fetchGithubPulls";
|
|
8
|
-
import { tLog } from "./utils/tLog";
|
|
9
|
-
if (import.meta.main) {
|
|
10
|
-
console.log(await tLog("Update CNRepos for Github Pulls", updateCNReposPulls));
|
|
11
|
-
}
|
|
12
|
-
export async function updateCNReposPulls() {
|
|
13
|
-
await CNRepos.createIndex("pulls.mtime");
|
|
14
|
-
return await
|
|
15
|
-
$pipeline(CNRepos)
|
|
16
|
-
.match($filaten({ pulls: { mtime: $stale("1d") } }))
|
|
17
|
-
.project({ repository: 1 })
|
|
18
|
-
.aggregate(),
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
1
|
+
import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
|
|
2
|
+
import sflow from "sflow";
|
|
3
|
+
import { match } from "ts-pattern";
|
|
4
|
+
import { $OK, TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
5
|
+
import { CNRepos } from "./CNRepos";
|
|
6
|
+
import { $filaten, $stale } from "./db";
|
|
7
|
+
import { fetchGithubPulls } from "./gh/fetchGithubPulls";
|
|
8
|
+
import { tLog } from "./utils/tLog";
|
|
9
|
+
if (import.meta.main) {
|
|
10
|
+
console.log(await tLog("Update CNRepos for Github Pulls", updateCNReposPulls));
|
|
11
|
+
}
|
|
12
|
+
export async function updateCNReposPulls() {
|
|
13
|
+
await CNRepos.createIndex("pulls.mtime");
|
|
14
|
+
return await sflow(
|
|
15
|
+
$pipeline(CNRepos)
|
|
16
|
+
.match($filaten({ pulls: { mtime: $stale("1d") } }))
|
|
17
|
+
.project({ repository: 1 })
|
|
18
|
+
.aggregate(),
|
|
19
|
+
)
|
|
20
|
+
.pMap(
|
|
21
|
+
async ({ repository }) => {
|
|
22
|
+
const pulls = await fetchGithubPulls(repository).then(TaskOK).catch(TaskError);
|
|
23
|
+
match(pulls)
|
|
24
|
+
.with($OK, ({ data }) => console.debug(`[DEBUG] fetched ${data.length} Pulls from ${repository}`))
|
|
25
|
+
.otherwise(() => {});
|
|
26
|
+
return await CNRepos.updateOne({ repository }, { $set: { pulls } });
|
|
27
|
+
},
|
|
28
|
+
{ concurrency: 2 },
|
|
29
|
+
)
|
|
30
|
+
.toArray();
|
|
31
|
+
}
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import DIE from "@snomiao/die";
|
|
2
|
-
import { match } from "ts-pattern";
|
|
3
|
-
import { $OK } from "../packages/mongodb-pipeline-ts/Task";
|
|
4
|
-
import { CNRepos } from "./CNRepos";
|
|
5
|
-
import { $filaten, $fresh } from "./db";
|
|
6
|
-
import { gh } from "./gh";
|
|
7
|
-
import { ghUser } from "./ghUser";
|
|
8
|
-
import { parseUrlRepoOwner, stringifyOwnerRepo } from "./parseOwnerRepo";
|
|
9
|
-
|
|
10
|
-
export async function updateCNRepoPullsDashboard() {
|
|
11
|
-
if (ghUser.login !== "snomiao") return [];
|
|
12
|
-
const dashBoardIssue = process.env.DASHBOARD_ISSUE_URL || DIE("DASHBOARD_ISSUE_URL not found");
|
|
13
|
-
const dashBoardRepo = dashBoardIssue.replace(/\/issues\/\d+$/, "");
|
|
14
|
-
const dashBoardIssueNumber = Number(dashBoardIssue.match(/\/issues\/(\d+)$/)?.[1] || DIE("Issue number not found"));
|
|
15
|
-
// update dashboard issue if run by @snomiao
|
|
16
|
-
const repos = await CNRepos.find($filaten({ crPulls: { mtime: $fresh("1d") } })).toArray();
|
|
17
|
-
const result = repos
|
|
18
|
-
.map((repo) => {
|
|
19
|
-
const crPulls = match(repo.crPulls)
|
|
20
|
-
.with($OK, ({ data }) => data)
|
|
21
|
-
.otherwise(() => DIE("CR Pulls not found"));
|
|
22
|
-
const repoName = stringifyOwnerRepo(parseUrlRepoOwner(repo.repository));
|
|
23
|
-
const body = crPulls
|
|
24
|
-
.filter((e) => e.pull.prState !== "closed")
|
|
25
|
-
.map((e) => {
|
|
26
|
-
const date = new Date(e.pull.createdAt).toISOString().slice(0, 10);
|
|
27
|
-
const state = e.pull.prState.toUpperCase();
|
|
28
|
-
return {
|
|
29
|
-
href: e.pull.html_url,
|
|
30
|
-
name: `PR ${date} ${state}: ${repoName} #${e.type}`,
|
|
31
|
-
};
|
|
32
|
-
})
|
|
33
|
-
.map(({ href, name }) => `- [${name}](${href})`)
|
|
34
|
-
.toSorted()
|
|
35
|
-
.join("\n");
|
|
36
|
-
return body;
|
|
37
|
-
})
|
|
38
|
-
.filter(Boolean)
|
|
39
|
-
.join("\n");
|
|
40
|
-
const body = result;
|
|
41
|
-
|
|
42
|
-
return [
|
|
43
|
-
await gh.issues.update({
|
|
44
|
-
...parseUrlRepoOwner(dashBoardRepo),
|
|
45
|
-
issue_number: dashBoardIssueNumber,
|
|
46
|
-
body,
|
|
47
|
-
}),
|
|
48
|
-
];
|
|
49
|
-
}
|
|
1
|
+
import DIE from "@snomiao/die";
|
|
2
|
+
import { match } from "ts-pattern";
|
|
3
|
+
import { $OK } from "../packages/mongodb-pipeline-ts/Task";
|
|
4
|
+
import { CNRepos } from "./CNRepos";
|
|
5
|
+
import { $filaten, $fresh } from "./db";
|
|
6
|
+
import { gh } from "./gh";
|
|
7
|
+
import { ghUser } from "./ghUser";
|
|
8
|
+
import { parseUrlRepoOwner, stringifyOwnerRepo } from "./parseOwnerRepo";
|
|
9
|
+
|
|
10
|
+
export async function updateCNRepoPullsDashboard() {
|
|
11
|
+
if (ghUser.login !== "snomiao") return [];
|
|
12
|
+
const dashBoardIssue = process.env.DASHBOARD_ISSUE_URL || DIE("DASHBOARD_ISSUE_URL not found");
|
|
13
|
+
const dashBoardRepo = dashBoardIssue.replace(/\/issues\/\d+$/, "");
|
|
14
|
+
const dashBoardIssueNumber = Number(dashBoardIssue.match(/\/issues\/(\d+)$/)?.[1] || DIE("Issue number not found"));
|
|
15
|
+
// update dashboard issue if run by @snomiao
|
|
16
|
+
const repos = await CNRepos.find($filaten({ crPulls: { mtime: $fresh("1d") } })).toArray();
|
|
17
|
+
const result = repos
|
|
18
|
+
.map((repo) => {
|
|
19
|
+
const crPulls = match(repo.crPulls)
|
|
20
|
+
.with($OK, ({ data }) => data)
|
|
21
|
+
.otherwise(() => DIE("CR Pulls not found"));
|
|
22
|
+
const repoName = stringifyOwnerRepo(parseUrlRepoOwner(repo.repository));
|
|
23
|
+
const body = crPulls
|
|
24
|
+
.filter((e) => e.pull.prState !== "closed")
|
|
25
|
+
.map((e) => {
|
|
26
|
+
const date = new Date(e.pull.createdAt).toISOString().slice(0, 10);
|
|
27
|
+
const state = e.pull.prState.toUpperCase();
|
|
28
|
+
return {
|
|
29
|
+
href: e.pull.html_url,
|
|
30
|
+
name: `PR ${date} ${state}: ${repoName} #${e.type}`,
|
|
31
|
+
};
|
|
32
|
+
})
|
|
33
|
+
.map(({ href, name }) => `- [${name}](${href})`)
|
|
34
|
+
.toSorted()
|
|
35
|
+
.join("\n");
|
|
36
|
+
return body;
|
|
37
|
+
})
|
|
38
|
+
.filter(Boolean)
|
|
39
|
+
.join("\n");
|
|
40
|
+
const body = result;
|
|
41
|
+
|
|
42
|
+
return [
|
|
43
|
+
await gh.issues.update({
|
|
44
|
+
...parseUrlRepoOwner(dashBoardRepo),
|
|
45
|
+
issue_number: dashBoardIssueNumber,
|
|
46
|
+
body,
|
|
47
|
+
}),
|
|
48
|
+
];
|
|
49
|
+
}
|