comfy-pr 0.2.26 → 1.0.1
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 +258 -157
- package/bot/IdleWaiter.ts +31 -0
- package/bot/RestartManager.spec.ts +163 -0
- package/bot/RestartManager.ts +190 -0
- package/bot/WorkingTasksManager.spec.ts +154 -0
- package/bot/cli.ts +1171 -0
- package/bot/codesearch-ai-wip.ts +351 -0
- package/bot/error-collector.ts +133 -0
- package/bot/index.ts +14 -0
- package/bot/restart-example.ts +99 -0
- package/bot/slack-bolt.ts +688 -0
- package/bot/slack-bot.ts +1575 -0
- package/bot/state.ts +19 -0
- package/bot/templateLoader.test.ts +84 -0
- package/bot/templateLoader.ts +92 -0
- package/next.config.ts +26 -0
- package/package.json +161 -41
- package/post-summary.ts +44 -0
- package/src/Authors.ts +2 -2
- package/src/CMNodes.ts +3 -3
- package/src/CNRepos.ts +30 -7
- package/src/CRNodes.ts +11 -9
- package/src/CRPulls.ts +3 -0
- package/src/EmailTasks.ts +27 -9
- package/src/FORK_OWNER.ts +3 -1
- package/src/FollowRules.ts +3 -3
- package/src/GithubIssueComments.ts +1 -1
- package/src/Totals.ts +9 -8
- package/src/WorkerInstances.ts +31 -8
- package/src/addCommentAction.ts +19 -11
- package/src/analyzePullsStatus.ts +39 -17
- package/src/analyzeTotals.ts +19 -11
- package/src/bypassRepos.ts +6 -5
- package/src/checkPRsFailures.ts +13 -8
- package/src/cli.test.ts +2 -0
- package/src/cli.ts +1 -1
- package/src/constants.ts +2 -0
- package/src/createComfyRegistryPRsFromCandidates.ts +20 -12
- package/src/createComfyRegistryPullRequests.ts +35 -10
- package/src/createGithubForkForRepo.ts +36 -11
- package/src/createGithubPullRequest.ts +83 -33
- package/src/createIssueComment.ts +4 -4
- package/src/fetchComfyRegistryNodes.ts +34 -4
- package/src/fetchCurrentGeoInfo.ts +3 -1
- package/src/fetchRelatedPullWithComments.ts +1 -1
- package/src/fetchRepoDescriptionMap.ts +1 -4
- package/src/followRuleSchema.ts +10 -4
- package/src/getBranchWorkingDir.ts +3 -7
- package/src/getRepoWorkingDir.ts +2 -3
- package/src/gh.spec.ts +571 -0
- package/src/ghData.ts +13 -0
- package/src/ghPageFlow.ts +33 -0
- package/src/ghSubscriber.ts +76 -0
- package/src/ghUser.ts +28 -4
- package/src/index.ts +13 -4
- package/src/initializeFollowRules.ts +11 -4
- package/src/logger.spec.ts +95 -0
- package/src/logger.ts +46 -0
- package/src/makeGpl3LicenseBranch.ts +66 -0
- package/src/makePublishBranch.ts +21 -15
- package/src/makeTomlBranch.ts +48 -14
- package/src/makeUpdateTomlLicenseBranch.ts +40 -44
- package/src/matchRelatedPulls.ts +9 -4
- package/src/normalizeGithubUrl.spec.ts +131 -0
- package/src/normalizeGithubUrl.ts +64 -0
- package/src/parseIssueUrl.spec.ts +95 -0
- package/src/parseIssueUrl.ts +17 -3
- package/src/parseOwnerRepo.spec.ts +147 -0
- package/src/parseOwnerRepo.ts +8 -5
- package/src/parsePullsState.ts +2 -2
- package/src/parseTitleBodyOfMarkdown.ts +1 -1
- package/src/pickRepoInfo.ts +37 -0
- package/src/postSlackMessage.ts +5 -1
- package/src/preload.ts +30 -27
- package/src/readTemplateTitle.ts +1 -3
- package/src/sendEmailAction.ts +14 -10
- package/src/sendGmail.ts +3 -3
- package/src/updateAuthorsForGithub.ts +53 -35
- package/src/updateAuthorsFromCNRepo.ts +12 -5
- package/src/updateCMNodesDuplicationWarnings.ts +14 -9
- package/src/updateCMRepos.ts +1 -1
- package/src/updateCNRepos.ts +14 -14
- package/src/updateCNReposCRPullsComments.ts +7 -5
- package/src/updateCNReposInfo.ts +49 -40
- package/src/updateCNReposPRCandidate.ts +3 -3
- package/src/updateCNReposPulls.ts +9 -5
- package/src/updateCNReposPullsDashboard.ts +11 -9
- package/src/updateCNReposRelatedPulls.ts +3 -3
- package/src/updateCRNodes.ts +24 -5
- package/src/updateCRRepos.ts +1 -1
- package/src/updateComfyTotals.ts +7 -5
- package/src/updateFollowRuleSet.ts +17 -9
- package/src/updateOutdatedPullsTemplates.ts +61 -48
- package/src/updateSlackMessages.ts +8 -4
- package/tailwind.config.ts +7 -1
- package/next-env.d.ts +0 -5
- package/src/GIT_USEREMAIL.ts +0 -5
- package/src/GIT_USERNAME.ts +0 -9
- package/src/clone_modify_push_Branches.ts +0 -21
- package/src/tomlFillDescription.ts +0 -17
package/src/sendEmailAction.ts
CHANGED
|
@@ -3,11 +3,11 @@ import { $elemMatch } from "@/packages/mongodb-pipeline-ts/$elemMatch";
|
|
|
3
3
|
import { TaskDataOrNull, type Task } from "@/packages/mongodb-pipeline-ts/Task";
|
|
4
4
|
import DIE from "@snomiao/die";
|
|
5
5
|
import pMap from "p-map";
|
|
6
|
-
import {
|
|
6
|
+
import { sflow } from "sflow";
|
|
7
7
|
import type { z } from "zod";
|
|
8
8
|
import type { PullStatusShown } from "./analyzePullsStatus";
|
|
9
9
|
import { CNRepos } from "./CNRepos";
|
|
10
|
-
import { $
|
|
10
|
+
import { $flatten } from "./db";
|
|
11
11
|
import { enqueueEmailTask } from "./EmailTasks";
|
|
12
12
|
import { zSendEmailAction } from "./followRuleSchema";
|
|
13
13
|
import { yaml } from "./utils/yaml";
|
|
@@ -27,14 +27,15 @@ export async function sendEmailAction({
|
|
|
27
27
|
TaskDataOrNull(matched) ?? DIE("NO-PAYLOAD-AVAILABLE"),
|
|
28
28
|
async (payload) => {
|
|
29
29
|
if (action.provider !== "google") DIE("Currently we only support gmail sender");
|
|
30
|
-
const loadedAction = await
|
|
30
|
+
const loadedAction = await sflow([action])
|
|
31
31
|
.map((e) => yaml.stringify(e))
|
|
32
32
|
.map((e) =>
|
|
33
33
|
// replace {{var}} s
|
|
34
|
-
e.replace(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
e.replace(/{{\$([_A-Za-z0-9]+)}}/g, (_, key: string) =>
|
|
35
|
+
String(
|
|
36
|
+
(payload as Record<string, unknown>)[key] ??
|
|
37
|
+
DIE("Missing key: " + key + " in payload: " + JSON.stringify(payload)),
|
|
38
|
+
),
|
|
38
39
|
),
|
|
39
40
|
)
|
|
40
41
|
.map((e) => yaml.parse(e))
|
|
@@ -45,9 +46,12 @@ export async function sendEmailAction({
|
|
|
45
46
|
if (runAction) {
|
|
46
47
|
const task = await enqueueEmailTask(loadedAction);
|
|
47
48
|
console.log(rule.name + " email enqueued :" + yaml.stringify(loadedAction));
|
|
48
|
-
await CNRepos.updateOne(
|
|
49
|
-
$
|
|
50
|
-
|
|
49
|
+
await CNRepos.updateOne(
|
|
50
|
+
$flatten({ crPulls: { data: $elemMatch({ pull: { html_url: payload.url } }) } }),
|
|
51
|
+
{
|
|
52
|
+
$set: { "crPulls.data.$.emailTask_id": task._id },
|
|
53
|
+
},
|
|
54
|
+
);
|
|
51
55
|
}
|
|
52
56
|
return loadedAction;
|
|
53
57
|
},
|
package/src/sendGmail.ts
CHANGED
|
@@ -91,9 +91,9 @@ export async function sendGmail({
|
|
|
91
91
|
msg.setSender({ name: name, addr: from });
|
|
92
92
|
msg.setRecipient(to);
|
|
93
93
|
msg.setSubject(subject);
|
|
94
|
-
text
|
|
95
|
-
html
|
|
96
|
-
text
|
|
94
|
+
if (text) msg.addMessage({ contentType: "text/plain", data: text });
|
|
95
|
+
if (html) msg.addMessage({ contentType: "text/html", data: html });
|
|
96
|
+
if (!text && !html) DIE("Missing msg body");
|
|
97
97
|
|
|
98
98
|
const result = await new GoogleApis().gmail("v1").users.messages.send({
|
|
99
99
|
auth,
|
|
@@ -2,53 +2,71 @@ import { $OK, TaskDataOrNull, TaskError, TaskOK } from "@/packages/mongodb-pipel
|
|
|
2
2
|
import DIE from "@snomiao/die";
|
|
3
3
|
import console from "console";
|
|
4
4
|
import { peekYaml } from "peek-log";
|
|
5
|
-
import {
|
|
5
|
+
import { sflow } from "sflow";
|
|
6
6
|
import { Authors, GithubUsers } from "./Authors";
|
|
7
7
|
import { $stale } from "./db";
|
|
8
|
-
import { gh } from "
|
|
8
|
+
import { gh } from "@/lib/github";
|
|
9
9
|
|
|
10
10
|
if (import.meta.main) {
|
|
11
11
|
await updateAuthorsForGithub();
|
|
12
12
|
}
|
|
13
13
|
export async function updateAuthorsForGithub() {
|
|
14
|
-
await
|
|
14
|
+
await sflow(Authors.find({ githubMtime: $stale("7d") }))
|
|
15
15
|
.map((e) => e.githubId)
|
|
16
16
|
.filter()
|
|
17
|
-
.pMap(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
17
|
+
.pMap(
|
|
18
|
+
async (username) => {
|
|
19
|
+
const cached = await GithubUsers.findOne({ username, mtime: $stale("1d"), ...$OK });
|
|
20
|
+
if (cached) return cached;
|
|
21
|
+
console.log("Fetching github user " + username);
|
|
22
|
+
const result = await gh.users
|
|
23
|
+
.getByUsername({ username })
|
|
24
|
+
.then((e) => e.data)
|
|
25
|
+
.then(TaskOK)
|
|
26
|
+
.catch(TaskError);
|
|
27
|
+
return (
|
|
28
|
+
(await GithubUsers.findOneAndUpdate(
|
|
29
|
+
{ username },
|
|
30
|
+
{ $set: result },
|
|
31
|
+
{ returnDocument: "after", upsert: true },
|
|
32
|
+
)) ?? DIE(`fail to udpate gh users`)
|
|
33
|
+
);
|
|
34
|
+
},
|
|
35
|
+
{ concurrency: 2 },
|
|
36
|
+
)
|
|
34
37
|
.map((e) => TaskDataOrNull(e))
|
|
35
38
|
.filter()
|
|
36
|
-
.map(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
.map(
|
|
40
|
+
({
|
|
41
|
+
email,
|
|
42
|
+
avatar_url,
|
|
43
|
+
blog,
|
|
44
|
+
updated_at: _updated_at,
|
|
45
|
+
location,
|
|
46
|
+
company,
|
|
47
|
+
hireable,
|
|
48
|
+
bio,
|
|
49
|
+
login,
|
|
50
|
+
}) =>
|
|
51
|
+
Authors.findOneAndUpdate(
|
|
52
|
+
{ githubId: login },
|
|
53
|
+
{
|
|
54
|
+
$set: {
|
|
55
|
+
githubMtime: new Date(),
|
|
56
|
+
...(email && { email }),
|
|
57
|
+
...(null != hireable && { hireable }),
|
|
58
|
+
},
|
|
59
|
+
$addToSet: {
|
|
60
|
+
...(bio && { bios: bio }),
|
|
61
|
+
avatars: avatar_url,
|
|
62
|
+
...(location && { locations: location }),
|
|
63
|
+
...(blog && { blogs: blog }),
|
|
64
|
+
...(company && { companies: company }),
|
|
65
|
+
},
|
|
47
66
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
),
|
|
67
|
+
{ upsert: true, returnDocument: "after" },
|
|
68
|
+
),
|
|
51
69
|
)
|
|
52
|
-
.
|
|
70
|
+
.forEach(peekYaml)
|
|
53
71
|
.done();
|
|
54
72
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
|
|
2
|
-
import {
|
|
2
|
+
import { sflow } from "sflow";
|
|
3
3
|
import { Authors } from "./Authors";
|
|
4
4
|
import { CNRepos } from "./CNRepos";
|
|
5
|
-
import { $
|
|
5
|
+
import { $flatten } from "./db";
|
|
6
6
|
|
|
7
7
|
/** Update authors for gh users, collecting emails/username/hireable */
|
|
8
8
|
export async function updateAuthorsFromCNRepo() {
|
|
9
|
-
return await
|
|
9
|
+
return await sflow(
|
|
10
10
|
$pipeline(CNRepos)
|
|
11
|
-
.match($
|
|
11
|
+
.match($flatten({ info: { data: { owner: { login: { $exists: true } } } } }))
|
|
12
12
|
.group({
|
|
13
13
|
_id: "$info.data.owner.login",
|
|
14
14
|
// author: "$info.data.owner.login",
|
|
@@ -25,6 +25,13 @@ export async function updateAuthorsFromCNRepo() {
|
|
|
25
25
|
.project({ _id: 0 })
|
|
26
26
|
.aggregate(),
|
|
27
27
|
)
|
|
28
|
-
.map((
|
|
28
|
+
.map((doc) => {
|
|
29
|
+
const { githubId, ...$set } = doc as Record<string, unknown>;
|
|
30
|
+
return Authors.updateOne(
|
|
31
|
+
{ githubId: githubId as string | undefined },
|
|
32
|
+
{ $set: $set as Record<string, unknown> } as Parameters<typeof Authors.updateOne>[1],
|
|
33
|
+
{ upsert: true },
|
|
34
|
+
);
|
|
35
|
+
})
|
|
29
36
|
.done();
|
|
30
37
|
}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import { unary } from "lodash-es";
|
|
2
1
|
import pMap from "p-map";
|
|
3
|
-
import {
|
|
2
|
+
import { filter, groupBy, map, prop, toPairs } from "rambda";
|
|
4
3
|
import YAML from "yaml";
|
|
5
4
|
import { CMNodes, type CMNode } from "./CMNodes";
|
|
6
|
-
import { notifySlack } from "
|
|
5
|
+
import { notifySlack } from "@/lib/slack/notifySlack";
|
|
7
6
|
|
|
8
7
|
export async function updateCMNodesDuplicationWarnings(nodes: CMNode[]) {
|
|
9
8
|
console.log("CMNodes checking duplicates");
|
|
9
|
+
const idGroups = groupBy((e) => e.id, nodes);
|
|
10
|
+
const titleGroups = groupBy((e) => e.title, nodes);
|
|
11
|
+
const referenceGroups = groupBy((e) => e.reference, nodes);
|
|
10
12
|
// prettier-ignore
|
|
11
13
|
const dups = {
|
|
12
|
-
ID: filter((e
|
|
13
|
-
TITLE: filter((e
|
|
14
|
-
REFERENCE: filter((e
|
|
14
|
+
ID: filter((e?: CMNode[]) => (e?.length??0) > 1, idGroups),
|
|
15
|
+
TITLE: filter((e?: CMNode[]) => (e?.length??0) > 1, titleGroups),
|
|
16
|
+
REFERENCE: filter((e?: CMNode[]) => (e?.length??0) > 1, referenceGroups),
|
|
15
17
|
};
|
|
16
|
-
const dupsSummary = JSON.stringify(map((x) => map((x) => x
|
|
18
|
+
const dupsSummary = JSON.stringify(map((x) => map((x) => x?.length ?? 0, x), dups));
|
|
17
19
|
await notifySlack(
|
|
18
20
|
`[WARN] CMNodes duplicates: ${dupsSummary}\nSolve them in https://github.com/ltdrdata/ComfyUI-Manager/blob/main/custom-node-list.json`,
|
|
19
21
|
);
|
|
@@ -24,8 +26,11 @@ export async function updateCMNodesDuplicationWarnings(nodes: CMNode[]) {
|
|
|
24
26
|
await pMap(
|
|
25
27
|
toPairs(nodes),
|
|
26
28
|
async ([key, nodesRaw]) => {
|
|
27
|
-
const nodes = nodesRaw
|
|
28
|
-
|
|
29
|
+
const nodes = nodesRaw?.map((nodeRaw) => {
|
|
30
|
+
const { hash: _hash, ...node } = { ...nodeRaw };
|
|
31
|
+
return node;
|
|
32
|
+
});
|
|
33
|
+
const hashes = nodesRaw?.map(prop("hash"));
|
|
29
34
|
// check sent
|
|
30
35
|
const someDuplicateSent = await CMNodes.findOne({
|
|
31
36
|
hash: { $in: hashes },
|
package/src/updateCMRepos.ts
CHANGED
|
@@ -8,7 +8,7 @@ if (import.meta.main) {
|
|
|
8
8
|
}
|
|
9
9
|
export async function updateCMRepos() {
|
|
10
10
|
await CMNodes.createIndex({ repo_id: 1 });
|
|
11
|
-
return await pMap(CMNodes.find({ repo_id: { $exists: false } }), async (cm,
|
|
11
|
+
return await pMap(CMNodes.find({ repo_id: { $exists: false } }), async (cm, _i) => {
|
|
12
12
|
const { reference: repository, _id } = cm;
|
|
13
13
|
return await CNRepos.updateOne(
|
|
14
14
|
{ repository },
|
package/src/updateCNRepos.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { updateCMNodes } from "./CMNodes";
|
|
2
2
|
import { getWorkerInstance } from "./WorkerInstances";
|
|
3
3
|
import { createComfyRegistryPRsFromCandidates } from "./createComfyRegistryPRsFromCandidates";
|
|
4
|
-
import { notifySlack } from "
|
|
4
|
+
import { notifySlack } from "@/lib/slack/notifySlack";
|
|
5
5
|
import { updateCMRepos } from "./updateCMRepos";
|
|
6
6
|
import { updateCNReposCRPullsComments } from "./updateCNReposCRPullsComments";
|
|
7
7
|
import { updateCNReposInfo } from "./updateCNReposInfo";
|
|
@@ -34,24 +34,24 @@ export async function updateCNRepos() {
|
|
|
34
34
|
return [await notifySlack(msg, { unique: true, silent: true })];
|
|
35
35
|
}),
|
|
36
36
|
// stage 1: get repos
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
tLog("Update Nodes from ComfyUI Manager", updateCMNodes),
|
|
38
|
+
tLog("Update Repos from ComfyUI Manager", updateCMRepos),
|
|
39
|
+
tLog("Update Nodes from ComfyRegistry", updateCRNodes),
|
|
40
|
+
tLog("Update Repos from ComfyRegistry", updateCRRepos),
|
|
41
41
|
// stage 2: update repo info & pulls
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
tLog("Update CNRepos for Repo Infos", updateCNReposInfo),
|
|
43
|
+
tLog("Update CNRepos for Github Pulls", updateCNReposPulls),
|
|
44
|
+
tLog("Update Pulls Dashboard", updateCNRepoPullsDashboard),
|
|
45
45
|
// stage 3: update related pulls and comments
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
tLog("Update CNRepos for Related Pulls", updateCNReposRelatedPulls),
|
|
47
|
+
tLog("Update Outdated Pulls Templates", updateOutdatedPullsTemplates),
|
|
48
48
|
// stage 4: update related comments
|
|
49
|
-
|
|
49
|
+
tLog("Update CNRepos for Related Comments", updateCNReposCRPullsComments),
|
|
50
50
|
// stage 5: mark and create PRs
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
tLog("Update CNRepos PR Candidates", updateCNReposPRCandidate),
|
|
52
|
+
tLog("Create ComfyRegistry PRs", createComfyRegistryPRsFromCandidates),
|
|
53
53
|
// final
|
|
54
|
-
|
|
54
|
+
tLog("Update Comfy Totals", updateComfyTotals),
|
|
55
55
|
]);
|
|
56
56
|
|
|
57
57
|
console.log("All repo updated");
|
|
@@ -3,11 +3,11 @@ import { CNRepos, type CRPull } from "./CNRepos";
|
|
|
3
3
|
import { $fresh, $stale } from "./db";
|
|
4
4
|
// import { $filaten } from "./db";
|
|
5
5
|
// import { $pipeline } from "./db/$pipeline";
|
|
6
|
-
import { $
|
|
6
|
+
import { $flatten } from "@/packages/mongodb-pipeline-ts/$flatten";
|
|
7
7
|
import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
|
|
8
8
|
import { TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
9
9
|
import { getWorkerInstance } from "./WorkerInstances";
|
|
10
|
-
import { fetchIssueComments } from "
|
|
10
|
+
import { fetchIssueComments } from "@/lib/github/fetchIssueComments";
|
|
11
11
|
|
|
12
12
|
if (import.meta.main) {
|
|
13
13
|
await getWorkerInstance("updateCNReposCRPullsComments");
|
|
@@ -19,8 +19,10 @@ export async function updateCNReposCRPullsComments() {
|
|
|
19
19
|
return await pMap(
|
|
20
20
|
$pipeline(CNRepos)
|
|
21
21
|
.unwind("$crPulls.data")
|
|
22
|
-
.match(
|
|
23
|
-
|
|
22
|
+
.match(
|
|
23
|
+
$flatten({ crPulls: { mtime: $fresh("7d"), data: { comments: { mtime: $stale("1d") } } } }),
|
|
24
|
+
)
|
|
25
|
+
.set($flatten({ "crPulls.data": { repository: "$repository" } }))
|
|
24
26
|
.replaceRoot({ newRoot: "$crPulls.data" })
|
|
25
27
|
.aggregate(),
|
|
26
28
|
async (data) => {
|
|
@@ -29,7 +31,7 @@ export async function updateCNReposCRPullsComments() {
|
|
|
29
31
|
const comments = await fetchIssueComments(repository, pull).then(TaskOK).catch(TaskError);
|
|
30
32
|
return [
|
|
31
33
|
await CNRepos.findOneAndUpdate(
|
|
32
|
-
$
|
|
34
|
+
$flatten({ repository, crPulls: { data: { pull: { html_url } } } }),
|
|
33
35
|
{ $set: { "crPulls.data.$.comments": comments } },
|
|
34
36
|
{ upsert: true, returnDocument: "after" },
|
|
35
37
|
),
|
package/src/updateCNReposInfo.ts
CHANGED
|
@@ -4,10 +4,11 @@ import { match } from "ts-pattern";
|
|
|
4
4
|
import { $OK, TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
5
5
|
import { CNRepos } from "./CNRepos";
|
|
6
6
|
import { getWorkerInstance } from "./WorkerInstances";
|
|
7
|
-
import { $
|
|
8
|
-
import { gh } from "
|
|
9
|
-
import {
|
|
7
|
+
import { $flatten, $stale } from "./db";
|
|
8
|
+
import { gh } from "@/lib/github";
|
|
9
|
+
import { parseGithubRepoUrl } from "./parseOwnerRepo";
|
|
10
10
|
import { tLog } from "./utils/tLog";
|
|
11
|
+
import { pickRepoInfo } from "./pickRepoInfo";
|
|
11
12
|
|
|
12
13
|
if (import.meta.main) {
|
|
13
14
|
await getWorkerInstance("updateCNReposInfo");
|
|
@@ -15,44 +16,52 @@ if (import.meta.main) {
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export async function updateCNReposInfo() {
|
|
18
|
-
await CNRepos.createIndex($
|
|
19
|
-
return await sflow(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
19
|
+
await CNRepos.createIndex($flatten({ info: { mtime: 1 } }));
|
|
20
|
+
return await sflow(CNRepos.find($flatten({ info: { mtime: $stale("1d") } })))
|
|
21
|
+
.filter((repo) => {
|
|
22
|
+
// Skip repos with invalid repository values
|
|
23
|
+
if (!repo.repository || typeof repo.repository !== "string") {
|
|
24
|
+
console.log("[WARN] Skipping repo with invalid repository field:", repo);
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
})
|
|
29
|
+
.pMap(
|
|
30
|
+
async (repo) => {
|
|
31
|
+
const { repository } = repo;
|
|
32
|
+
console.log("[INFO] Fetching meta info from " + repository);
|
|
33
|
+
const _info = await gh.repos
|
|
34
|
+
.get({ ...parseGithubRepoUrl(repository) })
|
|
35
|
+
.then(({ data }) => pickRepoInfo(data))
|
|
36
|
+
.then(TaskOK)
|
|
37
|
+
.catch(TaskError);
|
|
38
|
+
// Handle renamed repos
|
|
39
|
+
const { info, url } = await match(_info)
|
|
40
|
+
.with($OK, async (info) => {
|
|
41
|
+
const url = info.data.html_url;
|
|
42
|
+
if (url === repository) return { info, url: repository };
|
|
35
43
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
// console.log(info.data.use_squash_pr_title_as_default)
|
|
45
|
+
console.log("[INFO] Migrating renamed repo: \nfrom: ", repository + "\n to: " + url);
|
|
46
|
+
// migrate data into new CNRepo
|
|
47
|
+
await CNRepos.updateOne(
|
|
48
|
+
{ repository: url },
|
|
49
|
+
{
|
|
50
|
+
$set: {
|
|
51
|
+
...dissoc("_id", { ...(await CNRepos.findOneAndDelete({ repository })) }),
|
|
52
|
+
repository: url,
|
|
53
|
+
oldUrls: { $addToSet: repository },
|
|
54
|
+
},
|
|
46
55
|
},
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
.otherwise((info) => ({ info, url: repository }));
|
|
56
|
+
{ upsert: true },
|
|
57
|
+
);
|
|
58
|
+
return { info, url };
|
|
59
|
+
})
|
|
60
|
+
.otherwise((info) => ({ info, url: repository }));
|
|
53
61
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
return await CNRepos.updateOne({ repository: url }, { $set: { info } }, { upsert: true });
|
|
63
|
+
},
|
|
64
|
+
{ concurrency: 2 },
|
|
65
|
+
)
|
|
66
|
+
.toArray();
|
|
58
67
|
}
|
|
@@ -4,7 +4,7 @@ import { peekYaml } from "peek-log";
|
|
|
4
4
|
import { match } from "ts-pattern";
|
|
5
5
|
import { $OK, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
6
6
|
import { CNRepos } from "./CNRepos";
|
|
7
|
-
import { $
|
|
7
|
+
import { $flatten, $fresh, $stale } from "./db";
|
|
8
8
|
import { updateCNReposPulls } from "./updateCNReposPulls";
|
|
9
9
|
import { updateCNReposRelatedPulls } from "./updateCNReposRelatedPulls";
|
|
10
10
|
import { tLog } from "./utils/tLog";
|
|
@@ -31,7 +31,7 @@ if (import.meta.main) {
|
|
|
31
31
|
peekYaml(
|
|
32
32
|
await $pipeline(CNRepos)
|
|
33
33
|
.match(
|
|
34
|
-
$
|
|
34
|
+
$flatten({
|
|
35
35
|
crPulls: { mtime: $stale("7d") },
|
|
36
36
|
// info: { mtime: $fresh("7d"), data: { private: false, archived: false } },
|
|
37
37
|
// createdPulls: { mtime: $stale("7d"), data: { $exists: false } },
|
|
@@ -55,7 +55,7 @@ export async function updateCNReposPRCandidate() {
|
|
|
55
55
|
return await pMap(
|
|
56
56
|
$pipeline(CNRepos)
|
|
57
57
|
.match(
|
|
58
|
-
$
|
|
58
|
+
$flatten({
|
|
59
59
|
crPulls: { mtime: $fresh("1d"), ...$OK },
|
|
60
60
|
// info: { mtime: $fresh("7d"), ...$OK, data: { private: false, archived: false } },
|
|
61
61
|
info: { mtime: $fresh("7d"), ...$OK },
|
|
@@ -3,8 +3,8 @@ import sflow from "sflow";
|
|
|
3
3
|
import { match } from "ts-pattern";
|
|
4
4
|
import { $OK, TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
5
5
|
import { CNRepos } from "./CNRepos";
|
|
6
|
-
import { $
|
|
7
|
-
import { fetchGithubPulls } from "
|
|
6
|
+
import { $flatten, $stale } from "./db";
|
|
7
|
+
import { fetchGithubPulls } from "@/lib/github/fetchGithubPulls";
|
|
8
8
|
import { tLog } from "./utils/tLog";
|
|
9
9
|
if (import.meta.main) {
|
|
10
10
|
console.log(await tLog("Update CNRepos for Github Pulls", updateCNReposPulls));
|
|
@@ -13,15 +13,19 @@ export async function updateCNReposPulls() {
|
|
|
13
13
|
await CNRepos.createIndex("pulls.mtime");
|
|
14
14
|
return await sflow(
|
|
15
15
|
$pipeline(CNRepos)
|
|
16
|
-
.match($
|
|
16
|
+
.match($flatten({ pulls: { mtime: $stale("1d") } }))
|
|
17
17
|
.project({ repository: 1 })
|
|
18
18
|
.aggregate(),
|
|
19
19
|
)
|
|
20
20
|
.pMap(
|
|
21
21
|
async ({ repository }) => {
|
|
22
|
-
const pulls = await fetchGithubPulls(repository)
|
|
22
|
+
const pulls = await fetchGithubPulls(repository as string)
|
|
23
|
+
.then(TaskOK)
|
|
24
|
+
.catch(TaskError);
|
|
23
25
|
match(pulls)
|
|
24
|
-
.with($OK, ({ data }) =>
|
|
26
|
+
.with($OK, ({ data }) =>
|
|
27
|
+
console.debug(`[DEBUG] fetched ${data.length} Pulls from ${repository}`),
|
|
28
|
+
)
|
|
25
29
|
.otherwise(() => {});
|
|
26
30
|
return await CNRepos.updateOne({ repository }, { $set: { pulls } });
|
|
27
31
|
},
|
|
@@ -2,24 +2,26 @@ import DIE from "@snomiao/die";
|
|
|
2
2
|
import { match } from "ts-pattern";
|
|
3
3
|
import { $OK } from "../packages/mongodb-pipeline-ts/Task";
|
|
4
4
|
import { CNRepos } from "./CNRepos";
|
|
5
|
-
import { $
|
|
6
|
-
import { gh } from "
|
|
5
|
+
import { $flatten, $fresh } from "./db";
|
|
6
|
+
import { gh } from "@/lib/github";
|
|
7
7
|
import { ghUser } from "./ghUser";
|
|
8
|
-
import {
|
|
8
|
+
import { parseGithubRepoUrl, stringifyOwnerRepo } from "./parseOwnerRepo";
|
|
9
9
|
|
|
10
10
|
export async function updateCNRepoPullsDashboard() {
|
|
11
|
-
if (ghUser.login !== "snomiao") return [];
|
|
11
|
+
if ((await ghUser()).login !== "snomiao") return [];
|
|
12
12
|
const dashBoardIssue = process.env.DASHBOARD_ISSUE_URL || DIE("DASHBOARD_ISSUE_URL not found");
|
|
13
13
|
const dashBoardRepo = dashBoardIssue.replace(/\/issues\/\d+$/, "");
|
|
14
|
-
const dashBoardIssueNumber = Number(
|
|
14
|
+
const dashBoardIssueNumber = Number(
|
|
15
|
+
dashBoardIssue.match(/\/issues\/(\d+)$/)?.[1] || DIE("Issue number not found"),
|
|
16
|
+
);
|
|
15
17
|
// update dashboard issue if run by @snomiao
|
|
16
|
-
const repos = await CNRepos.find($
|
|
18
|
+
const repos = await CNRepos.find($flatten({ crPulls: { mtime: $fresh("1d") } })).toArray();
|
|
17
19
|
const result = repos
|
|
18
20
|
.map((repo) => {
|
|
19
21
|
const crPulls = match(repo.crPulls)
|
|
20
22
|
.with($OK, ({ data }) => data)
|
|
21
23
|
.otherwise(() => DIE("CR Pulls not found"));
|
|
22
|
-
const repoName = stringifyOwnerRepo(
|
|
24
|
+
const repoName = stringifyOwnerRepo(parseGithubRepoUrl(repo.repository));
|
|
23
25
|
const body = crPulls
|
|
24
26
|
.filter((e) => e.pull.prState !== "closed")
|
|
25
27
|
.map((e) => {
|
|
@@ -31,7 +33,7 @@ export async function updateCNRepoPullsDashboard() {
|
|
|
31
33
|
};
|
|
32
34
|
})
|
|
33
35
|
.map(({ href, name }) => `- [${name}](${href})`)
|
|
34
|
-
.
|
|
36
|
+
.sort()
|
|
35
37
|
.join("\n");
|
|
36
38
|
return body;
|
|
37
39
|
})
|
|
@@ -41,7 +43,7 @@ export async function updateCNRepoPullsDashboard() {
|
|
|
41
43
|
|
|
42
44
|
return [
|
|
43
45
|
await gh.issues.update({
|
|
44
|
-
...
|
|
46
|
+
...parseGithubRepoUrl(dashBoardRepo),
|
|
45
47
|
issue_number: dashBoardIssueNumber,
|
|
46
48
|
body,
|
|
47
49
|
}),
|
|
@@ -3,7 +3,7 @@ import pMap from "p-map";
|
|
|
3
3
|
import { match } from "ts-pattern";
|
|
4
4
|
import { $OK, TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
5
5
|
import { CNRepos } from "./CNRepos";
|
|
6
|
-
import { $
|
|
6
|
+
import { $flatten, $stale } from "./db";
|
|
7
7
|
import { matchRelatedPulls } from "./matchRelatedPulls";
|
|
8
8
|
import { tLog } from "./utils/tLog";
|
|
9
9
|
if (import.meta.main) {
|
|
@@ -12,8 +12,8 @@ if (import.meta.main) {
|
|
|
12
12
|
export async function updateCNReposRelatedPulls() {
|
|
13
13
|
await CNRepos.createIndex({ "pulls.state": 1, "crPulls.mtime": 1 });
|
|
14
14
|
return await pMap(
|
|
15
|
-
CNRepos.find($
|
|
16
|
-
async (repo,
|
|
15
|
+
CNRepos.find($flatten({ pulls: { state: "ok" }, crPulls: { mtime: $stale("1d") } })),
|
|
16
|
+
async (repo, _i) => {
|
|
17
17
|
const { repository } = repo;
|
|
18
18
|
const pulls = match(repo.pulls)
|
|
19
19
|
.with($OK, (e) => e.data)
|
package/src/updateCRNodes.ts
CHANGED
|
@@ -4,9 +4,10 @@ import { filter, groupBy, values } from "rambda";
|
|
|
4
4
|
import YAML from "yaml";
|
|
5
5
|
import { TaskOK } from "../packages/mongodb-pipeline-ts/Task";
|
|
6
6
|
import { CNRepos } from "./CNRepos";
|
|
7
|
+
import { UNCLAIMED_ADMIN_PUBLISHER_ID } from "./constants";
|
|
7
8
|
import { CRNodes } from "./CRNodes";
|
|
8
9
|
import { fetchCRNodes } from "./fetchComfyRegistryNodes";
|
|
9
|
-
import { notifySlack } from "
|
|
10
|
+
import { notifySlack } from "@/lib/slack/notifySlack";
|
|
10
11
|
import { tLog } from "./utils/tLog";
|
|
11
12
|
|
|
12
13
|
if (import.meta.main) {
|
|
@@ -14,7 +15,11 @@ if (import.meta.main) {
|
|
|
14
15
|
console.log("CRNodes updated");
|
|
15
16
|
|
|
16
17
|
peekYaml(
|
|
17
|
-
await $pipeline(CNRepos)
|
|
18
|
+
await $pipeline(CNRepos)
|
|
19
|
+
.project({ repository: 1, on_registry: 1 })
|
|
20
|
+
.sample({ size: 8 })
|
|
21
|
+
.aggregate()
|
|
22
|
+
.toArray(),
|
|
18
23
|
);
|
|
19
24
|
}
|
|
20
25
|
export async function updateCRNodes() {
|
|
@@ -22,17 +27,31 @@ export async function updateCRNodes() {
|
|
|
22
27
|
|
|
23
28
|
// check src duplicated
|
|
24
29
|
const group = groupBy((e) => e.repository, nodes);
|
|
25
|
-
const duplicates = filter((e) => e
|
|
30
|
+
const duplicates = filter((e) => (e?.length ?? 0) > 1, group);
|
|
26
31
|
if (values(duplicates).length) {
|
|
27
32
|
const msg =
|
|
28
|
-
"[WARN] Same repo but different ids found in comfyregistry:\n" +
|
|
33
|
+
"[WARN] Same repo but different ids found in comfyregistry:\n" +
|
|
34
|
+
"```\n" +
|
|
35
|
+
YAML.stringify(duplicates) +
|
|
36
|
+
"\n```";
|
|
29
37
|
await notifySlack(msg, { unique: true });
|
|
30
38
|
}
|
|
31
39
|
|
|
40
|
+
const CRNodesRepo = nodes.map(({ repository }) => repository).filter(Boolean);
|
|
41
|
+
const CRNodesRepoExcludeUnclaimed = nodes
|
|
42
|
+
.filter((e) => e.publisher.id !== UNCLAIMED_ADMIN_PUBLISHER_ID)
|
|
43
|
+
.map(({ repository }) => repository)
|
|
44
|
+
.filter(Boolean);
|
|
32
45
|
return [
|
|
33
46
|
await $pipeline(CNRepos)
|
|
34
47
|
.project({ repository: 1 })
|
|
35
|
-
.
|
|
48
|
+
.match({
|
|
49
|
+
repository: { $exists: true, $ne: null as unknown as string, $type: "string" },
|
|
50
|
+
})
|
|
51
|
+
.set({
|
|
52
|
+
on_registry_all: TaskOK({ $in: ["$repository", CRNodesRepo] }),
|
|
53
|
+
on_registry: TaskOK({ $in: ["$repository", CRNodesRepoExcludeUnclaimed] }),
|
|
54
|
+
})
|
|
36
55
|
.merge({ into: "CNRepos", on: "repository", whenMatched: "merge", whenNotMatched: "insert" })
|
|
37
56
|
.aggregate()
|
|
38
57
|
.next(),
|