ci(icons): Add ChatGPT tags suggestions on icon PRs (#3372)

* Add gpt tags

* Add github actions flow

* Add link so people can use the chat

* Fix workflow

* Add openai dep

* Add actions core

* Try gh pr review in actions

* Try with octokit

* Remove changed files part

* Try with createReview function

* Try this

* fix broken json file

* Turn on review by gh action

* Try this

* Update icons/trash.json

* Update the runner

* Remove added tags

* Add more checks
This commit is contained in:
Eric Fennis
2025-06-27 17:11:00 +02:00
committed by GitHub
parent 110d8cce27
commit 0e54626bdb
6 changed files with 366 additions and 2 deletions

View File

@@ -0,0 +1,33 @@
name: Pull request tags suggestions
on:
pull_request:
paths:
- 'icons/*.json'
jobs:
pull-request-tags-suggestions:
name: Pull Request Tags Suggestions
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
cache: 'pnpm'
node-version-file: 'package.json'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Generate comment markup
run: node ./scripts/suggestTags.mts
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
PULL_REQUEST_NUMBER: ${{ github.event.number }}
COMMIT_SHA: ${{ github.sha }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@
.obsidian
.now
.idea
.env
node_modules
dist
build

View File

@@ -7,10 +7,20 @@
"karsa-mistmere"
],
"tags": [
"empty",
"deletion",
"cleanup",
"junk",
"clear",
"garbage",
"delete",
"remove",
"bin"
"bin",
"waste",
"recycle",
"discard",
"binoculars",
"rubbish"
],
"categories": [
"files",

View File

@@ -23,6 +23,8 @@
"generate:changelog": "node ./scripts/generateChangelog.mts",
"generate:contributors": "node ./scripts/updateContributors.mts icons/*.svg",
"generate:nextJSAliases": "node ./scripts/generateNextJSAliases.mts",
"suggest:tags": "node ./scripts/suggestTags.mts",
"suggest:tags:watch": "node --env-file .env --watch ./scripts/suggestTags.mts ",
"postinstall": "husky install",
"lint:es": "eslint .",
"lint:format": "prettier \"**/*.{js,mjs,ts,jsx,tsx,html,css,scss,json,yml,yaml}\" --check",
@@ -38,6 +40,8 @@
"renamePattern": "node ./scripts/rename/renamePattern.mts"
},
"devDependencies": {
"@actions/core": "^1.11.1",
"@actions/github": "^6.0.1",
"@html-eslint/eslint-plugin": "^0.19.1",
"@html-eslint/parser": "^0.19.1",
"@octokit/rest": "^19.0.13",
@@ -56,6 +60,7 @@
"husky": "^8.0.3",
"lint-staged": "^13.3.0",
"minimist": "^1.2.8",
"openai": "^5.8.1",
"p-memoize": "^7.1.1",
"prettier": "3.2.4",
"prettier-plugin-astro": "^0.14.1",
@@ -80,5 +85,8 @@
"overrides": {
"cross-spawn": "7.0.5"
}
},
"dependencies": {
"zod": "^3.25.67"
}
}

190
pnpm-lock.yaml generated
View File

@@ -12,7 +12,17 @@ packageExtensionsChecksum: sha256-iadh7fHFnueQwqCQdCI9Kni0+s5mxkL9biStuN8E4yQ=
importers:
.:
dependencies:
zod:
specifier: ^3.25.67
version: 3.25.67
devDependencies:
'@actions/core':
specifier: ^1.11.1
version: 1.11.1
'@actions/github':
specifier: ^6.0.1
version: 6.0.1
'@html-eslint/eslint-plugin':
specifier: ^0.19.1
version: 0.19.1
@@ -67,6 +77,9 @@ importers:
minimist:
specifier: ^1.2.8
version: 1.2.8
openai:
specifier: ^5.8.1
version: 5.8.1(ws@8.18.0)(zod@3.25.67)
p-memoize:
specifier: ^7.1.1
version: 7.1.1
@@ -870,6 +883,21 @@ importers:
packages:
'@actions/core@1.11.1':
resolution: {integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==}
'@actions/exec@1.1.1':
resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==}
'@actions/github@6.0.1':
resolution: {integrity: sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw==}
'@actions/http-client@2.2.3':
resolution: {integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==}
'@actions/io@1.1.3':
resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==}
'@adobe/css-tools@4.4.2':
resolution: {integrity: sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==}
@@ -3979,32 +4007,66 @@ packages:
resolution: {integrity: sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==}
engines: {node: '>= 14'}
'@octokit/auth-token@4.0.0':
resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==}
engines: {node: '>= 18'}
'@octokit/core@4.2.4':
resolution: {integrity: sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==}
engines: {node: '>= 14'}
'@octokit/core@5.2.1':
resolution: {integrity: sha512-dKYCMuPO1bmrpuogcjQ8z7ICCH3FP6WmxpwC03yjzGfZhj9fTJg6+bS1+UAplekbN2C+M61UNllGOOoAfGCrdQ==}
engines: {node: '>= 18'}
'@octokit/endpoint@7.0.6':
resolution: {integrity: sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==}
engines: {node: '>= 14'}
'@octokit/endpoint@9.0.6':
resolution: {integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==}
engines: {node: '>= 18'}
'@octokit/graphql@5.0.6':
resolution: {integrity: sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==}
engines: {node: '>= 14'}
'@octokit/graphql@7.1.1':
resolution: {integrity: sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==}
engines: {node: '>= 18'}
'@octokit/openapi-types@18.1.1':
resolution: {integrity: sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==}
'@octokit/openapi-types@20.0.0':
resolution: {integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==}
'@octokit/openapi-types@24.2.0':
resolution: {integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==}
'@octokit/plugin-paginate-rest@6.1.2':
resolution: {integrity: sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==}
engines: {node: '>= 14'}
peerDependencies:
'@octokit/core': '>=4'
'@octokit/plugin-paginate-rest@9.2.2':
resolution: {integrity: sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==}
engines: {node: '>= 18'}
peerDependencies:
'@octokit/core': '5'
'@octokit/plugin-request-log@1.0.4':
resolution: {integrity: sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==}
peerDependencies:
'@octokit/core': '>=3'
'@octokit/plugin-rest-endpoint-methods@10.4.1':
resolution: {integrity: sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==}
engines: {node: '>= 18'}
peerDependencies:
'@octokit/core': '5'
'@octokit/plugin-rest-endpoint-methods@7.2.3':
resolution: {integrity: sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==}
engines: {node: '>= 14'}
@@ -4015,10 +4077,18 @@ packages:
resolution: {integrity: sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==}
engines: {node: '>= 14'}
'@octokit/request-error@5.1.1':
resolution: {integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==}
engines: {node: '>= 18'}
'@octokit/request@6.2.8':
resolution: {integrity: sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==}
engines: {node: '>= 14'}
'@octokit/request@8.4.1':
resolution: {integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==}
engines: {node: '>= 18'}
'@octokit/rest@19.0.13':
resolution: {integrity: sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==}
engines: {node: '>= 14'}
@@ -4029,6 +4099,12 @@ packages:
'@octokit/types@10.0.0':
resolution: {integrity: sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==}
'@octokit/types@12.6.0':
resolution: {integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==}
'@octokit/types@13.10.0':
resolution: {integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==}
'@octokit/types@9.3.2':
resolution: {integrity: sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==}
@@ -10293,6 +10369,18 @@ packages:
resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
engines: {node: '>=12'}
openai@5.8.1:
resolution: {integrity: sha512-+qp4vQjJs43pzMSb6quTYslOhVE0c0c7j4YMoEks83BnusG23UrsWn3Hey6/8mwYadY05KipLvbp+PTO4jxO9w==}
hasBin: true
peerDependencies:
ws: ^8.18.0
zod: ^3.23.8
peerDependenciesMeta:
ws:
optional: true
zod:
optional: true
openapi-typescript@6.7.6:
resolution: {integrity: sha512-c/hfooPx+RBIOPM09GSxABOZhYPblDoyaGhqBkD/59vtpN21jEuWKDlM0KYTvqJVlSYjKs0tBcIdeXKChlSPtw==}
hasBin: true
@@ -12402,6 +12490,10 @@ packages:
resolution: {integrity: sha512-OvmFcj70PhmAsVQKfC15XoKH55cRWuaRzvr2fpTNhTNer6JBpG8n6vOhRrIgxMjcikyYt88xqYXMMVapJ4Rjvg==}
hasBin: true
tunnel@0.0.6:
resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==}
engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'}
type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
@@ -13456,6 +13548,9 @@ packages:
zod@3.24.2:
resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==}
zod@3.25.67:
resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==}
zone.js@0.11.8:
resolution: {integrity: sha512-82bctBg2hKcEJ21humWIkXRlLBBmrc3nN7DFh5LGGhcyycO2S7FN8NmdvlcKaGFDNVL4/9kFLmwmInTavdJERA==}
@@ -13464,6 +13559,32 @@ packages:
snapshots:
'@actions/core@1.11.1':
dependencies:
'@actions/exec': 1.1.1
'@actions/http-client': 2.2.3
'@actions/exec@1.1.1':
dependencies:
'@actions/io': 1.1.3
'@actions/github@6.0.1':
dependencies:
'@actions/http-client': 2.2.3
'@octokit/core': 5.2.1
'@octokit/plugin-paginate-rest': 9.2.2(@octokit/core@5.2.1)
'@octokit/plugin-rest-endpoint-methods': 10.4.1(@octokit/core@5.2.1)
'@octokit/request': 8.4.1
'@octokit/request-error': 5.1.1
undici: 5.28.5
'@actions/http-client@2.2.3':
dependencies:
tunnel: 0.0.6
undici: 5.28.5
'@actions/io@1.1.3': {}
'@adobe/css-tools@4.4.2': {}
'@algolia/autocomplete-core@1.17.7(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)(search-insights@2.8.2)':
@@ -16974,6 +17095,8 @@ snapshots:
'@octokit/auth-token@3.0.4': {}
'@octokit/auth-token@4.0.0': {}
'@octokit/core@4.2.4(encoding@0.1.13)':
dependencies:
'@octokit/auth-token': 3.0.4
@@ -16986,12 +17109,27 @@ snapshots:
transitivePeerDependencies:
- encoding
'@octokit/core@5.2.1':
dependencies:
'@octokit/auth-token': 4.0.0
'@octokit/graphql': 7.1.1
'@octokit/request': 8.4.1
'@octokit/request-error': 5.1.1
'@octokit/types': 13.10.0
before-after-hook: 2.2.3
universal-user-agent: 6.0.1
'@octokit/endpoint@7.0.6':
dependencies:
'@octokit/types': 9.3.2
is-plain-object: 5.0.0
universal-user-agent: 6.0.1
'@octokit/endpoint@9.0.6':
dependencies:
'@octokit/types': 13.10.0
universal-user-agent: 6.0.1
'@octokit/graphql@5.0.6(encoding@0.1.13)':
dependencies:
'@octokit/request': 6.2.8(encoding@0.1.13)
@@ -17000,18 +17138,38 @@ snapshots:
transitivePeerDependencies:
- encoding
'@octokit/graphql@7.1.1':
dependencies:
'@octokit/request': 8.4.1
'@octokit/types': 13.10.0
universal-user-agent: 6.0.1
'@octokit/openapi-types@18.1.1': {}
'@octokit/openapi-types@20.0.0': {}
'@octokit/openapi-types@24.2.0': {}
'@octokit/plugin-paginate-rest@6.1.2(@octokit/core@4.2.4(encoding@0.1.13))':
dependencies:
'@octokit/core': 4.2.4(encoding@0.1.13)
'@octokit/tsconfig': 1.0.2
'@octokit/types': 9.3.2
'@octokit/plugin-paginate-rest@9.2.2(@octokit/core@5.2.1)':
dependencies:
'@octokit/core': 5.2.1
'@octokit/types': 12.6.0
'@octokit/plugin-request-log@1.0.4(@octokit/core@4.2.4(encoding@0.1.13))':
dependencies:
'@octokit/core': 4.2.4(encoding@0.1.13)
'@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.2.1)':
dependencies:
'@octokit/core': 5.2.1
'@octokit/types': 12.6.0
'@octokit/plugin-rest-endpoint-methods@7.2.3(@octokit/core@4.2.4(encoding@0.1.13))':
dependencies:
'@octokit/core': 4.2.4(encoding@0.1.13)
@@ -17023,6 +17181,12 @@ snapshots:
deprecation: 2.3.1
once: 1.4.0
'@octokit/request-error@5.1.1':
dependencies:
'@octokit/types': 13.10.0
deprecation: 2.3.1
once: 1.4.0
'@octokit/request@6.2.8(encoding@0.1.13)':
dependencies:
'@octokit/endpoint': 7.0.6
@@ -17034,6 +17198,13 @@ snapshots:
transitivePeerDependencies:
- encoding
'@octokit/request@8.4.1':
dependencies:
'@octokit/endpoint': 9.0.6
'@octokit/request-error': 5.1.1
'@octokit/types': 13.10.0
universal-user-agent: 6.0.1
'@octokit/rest@19.0.13(encoding@0.1.13)':
dependencies:
'@octokit/core': 4.2.4(encoding@0.1.13)
@@ -17049,6 +17220,14 @@ snapshots:
dependencies:
'@octokit/openapi-types': 18.1.1
'@octokit/types@12.6.0':
dependencies:
'@octokit/openapi-types': 20.0.0
'@octokit/types@13.10.0':
dependencies:
'@octokit/openapi-types': 24.2.0
'@octokit/types@9.3.2':
dependencies:
'@octokit/openapi-types': 18.1.1
@@ -18978,7 +19157,7 @@ snapshots:
acorn-walk@8.3.3:
dependencies:
acorn: 8.14.0
acorn: 8.14.1
acorn@8.12.1: {}
@@ -24715,6 +24894,11 @@ snapshots:
is-docker: 2.2.1
is-wsl: 2.2.0
openai@5.8.1(ws@8.18.0)(zod@3.25.67):
optionalDependencies:
ws: 8.18.0
zod: 3.25.67
openapi-typescript@6.7.6:
dependencies:
ansi-colors: 4.1.3
@@ -27409,6 +27593,8 @@ snapshots:
argparse: 2.0.1
pako: 1.0.11
tunnel@0.0.6: {}
type-check@0.4.0:
dependencies:
prelude-ls: 1.2.1
@@ -28430,6 +28616,8 @@ snapshots:
zod@3.24.2: {}
zod@3.25.67: {}
zone.js@0.11.8:
dependencies:
tslib: 2.8.1

124
scripts/suggestTags.mts Normal file
View File

@@ -0,0 +1,124 @@
import OpenAI from "openai";
import { Octokit } from "@octokit/rest";
import { zodTextFormat } from "openai/helpers/zod";
import path from "node:path";
import fs from "node:fs/promises";
import z from "zod";
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
const pullRequestNumber = Number(process.env.PULL_REQUEST_NUMBER);
const username = process.env.REVIEWER ?? 'github-actions[bot]';
const commitSha = process.env.COMMIT_SHA ?? "HEAD";
const owner = 'lucide-icons';
const repo = 'lucide';
const tagsSchema = z.object({
tags: z.array(z.string()),
})
const { data: files } = await octokit.pulls.listFiles({
owner,
repo,
pull_number: pullRequestNumber,
});
const { data: reviews } = await octokit.pulls.listReviews({
owner,
repo,
pull_number: pullRequestNumber,
query: `in:body author:github-actions[bot]`,
});
const hasUserReviews = reviews.some(review => review.user?.login === username);
// TODO: Find a better way to check if the PR has been updated since the last review
if(hasUserReviews) {
console.log(`Pull request #${pullRequestNumber} already has reviews from ${username}. Skipping...`);
process.exit(0);
}
const changedFiles = files
.map((file) => file.filename)
.filter((file) => file.startsWith('icons/') && file.includes('.json'))
.filter((file, idx, arr) => arr.indexOf(file) === idx);;
if (changedFiles.length === 0) {
console.log('No changed icons found');
process.exit(0);
}
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
const suggestionsByFile = changedFiles.map(async (file) => {
const filePath = file.replace('.json', '');
const iconName = filePath.split('/').pop();
const input = `Create a list of tags for a \`${iconName}\` icon. Don't include words like: 'icon' and preferably use single words.`;
const response = await client.responses.create({
model: "gpt-4.1-nano",
input,
text: {
format: zodTextFormat(tagsSchema, "tags"),
},
});
const { tags: suggestedTags } = JSON.parse(response.output_text);
console.log(`Suggesting tags for ${iconName}:`, suggestedTags);
// const currentContent = require(`../${filePath}`);
const jsonFile = path.join(process.cwd(), file);
const currentFileContent = await fs.readFile(jsonFile, 'utf-8') as unknown as string;
const metaData = JSON.parse(currentFileContent);
console.log(`Current tags for ${iconName}:`, metaData.tags || []);
const tagSuggestionsWithoutDuplicates = suggestedTags.filter((tag) => {
return !metaData.tags?.includes(tag) && tag !== iconName;
});
console.log(`Tag suggestions for ${iconName} without duplicates:`, tagSuggestionsWithoutDuplicates);
if (tagSuggestionsWithoutDuplicates.length === 0) {
console.log(`No new tags to suggest for ${iconName}. Skipping...`);
return Promise.resolve(null);
}
// Find the startLine in the json file
const startLine = currentFileContent.split('\n').findIndex((line) => line.includes('"tags":')) + 1;
const codeSuggestion = tagSuggestionsWithoutDuplicates.map((tag) => ` "${tag}"`).join(',\n');
const message = `Suggestions for the \`${iconName}\` icon.
Try asking it your self if you want more suggestions. [Open ChatGPT](https://chatgpt.com/?q=${encodeURIComponent(input)})
Here are the suggestions:
\`\`\`suggestion\n "tags": [\n${codeSuggestion},`;
return {
path: file,
line: startLine,
body: message,
}
})
const comments = (await Promise.all(suggestionsByFile)).filter(comment => comment !== null)
if (comments.length === 0) {
console.log('No new tags to suggest for any icons.');
process.exit(0);
}
await octokit.pulls.createReview({
owner,
repo,
pull_number: pullRequestNumber,
body: `### 🤖 ChatGPT Tags suggestions ✨
I've asked ChatGPT for some suggestions for tags.`,
event: "COMMENT",
comments,
commit_id: commitSha,
});