comfy-pr 0.2.7 → 0.2.17

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/CHANGELOG.md CHANGED
@@ -2,6 +2,51 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.2.17](https://github.com/drip-art/Comfy-Registry-PR/compare/v0.2.8...v0.2.17) (2024-06-24)
6
+
7
+ ### Features
8
+
9
+ - **analyzePullsStatusPipeline:** also check comment in repo ([4ca14f6](https://github.com/drip-art/Comfy-Registry-PR/commit/4ca14f634fe2e0158ddc655f95d95992ccbcceb0))
10
+ - **analyzePullsStatusPipeline:** also check comment in repo ([62f055e](https://github.com/drip-art/Comfy-Registry-PR/commit/62f055e1c6ebc64b97061d4cdd4a7bba17e079ac))
11
+ - **main:** calculate authors ([9b0d719](https://github.com/drip-art/Comfy-Registry-PR/commit/9b0d719fa7be529e4b73d3c7a4189c7bc9da714f))
12
+ - **main:** calculate authors ([3299c3f](https://github.com/drip-art/Comfy-Registry-PR/commit/3299c3f0997eca73ad4121db6dd183d9b92b1a47))
13
+ - **sno-sep-apidoc:** init ([4c5a5e3](https://github.com/drip-art/Comfy-Registry-PR/commit/4c5a5e3f512696c5df4032cbd2ae5fddda99751c))
14
+ - **sno-sep-apidoc:** init ([994c57d](https://github.com/drip-art/Comfy-Registry-PR/commit/994c57deac01c7c3b11987fa736b73aeb45b9bb4))
15
+ - **update-follow-rule-set:** prematch comments ([34c98d5](https://github.com/drip-art/Comfy-Registry-PR/commit/34c98d55d0dd5973c457b23c44a21b576927a1c5))
16
+ - **update-follow-rule-set:** prematch comments ([7911528](https://github.com/drip-art/Comfy-Registry-PR/commit/7911528d3ce9cf8da3618ca1d44f26c6d5b532a0))
17
+
18
+ ### Bug Fixes
19
+
20
+ - **(dashboard):** add index ([81e4cf3](https://github.com/drip-art/Comfy-Registry-PR/commit/81e4cf372329a84069c102c2b89dce78fbc71a98))
21
+ - **edit-toml-PR-message:** add v2 outdated template edit logic ([b7719b8](https://github.com/drip-art/Comfy-Registry-PR/commit/b7719b8c9916ccc4ba09be3ef9a57e4e696eed88))
22
+ - **edit-toml-PR-message:** add v2 outdated template edit logic ([594976d](https://github.com/drip-art/Comfy-Registry-PR/commit/594976d309476ff289aae6027a6d4d0ec9f8c360))
23
+ - **follow-comment:** fix existed comment logic ([bc43c22](https://github.com/drip-art/Comfy-Registry-PR/commit/bc43c223e2db97c8e55c2e286d5a64d9698cf853))
24
+ - **ghuser:** rename ([d0cce7e](https://github.com/drip-art/Comfy-Registry-PR/commit/d0cce7e06511457ea0db3fe1c673977b6b1179a4))
25
+ - **main:** made a fork demo for haohao ([ed58416](https://github.com/drip-art/Comfy-Registry-PR/commit/ed58416c11a7c63cc4356ffce2aee93b9fa3bb2b))
26
+ - **main:** move ts-toolbelt to devDep ([19a46cf](https://github.com/drip-art/Comfy-Registry-PR/commit/19a46cf6d21b4009a7f02213350aa4086427dcb9))
27
+ - **main:** move ts-toolbelt to devDep ([904dd13](https://github.com/drip-art/Comfy-Registry-PR/commit/904dd13da40c04570c17460ee8ccc96801c323c4))
28
+ - **main:** repo ago ([e2b007b](https://github.com/drip-art/Comfy-Registry-PR/commit/e2b007bec237ba904d8f88a6a522ba4429f6f10b))
29
+ - **main:** repo ago ([5633d0e](https://github.com/drip-art/Comfy-Registry-PR/commit/5633d0eeb77fa42859b66d7a351d66355ed17da1))
30
+ - **mongodb-pipeline-ts:** pipeline with syntax ([246144d](https://github.com/drip-art/Comfy-Registry-PR/commit/246144d3a95c3c163a251a20c904d77891985ea6))
31
+ - **mongodb-pipeline-ts:** pipeline with syntax ([20bf3fc](https://github.com/drip-art/Comfy-Registry-PR/commit/20bf3fc07e435857d80240465865d702f9b3dada))
32
+ - **pipeline:** fix type-helper ([c75e6ac](https://github.com/drip-art/Comfy-Registry-PR/commit/c75e6ac12fdb1b95b218c89f2ede2c5607b7ed23))
33
+ - **pkg:** types ([51beb33](https://github.com/drip-art/Comfy-Registry-PR/commit/51beb337ceee555ceb4827304edeed395129c179))
34
+ - **pull-status:** updated-at ([7196c3a](https://github.com/drip-art/Comfy-Registry-PR/commit/7196c3a9b492102e820f9bba2f8216906079155e))
35
+ - **src:** last-comment-at ([5c6b37e](https://github.com/drip-art/Comfy-Registry-PR/commit/5c6b37e7a33c72188da9c0d923cd97c43ad7e0e3))
36
+ - **src:** last-comment-at ([8050d4a](https://github.com/drip-art/Comfy-Registry-PR/commit/8050d4adc1dbc53b8a43e53edf9b9fca094b067f))
37
+ - **src:** outdate publishcr ([05b64bf](https://github.com/drip-art/Comfy-Registry-PR/commit/05b64bfabb7a3931416f5c2ed939763f346f9ad4))
38
+ - **src:** outdate publishcr ([8034c71](https://github.com/drip-art/Comfy-Registry-PR/commit/8034c718898f11b1af98644986cc8fda9671d0b2))
39
+ - **src:** peek result of runfollowruleset ([96886ec](https://github.com/drip-art/Comfy-Registry-PR/commit/96886ec832cab7c1b8333283d055417f7b808d54))
40
+ - **src:** peek result of runfollowruleset ([e81f9d5](https://github.com/drip-art/Comfy-Registry-PR/commit/e81f9d52a9aad7826898dc2e731db999abb04d3a))
41
+ - **src:** promise seq order ([cbd2534](https://github.com/drip-art/Comfy-Registry-PR/commit/cbd25342716efe0be9853fd599a40e93ac418228))
42
+ - **src:** promise seq order ([304fbfd](https://github.com/drip-art/Comfy-Registry-PR/commit/304fbfddfcf90e357cce6562b5125f987ea997ee))
43
+ - **src:** remove peeks ([4d4f2a9](https://github.com/drip-art/Comfy-Registry-PR/commit/4d4f2a9d981030bb21ea8c18cf84a617cec0eda7))
44
+ - **src:** remove peeks ([b2a7586](https://github.com/drip-art/Comfy-Registry-PR/commit/b2a7586c5bd6279c46fa58f74572246512475dd5))
45
+ - **src:** run action skip not matched user ([30a0219](https://github.com/drip-art/Comfy-Registry-PR/commit/30a0219a59f4edbb964352cd66688d6040ff6e16))
46
+ - **templates:** outdate publish.yaml ([0ded9e8](https://github.com/drip-art/Comfy-Registry-PR/commit/0ded9e87dd14e268fab13071a82de7efb8382790))
47
+
48
+ ### [0.2.8](https://github.com/drip-art/Comfy-Registry-PR/compare/v0.2.7...v0.2.8) (2024-06-20)
49
+
5
50
  ### [0.2.7](https://github.com/drip-art/Comfy-Registry-PR/compare/v0.2.5...v0.2.7) (2024-06-20)
6
51
 
7
52
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "comfy-pr",
3
- "version": "0.2.7",
3
+ "version": "0.2.17",
4
4
  "description": "Make PRs that publishes ComfyUI Custom Nodes to [ComfyUI Registry]( https://www.comfyregistry.org/ ).",
5
5
  "keywords": [],
6
6
  "license": "ISC",
@@ -8,10 +8,11 @@
8
8
  "type": "module",
9
9
  "exports": {
10
10
  "import": "./src/index.ts",
11
- "types": "./index.ts"
11
+ "types": "./src/index.ts"
12
12
  },
13
13
  "main": "index.ts",
14
14
  "module": "index.ts",
15
+ "types": "./src/index.ts",
15
16
  "bin": {
16
17
  "comfy-pr": "./src/cli.ts"
17
18
  },
@@ -31,72 +32,55 @@
31
32
  "dependencies": {
32
33
  "@auth/mongodb-adapter": "^3.2.0",
33
34
  "@ctrl/mac-address": "^3.0.3",
34
- "@keyv/mongo": "^2.2.8",
35
- "@keyv/sqlite": "^3.6.7",
36
35
  "@monaco-editor/react": "^4.6.0",
37
- "@slack/web-api": "^7.0.4",
38
- "@snomiao/die": "^1.0.6",
36
+ "@slack/web-api": "^7.2.0",
37
+ "@snomiao/die": "^1.0.9",
39
38
  "@trpc/server": "^10.45.2",
40
39
  "@types/d3": "^7.4.3",
41
- "@types/jest": "^29.5.12",
42
- "@types/js-yaml": "^4.0.9",
43
- "@types/minimist": "^1.2.5",
44
- "@types/swagger-ui-react": "^4.18.3",
45
- "@types/uuid": "^9.0.8",
46
- "chatgpt-template": "^1.1.3",
47
40
  "d3": "^7.9.0",
48
- "daisyui": "^4.12.2",
41
+ "daisyui": "^4.12.7",
49
42
  "dotenv": "^16.4.5",
50
43
  "enhanced-ms": "^3.0.0",
51
- "execa": "^9.1.0",
52
- "flat": "^6.0.1",
44
+ "globby": "^14.0.1",
53
45
  "js-yaml": "^4.1.0",
54
46
  "json-stable-stringify": "^1.1.1",
55
- "json-to-zod": "^1.1.2",
56
47
  "keyv": "^4.5.4",
57
48
  "keyv-cached-with": "^0.0.13",
58
- "keyv-dir-store": "^0.0.3",
59
- "lefthook": "^1.6.15",
60
49
  "lodash-es": "^4.17.21",
61
50
  "md5": "^2.3.0",
62
51
  "minimist": "^1.2.8",
52
+ "monaco-editor": "^0.50.0",
63
53
  "mongodb": "^6.7.0",
64
- "mongodb-altas-api-sdk": "^0.1.1",
65
54
  "next-auth": "^5.0.0-beta.19",
66
- "nodemailer": "^6.9.13",
55
+ "nodemailer": "^6.9.14",
67
56
  "octokit": "^4.0.2",
68
57
  "p-map": "^7.0.2",
69
- "peek-log": "^0.0.4",
58
+ "peek-log": "^0.0.8",
59
+ "pretty-ms": "^9.0.0",
70
60
  "promise-all-properties": "^4.0.0",
71
- "rambda": "^9.2.0",
72
- "react-hook-form": "^7.51.5",
61
+ "rambda": "^9.2.1",
62
+ "react-api-doc": "^0.0.9",
63
+ "react-hook-form": "^7.52.0",
73
64
  "react-markdown": "^9.0.1",
74
- "react-use": "^17.5.0",
75
- "snorun": "^1.4.0",
76
- "swagger-ui-react": "^5.17.14",
77
- "swr": "^2.2.5",
78
- "timing-with": "^0.0.4",
79
65
  "toml": "^3.0.0",
80
66
  "trpc-openapi": "^1.2.0",
81
- "trpc-swagger": "^1.2.6",
82
67
  "ts-pattern": "^5.2.0",
83
68
  "use-swr-component": "^0.0.5",
84
- "uuid": "^10.0.0",
85
69
  "yaml": "^2.4.5",
86
- "yargs": "^17.7.2",
87
70
  "zod": "^3.23.8",
88
- "zx": "^8.1.2"
71
+ "zx": "^8.1.3"
89
72
  },
90
73
  "devDependencies": {
91
- "@tanstack/react-table": "^8.17.3",
92
74
  "@types/bun": "^1.1.5",
75
+ "@types/js-yaml": "^4.0.9",
93
76
  "@types/json-stable-stringify": "^1.0.36",
94
77
  "@types/lodash-es": "^4.17.12",
95
78
  "@types/md5": "^2.3.5",
79
+ "@types/minimist": "^1.2.5",
96
80
  "@types/node": "^20",
81
+ "@types/nodemailer": "^6.4.15",
97
82
  "@types/react": "^18",
98
83
  "@types/react-dom": "^18",
99
- "axios": "^1.6.8",
100
84
  "eslint": "^8",
101
85
  "eslint-config-next": "14.2.4",
102
86
  "next": "^14.2.4",
@@ -106,7 +90,8 @@
106
90
  "react": "^18.3.1",
107
91
  "react-dom": "^18.3.1",
108
92
  "tailwindcss": "^3.4.1",
109
- "typescript": "^5.4.5"
93
+ "ts-toolbelt": "^9.6.0",
94
+ "typescript": "^5.5.2"
110
95
  },
111
96
  "peerDependencies": {
112
97
  "typescript": "^5.4.5"
package/src/CNRepos.ts CHANGED
@@ -4,6 +4,7 @@ bun index.ts
4
4
  */
5
5
  import type { ObjectId, WithId } from "mongodb";
6
6
  import "react-hook-form";
7
+ import { type Task } from "../packages/mongodb-pipeline-ts/Task";
7
8
  import { type CMNode } from "./CMNodes";
8
9
  import { type CRNode } from "./CRNodes";
9
10
  import { db } from "./db";
@@ -11,7 +12,6 @@ import { gh } from "./gh";
11
12
  import { type RelatedPull } from "./matchRelatedPulls";
12
13
  import type { GithubPullParsed } from "./parsePullsState";
13
14
  import { type SlackMsg } from "./slack/SlackMsgs";
14
- import { type Task } from "./utils/Task";
15
15
 
16
16
  type Email = {
17
17
  from?: string;
package/src/CRNodes.ts CHANGED
@@ -14,6 +14,7 @@ export type CRNode = Awaited<ReturnType<typeof fetchCRNodes>>[number] & {
14
14
  export const CRNodes = db.collection<CRNode>("CRNodes");
15
15
  await CRNodes.createIndex({ id: 1 }, { unique: true });
16
16
  await CRNodes.createIndex({ repository: 1 }, { unique: false }); // WARN: duplicate is allowed
17
+
17
18
  if (import.meta.main) {
18
19
  const r = await pMap(
19
20
  $pipeline(CNRepos)
@@ -1,8 +1,8 @@
1
1
  import { z } from "zod";
2
+ import { type Task } from "../packages/mongodb-pipeline-ts/Task";
2
3
  import type { PullsStatus } from "./analyzePullsStatus";
3
4
  import { db } from "./db";
4
5
  import type { zFollowUpRules } from "./followRuleSchema";
5
- import { type Task } from "./utils/Task";
6
6
 
7
7
  // migrate data
8
8
  // await db.renameCollection("FollowRules", "FollowRuleSets").catch(() => null);
package/src/Totals.ts CHANGED
@@ -1,7 +1,7 @@
1
+ import { type Task } from "../packages/mongodb-pipeline-ts/Task";
1
2
  import { analyzeTotals } from "./analyzeTotals";
2
3
  import { db } from "./db";
3
4
  import { type AwaitedReturnType } from "./types/AwaitedReturnType";
4
- import { type Task } from "./utils/Task";
5
5
  export type Totals = AwaitedReturnType<typeof analyzeTotals>;
6
6
  export const Totals = db.collection<{
7
7
  today?: string;
@@ -2,10 +2,10 @@ import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
2
2
  import { peekYaml } from "peek-log";
3
3
  import prettyMs from "pretty-ms";
4
4
  import type { z } from "zod";
5
+ import type { Task } from "../packages/mongodb-pipeline-ts/Task";
5
6
  import { CNRepos, type CRPull } from "./CNRepos";
6
7
  import type { GithubIssueComment } from "./GithubIssueComments";
7
8
  import { db } from "./db";
8
- import type { Task } from "./utils/Task";
9
9
  import type { zPullStatus } from "./zod/zPullsStatus";
10
10
  // import { $pipeline } from "./db/$pipeline";
11
11
  // in case of dump production in local environment:
@@ -22,29 +22,20 @@ if (import.meta.main) {
22
22
  }
23
23
 
24
24
  export type PullStatus = z.infer<typeof zPullStatus>;
25
- export type PullsStatus = PullStatus[] &
26
- {
27
- lastwords: string;
28
- repository: string;
29
- author_email: string;
30
- ownername: string;
31
- on_registry: boolean;
32
- state: "OPEN" | "MERGED" | "CLOSED";
33
- url: string;
34
- head: string;
35
- comments: number;
36
- updated: string;
37
- }[];
38
- export async function analyzePullsStatus({ skip = 0, limit = 0 } = {}) {
25
+ export type PullsStatus = PullStatus[];
26
+ export async function analyzePullsStatus({ skip = 0, limit = 0, pipeline = analyzePullsStatusPipeline() } = {}) {
39
27
  "use server";
40
- return await analyzePullsStatusPipeline()
28
+ return await pipeline
41
29
  .skip(skip)
42
30
  .limit(limit || 2 ** 31 - 1)
43
31
  .aggregate()
44
- .map(({ updated_at, created_at, on_registry_at, ...pull }) => {
45
- const updated = prettyMs(+new Date() - +new Date(updated_at), { compact: true }) + " ago";
32
+ .map(({ updated_at, created_at, actived_at, on_registry_at, ...pull }) => {
33
+ const pull_updated = prettyMs(+new Date() - +new Date(updated_at), { compact: true }) + " ago";
34
+ const repo_updated = prettyMs(+new Date() - +new Date(actived_at), { compact: true }) + " ago";
46
35
  return {
47
- updated, //: updated === created ? "never" : updated,
36
+ updated: pull_updated, // @deprecated
37
+ pull_updated,
38
+ repo_updated,
48
39
  ...pull,
49
40
  lastwords: pull.lastwords?.replace(/\s+/g, " ").replace(/\*\*\*.*/g, "..."),
50
41
  };
@@ -54,8 +45,10 @@ export async function analyzePullsStatus({ skip = 0, limit = 0 } = {}) {
54
45
  export function analyzePullsStatusPipeline() {
55
46
  return (
56
47
  $pipeline(CNRepos)
48
+ .set({ "crPulls.data.pull.latest_comment_at": { $max: { $max: "$crPulls.data.comments.data.updated_at" } } })
57
49
  .unwind("$crPulls.data")
58
50
  .match({ "crPulls.data.comments.data": { $exists: true } })
51
+ .set({ "crPulls.data.pull.actived_at": { $toDate: "$info.data.updated_at" } })
59
52
  .set({ "crPulls.data.pull.repo": "$repository" })
60
53
  .set({ "crPulls.data.pull.on_registry": "$on_registry" })
61
54
  .set({ "crPulls.data.pull.type": "$crPulls.data.type" })
@@ -83,7 +76,12 @@ export function analyzePullsStatusPipeline() {
83
76
  head: { $concat: ["$user.login", ":", "$type"] },
84
77
  comments: { $size: "$comments" },
85
78
  lastwords: { $arrayElemAt: ["$comments", -1] },
79
+ latest_comment_at: { $toDate: "$latest_comment_at" },
80
+ actived_at: 1,
86
81
  })
82
+ // .project({ latest_comment_at: {$toDate: '$latest_comment_at'} })
83
+ .set({ updated_at: { $max: ["$latest_comment_at", "$updated_at"] } })
84
+ .project({ latest_comment_at: 0 })
87
85
  .set({ lastwords: { $concat: ["$lastwords.user.login", ": ", "$lastwords.body"] } })
88
86
  .set({ lastwords: { $ifNull: ["$lastwords", ""] } })
89
87
  // .set({ state: { $nin: ["CLOSED"] } })
@@ -98,6 +96,7 @@ export function analyzePullsStatusPipeline() {
98
96
  .as<{
99
97
  updated_at: Date;
100
98
  created_at: Date;
99
+ actived_at: Date;
101
100
  repository: string;
102
101
  author_email: string;
103
102
  ownername: string;
@@ -20,7 +20,7 @@ if (import.meta.main) {
20
20
  export async function analyzeTotals() {
21
21
  "use server";
22
22
  const totals = await promiseAllProperties({
23
- Now: new Date().toISOString(),
23
+ // Now: new Date().toISOString(),
24
24
  "Total Nodes": promiseAllProperties({
25
25
  "on ComfyUI Manager": CMNodes.estimatedDocumentCount(),
26
26
  "on Registry": CRNodes.estimatedDocumentCount(),
@@ -43,10 +43,16 @@ export async function analyzeTotals() {
43
43
  .match($filaten({ info: { data: { owner: { login: { $exists: true } } } } }))
44
44
  .group({
45
45
  _id: "$info.data.owner.login",
46
- // author: "$info.data.owner.email",
47
- "on Comfy Manager List": { $sum: { $cond: [{ $eq: [{ $type: "$cm" }, "missing"] }, 0, 1] } },
48
- "on Registry": { $sum: { $cond: [{ $eq: [{ $type: "$cr" }, "missing"] }, 0, 1] } },
49
- Archived: { $sum: { $cond: ["$info.data.archived", 1, 0] } },
46
+ // author: "$info.data.owner.login",
47
+ cm: { $sum: { $cond: [{ $eq: [{ $type: "$cm" }, "missing"] }, 0, 1] } },
48
+ cr: { $sum: { $cond: [{ $eq: [{ $type: "$cr" }, "missing"] }, 0, 1] } },
49
+ All: { $sum: 1 },
50
+ })
51
+ .set({ author: "$_id" })
52
+ .group({
53
+ _id: null,
54
+ "on Comfy Manager List": { $sum: { $cond: [{ $eq: ["$cm", 0] }, 0, 1] } },
55
+ "on Registry": { $sum: { $cond: [{ $eq: ["$cr", 0] }, 0, 1] } },
50
56
  All: { $sum: 1 },
51
57
  })
52
58
  .project({ _id: 0 })
package/src/cli.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  #!bun
2
2
  import DIE from "@snomiao/die";
3
3
  import { readFile } from "fs/promises";
4
- import { argv } from "zx";
4
+ import { argv, $ as zx } from "zx";
5
5
  import { checkComfyActivated } from "./checkComfyActivated";
6
6
  import { createComfyRegistryPullRequests } from "./createComfyRegistryPullRequests";
7
+ zx.verbose = true;
8
+
7
9
  if (argv.help) {
8
10
  console.log(
9
11
  `
@@ -31,9 +33,7 @@ if (argv.help) {
31
33
  [];
32
34
  const repos = (listRepos.length && listRepos) ||
33
35
  (argvRepos.length && argvRepos) ||
34
- (envRepos.length && envRepos) || [
35
- DIE("Missing PR target, please set env.REPO"),
36
- ];
36
+ (envRepos.length && envRepos) || [DIE("Missing PR target, please set env.REPO")];
37
37
  for await (const upstreamUrl of repos) {
38
38
  await createComfyRegistryPullRequests(upstreamUrl);
39
39
  }
@@ -1,12 +1,12 @@
1
1
  import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
2
2
  import pMap from "p-map";
3
3
  import { match } from "ts-pattern";
4
+ import { $OK, TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
4
5
  import { CNRepos } from "./CNRepos";
5
6
  import { createComfyRegistryPullRequests } from "./createComfyRegistryPullRequests";
6
7
  import { $filaten, $stale } from "./db";
7
8
  import { parseUrlRepoOwner, stringifyOwnerRepo } from "./parseOwnerRepo";
8
9
  import { notifySlackLinks } from "./slack/notifySlackLinks";
9
- import { $OK, TaskError, TaskOK } from "./utils/Task";
10
10
  import { tLog } from "./utils/tLog";
11
11
  if (import.meta.main) {
12
12
  await tLog("createComfyRegistryPRsFromCandidates", createComfyRegistryPRsFromCandidates);
package/src/index.ts CHANGED
@@ -1,22 +1,21 @@
1
1
  #!/usr/bin/env bun
2
2
  import "dotenv/config";
3
- import { $ as zx } from "zx";
4
3
  import { checkComfyActivated } from "./checkComfyActivated";
5
4
  import { initializeFollowRules } from "./initializeFollowRules";
6
5
  import { updateCNRepos } from "./updateCNRepos";
7
6
  import { runFollowRuleSet } from "./updateFollowRuleSet";
8
7
  import { updateSlackMessages } from "./updateSlackMessages";
8
+ import { tLog } from "./utils/tLog";
9
9
 
10
10
  if (import.meta.main) {
11
- zx.verbose = true;
12
11
  await Promise.all([
13
12
  // try send msgs that didn't send in last run
14
13
  updateSlackMessages(),
15
14
  checkComfyActivated(), // needed if make pr
16
- initializeFollowRules(),
17
- runFollowRuleSet(),
18
15
  updateCNRepos(),
19
16
  ]);
17
+ await initializeFollowRules();
18
+ await tLog("runFollowRuleSet", runFollowRuleSet);
20
19
  console.log("All done");
21
20
  process.exit(0);
22
21
  }
@@ -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
- 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),
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
41
  // stage 2: update repo info & pulls
42
- tLog("Update CNRepos for Repo Infos", updateCNReposInfo),
43
- tLog("Update CNRepos for Github Pulls", updateCNReposPulls),
44
- tLog("Update Pulls Dashboard", updateCNRepoPullsDashboard),
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
45
  // stage 3: update related pulls and comments
46
- tLog("Update CNRepos for Related Pulls", updateCNReposRelatedPulls),
47
- tLog("Update Outdated Pulls Templates", updateOutdatedPullsTemplates),
46
+ await tLog("Update CNRepos for Related Pulls", updateCNReposRelatedPulls),
47
+ await tLog("Update Outdated Pulls Templates", updateOutdatedPullsTemplates),
48
48
  // stage 4: update related comments
49
- tLog("Update CNRepos for Related Comments", updateCNReposCRPullsComments),
49
+ await tLog("Update CNRepos for Related Comments", updateCNReposCRPullsComments),
50
50
  // stage 5: mark and create PRs
51
- tLog("Update CNRepos PR Candidates", updateCNReposPRCandidate),
52
- tLog("Create ComfyRegistry PRs", createComfyRegistryPRsFromCandidates),
51
+ await tLog("Update CNRepos PR Candidates", updateCNReposPRCandidate),
52
+ await tLog("Create ComfyRegistry PRs", createComfyRegistryPRsFromCandidates),
53
53
  // final
54
- tLog("Update Comfy Totals", updateComfyTotals),
54
+ await tLog("Update Comfy Totals", updateComfyTotals),
55
55
  ]);
56
56
 
57
57
  console.log("All repo updated");
@@ -1,14 +1,13 @@
1
1
  import pMap from "p-map";
2
- import { peekYaml } from "peek-log";
3
2
  import { CNRepos, type CRPull } from "./CNRepos";
4
3
  import { $fresh, $stale } from "./db";
5
4
  // import { $filaten } from "./db";
6
5
  // import { $pipeline } from "./db/$pipeline";
7
6
  import { $filaten } from "@/packages/mongodb-pipeline-ts/$filaten";
8
7
  import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
8
+ import { TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
9
9
  import { getWorkerInstance } from "./WorkerInstances";
10
10
  import { fetchIssueComments } from "./gh/fetchIssueComments";
11
- import { TaskError, TaskOK } from "./utils/Task";
12
11
 
13
12
  if (import.meta.main) {
14
13
  await getWorkerInstance("updateCNReposCRPullsComments");
@@ -28,13 +27,13 @@ export async function updateCNReposCRPullsComments() {
28
27
  const { repository, pull } = data as unknown as { repository: string } & CRPull;
29
28
  const html_url = pull.html_url;
30
29
  const comments = await fetchIssueComments(repository, pull).then(TaskOK).catch(TaskError);
31
- return peekYaml([
30
+ return [
32
31
  await CNRepos.findOneAndUpdate(
33
32
  $filaten({ repository, crPulls: { data: { pull: { html_url } } } }),
34
33
  { $set: { "crPulls.data.$.comments": comments } },
35
34
  { upsert: true, returnDocument: "after" },
36
35
  ),
37
- ]);
36
+ ];
38
37
  },
39
38
  { concurrency: 2 },
40
39
  );
@@ -1,12 +1,12 @@
1
1
  import pMap from "p-map";
2
2
  import { dissoc } from "rambda";
3
3
  import { match } from "ts-pattern";
4
+ import { $OK, TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
4
5
  import { CNRepos } from "./CNRepos";
5
6
  import { getWorkerInstance } from "./WorkerInstances";
6
7
  import { $filaten, $stale } from "./db";
7
8
  import { gh } from "./gh";
8
9
  import { parseUrlRepoOwner } from "./parseOwnerRepo";
9
- import { $OK, TaskError, TaskOK } from "./utils/Task";
10
10
  import { tLog } from "./utils/tLog";
11
11
 
12
12
  if (import.meta.main) {
@@ -2,11 +2,11 @@ import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
2
2
  import pMap from "p-map";
3
3
  import { peekYaml } from "peek-log";
4
4
  import { match } from "ts-pattern";
5
+ import { $OK, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
5
6
  import { CNRepos } from "./CNRepos";
6
7
  import { $filaten, $fresh, $stale } from "./db";
7
8
  import { updateCNReposPulls } from "./updateCNReposPulls";
8
9
  import { updateCNReposRelatedPulls } from "./updateCNReposRelatedPulls";
9
- import { $OK, TaskOK } from "./utils/Task";
10
10
  import { tLog } from "./utils/tLog";
11
11
  if (import.meta.main) {
12
12
  console.log(await updateCNReposPRCandidate());
@@ -1,10 +1,10 @@
1
1
  import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
2
2
  import pMap from "p-map";
3
3
  import { match } from "ts-pattern";
4
+ import { $OK, TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
4
5
  import { CNRepos } from "./CNRepos";
5
6
  import { $filaten, $stale } from "./db";
6
7
  import { fetchGithubPulls } from "./gh/fetchGithubPulls";
7
- import { $OK, TaskError, TaskOK } from "./utils/Task";
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));
@@ -1,11 +1,11 @@
1
1
  import DIE from "@snomiao/die";
2
2
  import { match } from "ts-pattern";
3
+ import { $OK } from "../packages/mongodb-pipeline-ts/Task";
3
4
  import { CNRepos } from "./CNRepos";
4
5
  import { $filaten, $fresh } from "./db";
5
6
  import { gh } from "./gh";
6
7
  import { ghUser } from "./ghUser";
7
8
  import { parseUrlRepoOwner, stringifyOwnerRepo } from "./parseOwnerRepo";
8
- import { $OK } from "./utils/Task";
9
9
 
10
10
  export async function updateCNRepoPullsDashboard() {
11
11
  if (ghUser.login !== "snomiao") return [];
@@ -1,10 +1,10 @@
1
1
  import DIE from "@snomiao/die";
2
2
  import pMap from "p-map";
3
3
  import { match } from "ts-pattern";
4
+ import { $OK, TaskError, TaskOK } from "../packages/mongodb-pipeline-ts/Task";
4
5
  import { CNRepos } from "./CNRepos";
5
6
  import { $filaten, $stale } from "./db";
6
7
  import { matchRelatedPulls } from "./matchRelatedPulls";
7
- import { $OK, TaskError, TaskOK } from "./utils/Task";
8
8
  import { tLog } from "./utils/tLog";
9
9
  if (import.meta.main) {
10
10
  await tLog("updateCNReposRelatedPulls", updateCNReposRelatedPulls);
@@ -2,11 +2,11 @@ import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
2
2
  import { peekYaml } from "peek-log";
3
3
  import { filter, groupBy, values } from "rambda";
4
4
  import YAML from "yaml";
5
+ import { TaskOK } from "../packages/mongodb-pipeline-ts/Task";
5
6
  import { CNRepos } from "./CNRepos";
6
7
  import { CRNodes } from "./CRNodes";
7
8
  import { fetchCRNodes } from "./fetchComfyRegistryNodes";
8
9
  import { notifySlack } from "./slack/notifySlack";
9
- import { TaskOK } from "./utils/Task";
10
10
  import { tLog } from "./utils/tLog";
11
11
 
12
12
  if (import.meta.main) {
@@ -1,11 +1,10 @@
1
1
  import { match } from "ts-pattern";
2
2
  import YAML from "yaml";
3
+ import { $OK, TaskError, TaskOK, tsmatch } from "../packages/mongodb-pipeline-ts/Task";
3
4
  import { Totals } from "./Totals";
4
5
  import { analyzeTotals } from "./analyzeTotals";
5
6
  import { $filaten, $fresh } from "./db";
6
7
  import { notifySlack } from "./slack/notifySlack";
7
- import { $OK, TaskError, TaskOK } from "./utils/Task";
8
- import { tsmatch } from "./utils/tsmatch";
9
8
 
10
9
  if (import.meta.main) {
11
10
  await updateComfyTotals();
@@ -23,13 +22,15 @@ export async function updateComfyTotals({ notify = true, fresh = "30m" } = {}) {
23
22
  const totals = await analyzeTotals().then(TaskOK).catch(TaskError);
24
23
 
25
24
  // notify
26
- notify &&
27
- (await match(totals)
25
+ if (notify) {
26
+ // ignore today
27
+ await match(totals)
28
28
  .with($OK, async (totals) => {
29
29
  const msg = `Totals: \n${"```"}\n${YAML.stringify(totals)}\n${"```"}`;
30
30
  await notifySlack(msg, { unique: true });
31
31
  })
32
- .otherwise(() => null));
32
+ .otherwise(() => null);
33
+ }
33
34
 
34
35
  const insertResult = await Totals.insertOne({ totals });
35
36
  return [
@@ -1,34 +1,45 @@
1
1
  "use server";
2
- import { TaskDataOrNull } from "@/app/(dashboard)/rules/TaskDataOrNull";
3
2
  import { $elemMatch } from "@/packages/mongodb-pipeline-ts/$elemMatch";
4
3
  import { $pipeline } from "@/packages/mongodb-pipeline-ts/$pipeline";
4
+ import { TaskDataOrNull } from "@/packages/mongodb-pipeline-ts/Task";
5
5
  import DIE from "@snomiao/die";
6
6
  import pMap from "p-map";
7
+ import { peekYaml } from "peek-log";
8
+ import { TaskError, TaskOK, type Task } from "../packages/mongodb-pipeline-ts/Task";
7
9
  import { CNRepos, type CRPull } from "./CNRepos";
8
10
  import { FollowRuleSets } from "./FollowRules";
9
11
  import type { GithubIssueComment } from "./GithubIssueComments";
10
- import { analyzePullsStatusPipeline, type PullStatus } from "./analyzePullsStatus";
12
+ import { analyzePullsStatus, analyzePullsStatusPipeline } from "./analyzePullsStatus";
11
13
  import { createIssueComment } from "./createIssueComment";
12
14
  import { $filaten } from "./db";
13
15
  import { zAddCommentAction, zFollowUpRules } from "./followRuleSchema";
16
+ import { fetchIssueComments } from "./gh/fetchIssueComments";
17
+ import { ghUser } from "./ghUser";
18
+ import { initializeFollowRules } from "./initializeFollowRules";
19
+ import { stringifyGithubRepoUrl } from "./parseOwnerRepo";
20
+ import { parsePullUrl } from "./parsePullUrl";
14
21
  import { notifySlackLinks } from "./slack/notifySlackLinks";
15
- import { TaskError, TaskOK } from "./utils/Task";
16
- import { prettyMs } from "./utils/tLog";
17
22
  import { yaml } from "./utils/yaml";
18
23
 
19
24
  if (import.meta.main) {
20
25
  // updateFollowRuleSet({yaml: 'default'})
26
+ await FollowRuleSets.drop();
27
+ const defaultRuleSet = await initializeFollowRules();
28
+
29
+ await updateFollowRuleSet({ name: "default", enable: true, yaml: defaultRuleSet.yaml });
21
30
  await runFollowRuleSet();
22
31
  }
23
32
 
24
33
  export async function runFollowRuleSet({ name = "default" } = {}) {
25
34
  const ruleset = (await FollowRuleSets.findOne({ name })) ?? DIE("default ruleset not found");
26
- return await updateFollowRuleSet({
27
- name: ruleset.name,
28
- enable: ruleset.enabled ?? DIE("Ruleset is not enabled"),
29
- yaml: ruleset.yamlWhenEnabled ?? DIE("Enabled yaml is not found"),
30
- runAction: true,
31
- });
35
+ return peekYaml(
36
+ await updateFollowRuleSet({
37
+ name: ruleset.name,
38
+ enable: ruleset.enabled ?? DIE("Ruleset is not enabled"),
39
+ yaml: ruleset.yamlWhenEnabled ?? DIE("Enabled yaml is not found"),
40
+ runAction: true,
41
+ }),
42
+ );
32
43
  }
33
44
  export type updateFollowRuleSet = typeof updateFollowRuleSet;
34
45
  export async function updateFollowRuleSet({
@@ -59,20 +70,34 @@ export async function updateFollowRuleSet({
59
70
  const parseResult = await pMap(
60
71
  rules,
61
72
  async (rule) => {
62
- const matched = await analyzePullsStatusPipeline()
63
- .match(rule.$match)
64
- .aggregate()
65
- .map(({ updated_at, created_at, on_registry_at, ...pull }) => {
66
- const updated = prettyMs(+new Date() - +new Date(updated_at), { compact: true }) + " ago";
67
- return {
68
- updated, //: updated === created ? "never" : updated,
69
- ...pull,
70
- lastwords: pull.lastwords?.replace(/\s+/g, " ").replace(/\*\*\*.*/g, "..."),
71
- } as PullStatus;
72
- })
73
- .toArray()
73
+ if (runAction) {
74
+ // pre-fetch comments before run a rule -> match -> action, to prevent comment on a outdated pull state
75
+ const preMatched = await analyzePullsStatus({ pipeline: analyzePullsStatusPipeline().match(rule.$match) })
76
+ .then(TaskOK)
77
+ .catch(TaskError);
78
+
79
+ // update comments before run action
80
+ const matchedData = TaskDataOrNull(preMatched) ?? DIE("NO-PAYLOAD-AVAILABLE");
81
+ await pMap(matchedData, async (payload) => {
82
+ const html_url = payload.url;
83
+ const { owner, repo, pull_number } = parsePullUrl(payload.url);
84
+ const repository = stringifyGithubRepoUrl({ owner, repo });
85
+
86
+ const comments = await fetchIssueComments(repository, { number: pull_number })
87
+ .then(TaskOK)
88
+ .catch(TaskError);
89
+ (
90
+ await CNRepos.updateOne($filaten({ repository, crPulls: { data: { pull: { html_url } } } }), {
91
+ $set: { "crPulls.data.$.comments": comments },
92
+ })
93
+ ).matchedCount ?? DIE("pre-matched comments is not found");
94
+ });
95
+ }
96
+
97
+ const matched = await analyzePullsStatus({ pipeline: analyzePullsStatusPipeline().match(rule.$match) })
74
98
  .then(TaskOK)
75
99
  .catch(TaskError);
100
+
76
101
  const actions = await (async function () {
77
102
  return await pMap(
78
103
  Object.entries(rule.action),
@@ -95,19 +120,23 @@ export async function updateFollowRuleSet({
95
120
  ),
96
121
  };
97
122
 
98
- if (runAction) {
99
- const existedComments =
123
+ if (runAction && loadedAction.by === ghUser.login) {
124
+ const existedCommentsTask =
100
125
  (await $pipeline(CNRepos)
101
126
  .unwind("$crPulls.data")
102
127
  .match({ "crPulls.data.pull.html_url": loadedAction.url })
103
128
  .with<{ "crPulls.data": CRPull }>()
104
- .replaceRoot({ newRoot: "$crPulls.data.comments.data" })
105
- .as<GithubIssueComment[]>()
129
+ .replaceRoot({ newRoot: "$crPulls.data.comments" })
130
+ .as<Task<GithubIssueComment[]>>()
106
131
  .aggregate()
107
132
  .next()) ??
108
133
  DIE("comments is not fetched before, plz check " + loadedAction.url + " in CNRepos");
109
134
 
135
+ const existedComments =
136
+ TaskDataOrNull(existedCommentsTask) ??
137
+ DIE("NO-COMMENTS-FOUND should never happen here, bcz pipeline filtered at first");
110
138
  const existedComment = existedComments.find((e) => e.body === loadedAction.body);
139
+
111
140
  if (!existedComment) {
112
141
  const { comments, comment } = await createIssueComment(
113
142
  loadedAction.url,
@@ -127,7 +156,7 @@ export async function updateFollowRuleSet({
127
156
 
128
157
  return loadedAction;
129
158
  },
130
- { stopOnError: false, concurrency: 1 },
159
+ { concurrency: 1 },
131
160
  );
132
161
  }
133
162
  },
@@ -2,6 +2,7 @@ import { $elemMatch } from "@/packages/mongodb-pipeline-ts/$elemMatch";
2
2
  import DIE from "@snomiao/die";
3
3
  import pMap from "p-map";
4
4
  import { match } from "ts-pattern";
5
+ import { $OK, TaskError, TaskOK, tsmatch } from "../packages/mongodb-pipeline-ts/Task";
5
6
  import { CNRepos, type CRPull } from "./CNRepos";
6
7
  import { $filaten, $fresh, $stale } from "./db";
7
8
  import { gh } from "./gh";
@@ -10,9 +11,7 @@ import { ghUser } from "./ghUser";
10
11
  import { parseUrlRepoOwner } from "./parseOwnerRepo";
11
12
  import { readTemplate } from "./readTemplateTitle";
12
13
  import { notifySlackLinks } from "./slack/notifySlackLinks";
13
- import { $OK, TaskError, TaskOK } from "./utils/Task";
14
14
  import { tLog } from "./utils/tLog";
15
- import { tsmatch } from "./utils/tsmatch";
16
15
  if (import.meta.main) {
17
16
  await tLog("updateOutdatedPullsTemplates", updateOutdatedPullsTemplates);
18
17
  }
@@ -21,7 +20,9 @@ export async function updateOutdatedPullsTemplates() {
21
20
  const pyproject = await readTemplate("add-toml.md");
22
21
  const publishcr = await readTemplate("add-action.md");
23
22
  const outdated_pyproject = await readTemplate("outdated/add-toml.md");
23
+ const outdated_pyproject_v2 = await readTemplate("outdated/add-toml-v2.md");
24
24
  const outdated_publishcr = await readTemplate("outdated/add-action.md");
25
+ const outdated_publishcr_v2 = await readTemplate("outdated/add-action-v2.md");
25
26
  // const templateOutdate = new Date("2024-06-13T09:02:56.630Z");
26
27
 
27
28
  await CNRepos.createIndex({
@@ -46,12 +47,21 @@ export async function updateOutdatedPullsTemplates() {
46
47
  },
47
48
  pull: {
48
49
  user: { login: ghUser.login },
49
- title: outdated_pyproject.title,
50
- // title: {
51
- // $in: [outdated_pyproject.title, outdated_publishcr.title],
52
- // },
50
+ title: {
51
+ $in: [
52
+ outdated_pyproject.title,
53
+ outdated_pyproject_v2.title,
54
+ outdated_publishcr.title,
55
+ outdated_publishcr_v2.title,
56
+ ],
57
+ },
53
58
  body: {
54
- $in: [outdated_pyproject.body, outdated_publishcr.body],
59
+ $in: [
60
+ outdated_pyproject.body,
61
+ outdated_pyproject_v2.body,
62
+ outdated_publishcr.body,
63
+ outdated_publishcr_v2.body,
64
+ ],
55
65
  },
56
66
  },
57
67
  }),
@@ -92,7 +102,9 @@ export async function updateOutdatedPullsTemplates() {
92
102
  .with(pyproject, () => DIE("is already latest template"))
93
103
  .with(publishcr, () => DIE("is already latest template"))
94
104
  .with(outdated_pyproject, () => pyproject)
105
+ .with(outdated_pyproject_v2, () => pyproject)
95
106
  .with(outdated_publishcr, () => publishcr)
107
+ .with(outdated_publishcr_v2, () => publishcr)
96
108
  // in case author clicked some task as completed, body will be different, may cause template mismatch
97
109
  .otherwise(() => DIE("Template not found: " + pull.title));
98
110
  if (!replacement) return { ...data, edited: TaskError("Template mismatch") };