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/readTemplateTitle.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { readFile } from "fs/promises";
|
|
2
|
-
import { parseTitleBodyOfMarkdown } from "./parseTitleBodyOfMarkdown";
|
|
3
|
-
|
|
4
|
-
export async function readTemplateTitle(filename: string) {
|
|
5
|
-
return await readTemplate(filename).then((e) => e.title);
|
|
6
|
-
}
|
|
7
|
-
export async function readTemplate(filename: string) {
|
|
8
|
-
return readFile("./templates/" + filename, "utf8").then(
|
|
9
|
-
parseTitleBodyOfMarkdown,
|
|
10
|
-
);
|
|
11
|
-
}
|
|
1
|
+
import { readFile } from "fs/promises";
|
|
2
|
+
import { parseTitleBodyOfMarkdown } from "./parseTitleBodyOfMarkdown";
|
|
3
|
+
|
|
4
|
+
export async function readTemplateTitle(filename: string) {
|
|
5
|
+
return await readTemplate(filename).then((e) => e.title);
|
|
6
|
+
}
|
|
7
|
+
export async function readTemplate(filename: string) {
|
|
8
|
+
return readFile("./templates/" + filename, "utf8").then(
|
|
9
|
+
parseTitleBodyOfMarkdown,
|
|
10
|
+
);
|
|
11
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { $elemMatch } from "@/packages/mongodb-pipeline-ts/$elemMatch";
|
|
3
|
+
import { TaskDataOrNull, type Task } from "@/packages/mongodb-pipeline-ts/Task";
|
|
4
|
+
import DIE from "@snomiao/die";
|
|
5
|
+
import pMap from "p-map";
|
|
6
|
+
import { snoflow } from "snoflow";
|
|
7
|
+
import type { z } from "zod";
|
|
8
|
+
import type { PullStatusShown } from "./analyzePullsStatus";
|
|
9
|
+
import { CNRepos } from "./CNRepos";
|
|
10
|
+
import { $filaten } from "./db";
|
|
11
|
+
import { enqueueEmailTask } from "./EmailTasks";
|
|
12
|
+
import { zSendEmailAction } from "./followRuleSchema";
|
|
13
|
+
import { yaml } from "./utils/yaml";
|
|
14
|
+
|
|
15
|
+
export async function sendEmailAction({
|
|
16
|
+
matched,
|
|
17
|
+
action,
|
|
18
|
+
runAction,
|
|
19
|
+
rule,
|
|
20
|
+
}: {
|
|
21
|
+
matched: Task<PullStatusShown[]>;
|
|
22
|
+
action: z.infer<typeof zSendEmailAction>;
|
|
23
|
+
runAction: boolean;
|
|
24
|
+
rule: { name: string };
|
|
25
|
+
}) {
|
|
26
|
+
return await pMap(
|
|
27
|
+
TaskDataOrNull(matched) ?? DIE("NO-PAYLOAD-AVAILABLE"),
|
|
28
|
+
async (payload) => {
|
|
29
|
+
if (action.provider !== "google") DIE("Currently we only support gmail sender");
|
|
30
|
+
const loadedAction = await snoflow([action])
|
|
31
|
+
.map((e) => yaml.stringify(e))
|
|
32
|
+
.map((e) =>
|
|
33
|
+
// replace {{var}} s
|
|
34
|
+
e.replace(
|
|
35
|
+
/{{\$([_A-Za-z0-9]+)}}/g,
|
|
36
|
+
(_, key: string) =>
|
|
37
|
+
(payload as any)[key] || DIE("Missing key: " + key + " in payload: " + JSON.stringify(payload)),
|
|
38
|
+
),
|
|
39
|
+
)
|
|
40
|
+
.map((e) => yaml.parse(e))
|
|
41
|
+
.map((y) => zSendEmailAction.parse(y))
|
|
42
|
+
.map((a) => ({ ...a, action: "send-email" }))
|
|
43
|
+
.toLast();
|
|
44
|
+
|
|
45
|
+
if (runAction) {
|
|
46
|
+
const task = await enqueueEmailTask(loadedAction);
|
|
47
|
+
console.log(rule.name + " email enqueued :" + yaml.stringify(loadedAction));
|
|
48
|
+
await CNRepos.updateOne($filaten({ crPulls: { data: $elemMatch({ pull: { html_url: payload.url } }) } }), {
|
|
49
|
+
$set: { "crPulls.data.$.emailTask_id": task._id },
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return loadedAction;
|
|
53
|
+
},
|
|
54
|
+
{ concurrency: 1 },
|
|
55
|
+
);
|
|
56
|
+
}
|
package/src/sendGmail.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import DIE from "@snomiao/die";
|
|
2
|
+
// import type { Credentials } from "google-auth-library";
|
|
3
|
+
import type { Credentials } from "google-auth-library";
|
|
4
|
+
import { GoogleApis } from "googleapis";
|
|
5
|
+
import type { OAuth2Client } from "googleapis-common";
|
|
6
|
+
import { createMimeMessage } from "mail-mime-builder";
|
|
7
|
+
import markdownIt from "markdown-it";
|
|
8
|
+
import {
|
|
9
|
+
GCloudOAuth2Credentials,
|
|
10
|
+
getGCloudOAuth2Client,
|
|
11
|
+
handleGCloudOAuth2Callback,
|
|
12
|
+
} from "./gcloud/GCloudOAuth2Credentials";
|
|
13
|
+
if (import.meta.main) {
|
|
14
|
+
// send test email
|
|
15
|
+
const name = "snomiao";
|
|
16
|
+
const from = "snomiao@gmail.com";
|
|
17
|
+
const to = ".snomiao@gmail.com";
|
|
18
|
+
const subject = "Hello! snomiao";
|
|
19
|
+
const markdown = `
|
|
20
|
+
# hello from sno
|
|
21
|
+
|
|
22
|
+
You've <b>just</b> received an *email* from snomiao.
|
|
23
|
+
|
|
24
|
+
Thank you for receiving this email!!!!
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
const html = markdownIt().render(markdown);
|
|
28
|
+
console.log(html);
|
|
29
|
+
|
|
30
|
+
const sent = await sendGmail({
|
|
31
|
+
name,
|
|
32
|
+
from,
|
|
33
|
+
to,
|
|
34
|
+
subject,
|
|
35
|
+
html,
|
|
36
|
+
auth: await getGCloudOAuth2Client({
|
|
37
|
+
email: from,
|
|
38
|
+
scope: ["https://www.googleapis.com/auth/gmail.compose"],
|
|
39
|
+
authorize: async (url) => {
|
|
40
|
+
// check saved credential in db
|
|
41
|
+
const getCred = async () =>
|
|
42
|
+
(
|
|
43
|
+
await GCloudOAuth2Credentials.findOne({
|
|
44
|
+
scopes: "https://www.googleapis.com/auth/gmail.compose",
|
|
45
|
+
email: from,
|
|
46
|
+
credentials: { $exists: true },
|
|
47
|
+
})
|
|
48
|
+
)?.credentials;
|
|
49
|
+
const cred = await getCred();
|
|
50
|
+
if (cred) return cred;
|
|
51
|
+
|
|
52
|
+
// otherwise wait for user approve
|
|
53
|
+
(await (await import("open")).default(url)).unref();
|
|
54
|
+
// setup one time server to receive ?code={{....}}
|
|
55
|
+
return await new Promise<Credentials>((r) => {
|
|
56
|
+
const server = Bun.serve({
|
|
57
|
+
fetch: async (req) => {
|
|
58
|
+
// wait for code, and then save to db
|
|
59
|
+
const res = await handleGCloudOAuth2Callback(req);
|
|
60
|
+
const cred = await getCred();
|
|
61
|
+
if (cred) r(cred);
|
|
62
|
+
server.stop();
|
|
63
|
+
return res;
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
70
|
+
console.log(sent);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function sendGmail({
|
|
74
|
+
name,
|
|
75
|
+
from,
|
|
76
|
+
to,
|
|
77
|
+
subject,
|
|
78
|
+
text,
|
|
79
|
+
html,
|
|
80
|
+
auth,
|
|
81
|
+
}: {
|
|
82
|
+
name: string;
|
|
83
|
+
from: string;
|
|
84
|
+
to: string;
|
|
85
|
+
subject: string;
|
|
86
|
+
text?: string;
|
|
87
|
+
html?: string;
|
|
88
|
+
auth: OAuth2Client;
|
|
89
|
+
}) {
|
|
90
|
+
const msg = createMimeMessage();
|
|
91
|
+
msg.setSender({ name: name, addr: from });
|
|
92
|
+
msg.setRecipient(to);
|
|
93
|
+
msg.setSubject(subject);
|
|
94
|
+
text && msg.addMessage({ contentType: "text/plain", data: text });
|
|
95
|
+
html && msg.addMessage({ contentType: "text/html", data: html });
|
|
96
|
+
text || html || DIE("Missing msg body");
|
|
97
|
+
|
|
98
|
+
const result = await new GoogleApis().gmail("v1").users.messages.send({
|
|
99
|
+
auth,
|
|
100
|
+
userId: from,
|
|
101
|
+
requestBody: { raw: btoa(msg.asRaw()) },
|
|
102
|
+
});
|
|
103
|
+
const sent = result.data;
|
|
104
|
+
return sent;
|
|
105
|
+
}
|
package/src/showFollowRuleSet.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
"use server";
|
|
2
|
-
import DIE from "@snomiao/die";
|
|
3
|
-
import { FollowRuleSets } from "./FollowRules";
|
|
4
|
-
import { updateFollowRuleSet } from "./updateFollowRuleSet";
|
|
5
|
-
|
|
6
|
-
export async function showFollowRuleSet({ name = "default" } = {}) {
|
|
7
|
-
const ruleset = (await FollowRuleSets.findOne({ name })) ?? DIE("default ruleset not found");
|
|
8
|
-
return await updateFollowRuleSet({
|
|
9
|
-
name: ruleset.name,
|
|
10
|
-
yaml: ruleset.yamlWhenEnabled ?? DIE("Rule not enabled"),
|
|
11
|
-
});
|
|
12
|
-
}
|
|
1
|
+
"use server";
|
|
2
|
+
import DIE from "@snomiao/die";
|
|
3
|
+
import { FollowRuleSets } from "./FollowRules";
|
|
4
|
+
import { updateFollowRuleSet } from "./updateFollowRuleSet";
|
|
5
|
+
|
|
6
|
+
export async function showFollowRuleSet({ name = "default" } = {}) {
|
|
7
|
+
const ruleset = (await FollowRuleSets.findOne({ name })) ?? DIE("default ruleset not found");
|
|
8
|
+
return await updateFollowRuleSet({
|
|
9
|
+
name: ruleset.name,
|
|
10
|
+
yaml: ruleset.yamlWhenEnabled ?? DIE("Rule not enabled"),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { type GithubIssueComment } from "./GithubIssueComments";
|
|
2
|
-
|
|
3
|
-
export function summaryLastPullComment(comments: GithubIssueComment[]) {
|
|
4
|
-
// assume ascending order
|
|
5
|
-
const last = comments.toReversed()[0];
|
|
6
|
-
const lastText = (last ?? "") && "@" + last.user!.name + ":" + last.body!.replace(/\s+/gim, " ");
|
|
7
|
-
return lastText;
|
|
8
|
-
}
|
|
1
|
+
import { type GithubIssueComment } from "./GithubIssueComments";
|
|
2
|
+
|
|
3
|
+
export function summaryLastPullComment(comments: GithubIssueComment[]) {
|
|
4
|
+
// assume ascending order
|
|
5
|
+
const last = comments.toReversed()[0];
|
|
6
|
+
const lastText = (last ?? "") && "@" + last.user!.name + ":" + last.body!.replace(/\s+/gim, " ");
|
|
7
|
+
return lastText;
|
|
8
|
+
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { writeFile, readFile } from "fs/promises";
|
|
2
|
-
import DIE from "@snomiao/die";
|
|
3
|
-
import toml from "toml";
|
|
4
|
-
import { fetchRepoDescriptionMap } from "./fetchRepoDescriptionMap";
|
|
5
|
-
|
|
6
|
-
export async function tomlFillDescription(referenceUrl: string, pyprojectToml: string) {
|
|
7
|
-
const repoDescriptionMap = await fetchRepoDescriptionMap();
|
|
8
|
-
const matchedDescription = repoDescriptionMap[referenceUrl]?.toString() ||
|
|
9
|
-
DIE("Warn: missing description for " + referenceUrl);
|
|
10
|
-
const replaced = (await readFile(pyprojectToml, "utf8")).replace(
|
|
11
|
-
`description = ""`,
|
|
12
|
-
`description = ${JSON.stringify(matchedDescription)}`
|
|
13
|
-
);
|
|
14
|
-
// check validity
|
|
15
|
-
toml.parse(replaced);
|
|
16
|
-
await writeFile(pyprojectToml, replaced);
|
|
17
|
-
}
|
|
1
|
+
import { writeFile, readFile } from "fs/promises";
|
|
2
|
+
import DIE from "@snomiao/die";
|
|
3
|
+
import toml from "toml";
|
|
4
|
+
import { fetchRepoDescriptionMap } from "./fetchRepoDescriptionMap";
|
|
5
|
+
|
|
6
|
+
export async function tomlFillDescription(referenceUrl: string, pyprojectToml: string) {
|
|
7
|
+
const repoDescriptionMap = await fetchRepoDescriptionMap();
|
|
8
|
+
const matchedDescription = repoDescriptionMap[referenceUrl]?.toString() ||
|
|
9
|
+
DIE("Warn: missing description for " + referenceUrl);
|
|
10
|
+
const replaced = (await readFile(pyprojectToml, "utf8")).replace(
|
|
11
|
+
`description = ""`,
|
|
12
|
+
`description = ${JSON.stringify(matchedDescription)}`
|
|
13
|
+
);
|
|
14
|
+
// check validity
|
|
15
|
+
toml.parse(replaced);
|
|
16
|
+
await writeFile(pyprojectToml, replaced);
|
|
17
|
+
}
|
package/src/updateAuthors.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { updateAuthorsForGithub } from "./updateAuthorsForGithub";
|
|
2
|
-
import { updateAuthorsFromCNRepo } from "./updateAuthorsFromCNRepo";
|
|
3
|
-
|
|
4
|
-
export async function updateAuthors() {
|
|
5
|
-
await updateAuthorsFromCNRepo();
|
|
6
|
-
await updateAuthorsForGithub();
|
|
7
|
-
}
|
|
1
|
+
import { updateAuthorsForGithub } from "./updateAuthorsForGithub";
|
|
2
|
+
import { updateAuthorsFromCNRepo } from "./updateAuthorsFromCNRepo";
|
|
3
|
+
|
|
4
|
+
export async function updateAuthors() {
|
|
5
|
+
await updateAuthorsFromCNRepo();
|
|
6
|
+
await updateAuthorsForGithub();
|
|
7
|
+
}
|
|
@@ -1,50 +1,54 @@
|
|
|
1
|
-
import { $OK, TaskDataOrNull, TaskError, TaskOK } from "@/packages/mongodb-pipeline-ts/Task";
|
|
2
|
-
import DIE from "@snomiao/die";
|
|
3
|
-
import console from "console";
|
|
4
|
-
import { peekYaml } from "peek-log";
|
|
5
|
-
import { snoflow } from "snoflow";
|
|
6
|
-
import { Authors, GithubUsers } from "./Authors";
|
|
7
|
-
import { $stale } from "./db";
|
|
8
|
-
import { gh } from "./gh";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
await
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
...(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
1
|
+
import { $OK, TaskDataOrNull, TaskError, TaskOK } from "@/packages/mongodb-pipeline-ts/Task";
|
|
2
|
+
import DIE from "@snomiao/die";
|
|
3
|
+
import console from "console";
|
|
4
|
+
import { peekYaml } from "peek-log";
|
|
5
|
+
import { snoflow } from "snoflow";
|
|
6
|
+
import { Authors, GithubUsers } from "./Authors";
|
|
7
|
+
import { $stale } from "./db";
|
|
8
|
+
import { gh } from "./gh";
|
|
9
|
+
|
|
10
|
+
if (import.meta.main) {
|
|
11
|
+
await updateAuthorsForGithub();
|
|
12
|
+
}
|
|
13
|
+
export async function updateAuthorsForGithub() {
|
|
14
|
+
await snoflow(Authors.find({ githubMtime: $stale("7d") }))
|
|
15
|
+
.map((e) => e.githubId)
|
|
16
|
+
.filter()
|
|
17
|
+
.pMap(2, async (username) => {
|
|
18
|
+
const cached = await GithubUsers.findOne({ username, mtime: $stale("1d"), ...$OK });
|
|
19
|
+
if (cached) return cached;
|
|
20
|
+
console.log("Fetching github user " + username);
|
|
21
|
+
const result = await gh.users
|
|
22
|
+
.getByUsername({ username })
|
|
23
|
+
.then((e) => e.data)
|
|
24
|
+
.then(TaskOK)
|
|
25
|
+
.catch(TaskError);
|
|
26
|
+
return (
|
|
27
|
+
(await GithubUsers.findOneAndUpdate(
|
|
28
|
+
{ username },
|
|
29
|
+
{ $set: result },
|
|
30
|
+
{ returnDocument: "after", upsert: true },
|
|
31
|
+
)) ?? DIE(`fail to udpate gh users`)
|
|
32
|
+
);
|
|
33
|
+
})
|
|
34
|
+
.map((e) => TaskDataOrNull(e))
|
|
35
|
+
.filter()
|
|
36
|
+
.map(({ email, avatar_url, blog, updated_at, location, company, hireable, bio, login }) =>
|
|
37
|
+
Authors.findOneAndUpdate(
|
|
38
|
+
{ githubId: login },
|
|
39
|
+
{
|
|
40
|
+
$set: { githubMtime: new Date(), ...(email && { email }), ...(null != hireable && { hireable }) },
|
|
41
|
+
$addToSet: {
|
|
42
|
+
...(bio && { bios: bio }),
|
|
43
|
+
avatars: avatar_url,
|
|
44
|
+
...(location && { locations: location }),
|
|
45
|
+
...(blog && { blogs: blog }),
|
|
46
|
+
...(company && { companies: company }),
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{ upsert: true, returnDocument: "after" },
|
|
50
|
+
),
|
|
51
|
+
)
|
|
52
|
+
.peek(peekYaml)
|
|
53
|
+
.done();
|
|
54
|
+
}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
|
|
2
|
-
import { snoflow } from "snoflow";
|
|
3
|
-
import { Authors } from "./Authors";
|
|
4
|
-
import { CNRepos } from "./CNRepos";
|
|
5
|
-
import { $filaten } from "./db";
|
|
6
|
-
|
|
7
|
-
/** Update authors for gh users, collecting emails/username/hireable */
|
|
8
|
-
export async function updateAuthorsFromCNRepo() {
|
|
9
|
-
return await snoflow(
|
|
10
|
-
$pipeline(CNRepos)
|
|
11
|
-
.match($filaten({ info: { data: { owner: { login: { $exists: true } } } } }))
|
|
12
|
-
.group({
|
|
13
|
-
_id: "$info.data.owner.login",
|
|
14
|
-
// author: "$info.data.owner.login",
|
|
15
|
-
cm: { $sum: { $cond: [{ $eq: [{ $type: "$cm" }, "missing"] }, 0, 1] } },
|
|
16
|
-
cr: { $sum: { $cond: [{ $eq: [{ $type: "$cr" }, "missing"] }, 0, 1] } },
|
|
17
|
-
|
|
18
|
-
// TODO: get totals open/closed/merged
|
|
19
|
-
// pulls:{
|
|
20
|
-
// OPEN: {"$crPulls.data.pull.prState", "open"}
|
|
21
|
-
// }
|
|
22
|
-
All: { $sum: 1 },
|
|
23
|
-
})
|
|
24
|
-
.set({
|
|
25
|
-
.project({ _id: 0 })
|
|
26
|
-
.aggregate()
|
|
27
|
-
)
|
|
28
|
-
.
|
|
29
|
-
.done();
|
|
30
|
-
}
|
|
1
|
+
import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
|
|
2
|
+
import { snoflow } from "snoflow";
|
|
3
|
+
import { Authors } from "./Authors";
|
|
4
|
+
import { CNRepos } from "./CNRepos";
|
|
5
|
+
import { $filaten } from "./db";
|
|
6
|
+
|
|
7
|
+
/** Update authors for gh users, collecting emails/username/hireable */
|
|
8
|
+
export async function updateAuthorsFromCNRepo() {
|
|
9
|
+
return await snoflow(
|
|
10
|
+
$pipeline(CNRepos)
|
|
11
|
+
.match($filaten({ info: { data: { owner: { login: { $exists: true } } } } }))
|
|
12
|
+
.group({
|
|
13
|
+
_id: "$info.data.owner.login",
|
|
14
|
+
// author: "$info.data.owner.login",
|
|
15
|
+
cm: { $sum: { $cond: [{ $eq: [{ $type: "$cm" }, "missing"] }, 0, 1] } },
|
|
16
|
+
cr: { $sum: { $cond: [{ $eq: [{ $type: "$cr" }, "missing"] }, 0, 1] } },
|
|
17
|
+
|
|
18
|
+
// TODO: get totals open/closed/merged
|
|
19
|
+
// pulls:{
|
|
20
|
+
// OPEN: {"$crPulls.data.pull.prState", "open"}
|
|
21
|
+
// }
|
|
22
|
+
All: { $sum: 1 },
|
|
23
|
+
})
|
|
24
|
+
.set({ githubId: "$_id" })
|
|
25
|
+
.project({ _id: 0 })
|
|
26
|
+
.aggregate(),
|
|
27
|
+
)
|
|
28
|
+
.map(({ githubId, ...$set }) => Authors.updateOne({ githubId }, { $set }, { upsert: true }))
|
|
29
|
+
.done();
|
|
30
|
+
}
|
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
import { unary } from "lodash-es";
|
|
2
|
-
import pMap from "p-map";
|
|
3
|
-
import { dissoc, filter, groupBy, map, prop, toPairs } from "rambda";
|
|
4
|
-
import YAML from "yaml";
|
|
5
|
-
import { CMNodes, type CMNode } from "./CMNodes";
|
|
6
|
-
import { notifySlack } from "./slack/notifySlack";
|
|
7
|
-
|
|
8
|
-
export async function updateCMNodesDuplicationWarnings(nodes: CMNode[]) {
|
|
9
|
-
console.log("CMNodes checking duplicates");
|
|
10
|
-
// prettier-ignore
|
|
11
|
-
const dups = {
|
|
12
|
-
ID: filter((e: typeof nodes) => e.length > 1, groupBy((e) => e.id, nodes)),
|
|
13
|
-
TITLE: filter((e: typeof nodes) => e.length > 1, groupBy((e) => e.title, nodes)),
|
|
14
|
-
REFERENCE: filter((e: typeof nodes) => e.length > 1, groupBy((e) => e.reference, nodes)),
|
|
15
|
-
};
|
|
16
|
-
const dupsSummary = JSON.stringify(map((x) => map((x) => x.length, x), dups));
|
|
17
|
-
await notifySlack(
|
|
18
|
-
`[WARN] CMNodes duplicates: ${dupsSummary}\nSolve them in https://github.com/ltdrdata/ComfyUI-Manager/blob/main/custom-node-list.json`,
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
await pMap(
|
|
22
|
-
toPairs(dups),
|
|
23
|
-
async ([topic, nodes]) =>
|
|
24
|
-
await pMap(
|
|
25
|
-
toPairs(nodes),
|
|
26
|
-
async ([key, nodesRaw]) => {
|
|
27
|
-
const nodes = nodesRaw.map(unary(dissoc("hash")));
|
|
28
|
-
const hashes = nodesRaw.map(prop("hash"));
|
|
29
|
-
// check sent
|
|
30
|
-
const someDuplicateSent = await CMNodes.findOne({
|
|
31
|
-
hash: { $in: hashes },
|
|
32
|
-
[`duplicated.${topic}`]: { $exists: true },
|
|
33
|
-
});
|
|
34
|
-
if (someDuplicateSent) return;
|
|
35
|
-
// send slack notification
|
|
36
|
-
const slackNotification = await notifySlack(
|
|
37
|
-
`[ACTION NEEDED WARNING]: please resolve duplicated node in ${topic}: ${key}\n` +
|
|
38
|
-
"```\n" +
|
|
39
|
-
YAML.stringify(nodes) +
|
|
40
|
-
"```" +
|
|
41
|
-
"\n\nSolve them in https://github.com/ltdrdata/ComfyUI-Manager/blob/main/custom-node-list.json",
|
|
42
|
-
{ unique: true },
|
|
43
|
-
);
|
|
44
|
-
// mark duplicates
|
|
45
|
-
await CMNodes.updateMany(
|
|
46
|
-
{ hash: { $in: hashes } },
|
|
47
|
-
{
|
|
48
|
-
$set: { [`duplicated.${topic}`]: { hashes, slackNotification } },
|
|
49
|
-
},
|
|
50
|
-
);
|
|
51
|
-
},
|
|
52
|
-
{ concurrency: 2 },
|
|
53
|
-
),
|
|
54
|
-
{ concurrency: 2 },
|
|
55
|
-
);
|
|
56
|
-
}
|
|
1
|
+
import { unary } from "lodash-es";
|
|
2
|
+
import pMap from "p-map";
|
|
3
|
+
import { dissoc, filter, groupBy, map, prop, toPairs } from "rambda";
|
|
4
|
+
import YAML from "yaml";
|
|
5
|
+
import { CMNodes, type CMNode } from "./CMNodes";
|
|
6
|
+
import { notifySlack } from "./slack/notifySlack";
|
|
7
|
+
|
|
8
|
+
export async function updateCMNodesDuplicationWarnings(nodes: CMNode[]) {
|
|
9
|
+
console.log("CMNodes checking duplicates");
|
|
10
|
+
// prettier-ignore
|
|
11
|
+
const dups = {
|
|
12
|
+
ID: filter((e: typeof nodes) => e.length > 1, groupBy((e) => e.id, nodes)),
|
|
13
|
+
TITLE: filter((e: typeof nodes) => e.length > 1, groupBy((e) => e.title, nodes)),
|
|
14
|
+
REFERENCE: filter((e: typeof nodes) => e.length > 1, groupBy((e) => e.reference, nodes)),
|
|
15
|
+
};
|
|
16
|
+
const dupsSummary = JSON.stringify(map((x) => map((x) => x.length, x), dups));
|
|
17
|
+
await notifySlack(
|
|
18
|
+
`[WARN] CMNodes duplicates: ${dupsSummary}\nSolve them in https://github.com/ltdrdata/ComfyUI-Manager/blob/main/custom-node-list.json`,
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
await pMap(
|
|
22
|
+
toPairs(dups),
|
|
23
|
+
async ([topic, nodes]) =>
|
|
24
|
+
await pMap(
|
|
25
|
+
toPairs(nodes),
|
|
26
|
+
async ([key, nodesRaw]) => {
|
|
27
|
+
const nodes = nodesRaw.map(unary(dissoc("hash")));
|
|
28
|
+
const hashes = nodesRaw.map(prop("hash"));
|
|
29
|
+
// check sent
|
|
30
|
+
const someDuplicateSent = await CMNodes.findOne({
|
|
31
|
+
hash: { $in: hashes },
|
|
32
|
+
[`duplicated.${topic}`]: { $exists: true },
|
|
33
|
+
});
|
|
34
|
+
if (someDuplicateSent) return;
|
|
35
|
+
// send slack notification
|
|
36
|
+
const slackNotification = await notifySlack(
|
|
37
|
+
`[ACTION NEEDED WARNING]: please resolve duplicated node in ${topic}: ${key}\n` +
|
|
38
|
+
"```\n" +
|
|
39
|
+
YAML.stringify(nodes) +
|
|
40
|
+
"```" +
|
|
41
|
+
"\n\nSolve them in https://github.com/ltdrdata/ComfyUI-Manager/blob/main/custom-node-list.json",
|
|
42
|
+
{ unique: true },
|
|
43
|
+
);
|
|
44
|
+
// mark duplicates
|
|
45
|
+
await CMNodes.updateMany(
|
|
46
|
+
{ hash: { $in: hashes } },
|
|
47
|
+
{
|
|
48
|
+
$set: { [`duplicated.${topic}`]: { hashes, slackNotification } },
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
{ concurrency: 2 },
|
|
53
|
+
),
|
|
54
|
+
{ concurrency: 2 },
|
|
55
|
+
);
|
|
56
|
+
}
|
package/src/updateCMRepos.ts
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import pMap from "p-map";
|
|
2
|
-
import { CMNodes } from "./CMNodes";
|
|
3
|
-
import { CNRepos } from "./CNRepos";
|
|
4
|
-
import { tLog } from "./utils/tLog";
|
|
5
|
-
if (import.meta.main) {
|
|
6
|
-
await tLog("Update Repos from ComfyUI Manager", updateCMRepos);
|
|
7
|
-
console.log(await CMNodes.estimatedDocumentCount());
|
|
8
|
-
}
|
|
9
|
-
export async function updateCMRepos() {
|
|
10
|
-
await CMNodes.createIndex({ repo_id: 1 });
|
|
11
|
-
return await pMap(CMNodes.find({ repo_id: { $exists: false } }), async (cm, i) => {
|
|
12
|
-
const { reference: repository, _id } = cm;
|
|
13
|
-
return await CNRepos.updateOne(
|
|
14
|
-
{ repository },
|
|
15
|
-
{
|
|
16
|
-
$set: {
|
|
17
|
-
cm: (await CMNodes.findOneAndUpdate(
|
|
18
|
-
{ _id },
|
|
19
|
-
{ $set: { repo_id: cm._id } },
|
|
20
|
-
{ upsert: true, returnDocument: "after" },
|
|
21
|
-
))!,
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
{ upsert: true },
|
|
25
|
-
);
|
|
26
|
-
});
|
|
27
|
-
}
|
|
1
|
+
import pMap from "p-map";
|
|
2
|
+
import { CMNodes } from "./CMNodes";
|
|
3
|
+
import { CNRepos } from "./CNRepos";
|
|
4
|
+
import { tLog } from "./utils/tLog";
|
|
5
|
+
if (import.meta.main) {
|
|
6
|
+
await tLog("Update Repos from ComfyUI Manager", updateCMRepos);
|
|
7
|
+
console.log(await CMNodes.estimatedDocumentCount());
|
|
8
|
+
}
|
|
9
|
+
export async function updateCMRepos() {
|
|
10
|
+
await CMNodes.createIndex({ repo_id: 1 });
|
|
11
|
+
return await pMap(CMNodes.find({ repo_id: { $exists: false } }), async (cm, i) => {
|
|
12
|
+
const { reference: repository, _id } = cm;
|
|
13
|
+
return await CNRepos.updateOne(
|
|
14
|
+
{ repository },
|
|
15
|
+
{
|
|
16
|
+
$set: {
|
|
17
|
+
cm: (await CMNodes.findOneAndUpdate(
|
|
18
|
+
{ _id },
|
|
19
|
+
{ $set: { repo_id: cm._id } },
|
|
20
|
+
{ upsert: true, returnDocument: "after" },
|
|
21
|
+
))!,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
{ upsert: true },
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
}
|