From e516424935598434c6a3b162628e622a41cca18a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?chencheng=20=28=E4=BA=91=E8=B0=A6=29?= Date: Thu, 23 Mar 2023 21:43:19 +0800 Subject: [PATCH] feat: add @umijs/copilot (still wip) (#10831) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add @umijs/copilot (still wip) * chore: update pnpm-lock.yaml * chore: code style * Update copilot/bin/umi-copilot.js Co-authored-by: 咲奈Sakina <59400654+fz6m@users.noreply.github.com> --------- Co-authored-by: 咲奈Sakina <59400654+fz6m@users.noreply.github.com> --- codemod/.fatherrc.ts | 3 ++ codemod/package.json | 5 +- copilot/.fatherrc.ts | 4 ++ copilot/.gitignore | 5 ++ copilot/bin/umi-copilot.js | 6 +++ copilot/package.json | 35 ++++++++++++++ copilot/src/chatgpt.ts | 80 ++++++++++++++++++++++++++++++++ copilot/src/cli.ts | 90 ++++++++++++++++++++++++++++++++++++ copilot/src/constants.ts | 16 +++++++ copilot/src/printHelp.ts | 16 +++++++ did-you-know/package.json | 2 + package.json | 7 ++- pnpm-lock.yaml | 77 ++++++++++++++++++++++++------ pnpm-workspace.yaml | 1 + scripts/releaseCodemod.ts | 66 -------------------------- scripts/releaseDidYouKnow.ts | 70 ---------------------------- scripts/releasePackage.ts | 23 +++++++++ 17 files changed, 354 insertions(+), 152 deletions(-) create mode 100644 codemod/.fatherrc.ts create mode 100644 copilot/.fatherrc.ts create mode 100644 copilot/.gitignore create mode 100755 copilot/bin/umi-copilot.js create mode 100644 copilot/package.json create mode 100644 copilot/src/chatgpt.ts create mode 100644 copilot/src/cli.ts create mode 100644 copilot/src/constants.ts create mode 100644 copilot/src/printHelp.ts delete mode 100644 scripts/releaseCodemod.ts delete mode 100644 scripts/releaseDidYouKnow.ts create mode 100644 scripts/releasePackage.ts diff --git a/codemod/.fatherrc.ts b/codemod/.fatherrc.ts new file mode 100644 index 000000000000..2ac8c0f6ec49 --- /dev/null +++ b/codemod/.fatherrc.ts @@ -0,0 +1,3 @@ +export default { + extends: '../.fatherrc.base.ts', +}; diff --git a/codemod/package.json b/codemod/package.json index fc630da8af4c..456a6eb9dfdf 100644 --- a/codemod/package.json +++ b/codemod/package.json @@ -15,7 +15,10 @@ "dist" ], "scripts": { - "build": "pnpm tsc", + "build": "father build", + "dev": "father dev", + "doctor": "father doctor", + "release": "father doctor && esno ../scripts/release.ts --pkg codemod", "test": "jest" }, "dependencies": { diff --git a/copilot/.fatherrc.ts b/copilot/.fatherrc.ts new file mode 100644 index 000000000000..e64c91d37329 --- /dev/null +++ b/copilot/.fatherrc.ts @@ -0,0 +1,4 @@ +export default { + extends: '../.fatherrc.base.ts', + prebundle: {}, +}; diff --git a/copilot/.gitignore b/copilot/.gitignore new file mode 100644 index 000000000000..de0a726e00d4 --- /dev/null +++ b/copilot/.gitignore @@ -0,0 +1,5 @@ +/dist +/node_modules +/fixtures/*/node_modules +/fixtures/tmp +/fixtures/**/*.out.js diff --git a/copilot/bin/umi-copilot.js b/copilot/bin/umi-copilot.js new file mode 100755 index 000000000000..eedaef0e0ee5 --- /dev/null +++ b/copilot/bin/umi-copilot.js @@ -0,0 +1,6 @@ +#!/usr/bin/env node + +require('../dist/cli').main().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/copilot/package.json b/copilot/package.json new file mode 100644 index 000000000000..9b8910c49f58 --- /dev/null +++ b/copilot/package.json @@ -0,0 +1,35 @@ +{ + "name": "@umijs/copilot", + "version": "0.0.0", + "homepage": "https://github.com/umijs/umi/tree/master/copilot", + "bugs": "https://github.com/umijs/umi/issues", + "repository": { + "type": "git", + "url": "https://github.com/umijs/umi" + }, + "bin": { + "umi-copilot": "bin/umi-copilot.js" + }, + "files": [ + "bin", + "dist" + ], + "scripts": { + "build": "father build", + "dev": "father dev", + "doctor": "father doctor", + "prebundle": "father prebundle", + "release": "father doctor && esno ../scripts/release.ts --pkg copilot", + "test": "jest" + }, + "dependencies": { + "@umijs/utils": "workspace:*", + "zx": "^7.2.1" + }, + "publishConfig": { + "access": "public" + }, + "authors": [ + "chencheng (https://github.com/sorrycc)" + ] +} diff --git a/copilot/src/chatgpt.ts b/copilot/src/chatgpt.ts new file mode 100644 index 000000000000..b52a118c8cee --- /dev/null +++ b/copilot/src/chatgpt.ts @@ -0,0 +1,80 @@ +import { axios } from '@umijs/utils'; + +interface IMessage { + role: 'system' | 'user' | 'assistant'; + content: string; +} + +interface IChatGPTResponse { + error?: { + type: string; + code: string; + message: string; + }; + created: number; + choices: { + index: number; + message: IMessage; + finish_reason: string; + }[]; + usage: { + prompt_tokens: number; + completion_tokens: number; + total_tokens: number; + }; +} + +const requestParamsBase = { + model: 'gpt-3.5-turbo', + temperature: 0.5, + top_p: 0.8, + presence_penalty: 1.0, + max_tokens: 500, +}; + +function getApiUrl(proxyUrl?: string) { + if (proxyUrl) { + proxyUrl = proxyUrl.replace(/^https?:\/\//, '').replace(/\/$/, ''); + } + return `https://${proxyUrl || 'api.openai.com'}/v1/chat/completions`; +} + +export async function sendMessage(opts: { + messages: IMessage[]; + token: string; + proxyUrl?: string; + controller?: AbortController; + timeout?: number; +}) { + const apiUrl = getApiUrl(opts.proxyUrl); + let res: any = null; + try { + res = await axios.post( + apiUrl, + { + ...requestParamsBase, + messages: opts.messages, + stream: false, + }, + { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${opts.token}`, + }, + validateStatus: () => true, + signal: opts.controller?.signal, + timeout: opts.timeout || 20000, + }, + ); + } catch (e: any) { + if (opts.controller?.signal.aborted === true) { + // 用户手动取消了请求 + } else { + throw new Error('Network Error'); + } + } + if (res.data.error) { + throw new Error(res.data.error.message); + } + return res; +} diff --git a/copilot/src/cli.ts b/copilot/src/cli.ts new file mode 100644 index 000000000000..703239276942 --- /dev/null +++ b/copilot/src/cli.ts @@ -0,0 +1,90 @@ +import { chalk, clackPrompts, logger, resolve, yParser } from '@umijs/utils'; +import { sendMessage } from './chatgpt'; +import { SYSTEM_PROMPT } from './constants'; +import { printHelp } from './printHelp'; +const { confirm, spinner } = clackPrompts; + +export async function main() { + logger.info("🚧 It's in beta, please use it carefully."); + const args = yParser(process.argv.slice(2), { + alias: { + help: ['h'], + }, + }); + const cwd = args.cwd || process.cwd(); + + if (args.help) { + printHelp(); + return; + } + + // --token + const token = process.env.OPENAI_API_KEY || args.token; + if (!token) { + throw new Error('Please set OPENAI_API_KEY or --token'); + } + + const message = args._.join(' '); + const s = spinner(); + s.start('🕖 Hold on, asking OpenAI...'); + const res = await sendMessage({ + messages: [ + { + role: 'system', + content: SYSTEM_PROMPT, + }, + { + role: 'user', + content: message, + }, + ], + token, + // --proxy-url + proxyUrl: args.proxyUrl, + }); + s.stop(); + const command = res.data.choices[0].message.content; + logger.info('The suggested command is:'); + logger.info(chalk.green(command)); + + const shouldRunCommand = await confirm({ + message: `Run the command?`, + }); + // why equals true? + // since if user press ctrl+c, shouldRunCommand will not be falsy + if (shouldRunCommand === true) { + logger.info('✅ Running the command...'); + process.env.FORCE_COLOR = '1'; + const commandPath = await findUmiCommand({ cwd }); + logger.info(`Command Path: ${commandPath}`); + // why split? + // since zx.$ has problem when parsing command with template string + const { $ } = await import('zx'); + await $`${command.replace('umi', commandPath).split(' ')}`; + } +} + +async function findUmiCommand(opts: { cwd: string }) { + let ret; + // max > umi > global max > global umi + if (!ret) ret = resolveSyncSilently('max/bin/max.js', opts.cwd); + if (!ret) ret = resolveSyncSilently('umi/bin/umi.js', opts.cwd); + const { $ } = await import('zx'); + try { + if (!ret) ret = (await $`which max`).stdout.trim(); + } catch (_e) {} + try { + if (!ret) ret = (await $`which umi`).stdout.trim(); + } catch (_e) {} + return ret; +} + +function resolveSyncSilently(path: string, cwd: string) { + try { + return resolve.sync(path, { + basedir: cwd, + }); + } catch (e) { + return null; + } +} diff --git a/copilot/src/constants.ts b/copilot/src/constants.ts new file mode 100644 index 000000000000..f38fbaf92056 --- /dev/null +++ b/copilot/src/constants.ts @@ -0,0 +1,16 @@ +// TODO: IMPROVE THIS +export const SYSTEM_PROMPT = ` +Umi 框架有一些命令如下: + +umi dev +umi build + +umi dev 可以通过 PORT 环境变量指定端口号。 +umi build 可以通过设置 COMPRESS 环境变量为 none 来让构建不进行压缩。 + +环境变量的使用方法是在命令之前加入环境变量,如: +PORT=1234 umi dev +COMPRESS=none umi build + +基于以上知识,请基于我的要求给出 umi 相关可执行的命令。只给可执行的命令行,不要做任何额外解释。 +`; diff --git a/copilot/src/printHelp.ts b/copilot/src/printHelp.ts new file mode 100644 index 000000000000..b1e000d5540b --- /dev/null +++ b/copilot/src/printHelp.ts @@ -0,0 +1,16 @@ +export function printHelp() { + console.log(` +Usage: umi-copilot [message] + +Options: + --token OpenAI API key + --proxy-url Proxy URL for OpenAI API + --cwd Working directory + --timeout Timeout for OpenAI API, Default: 20000 + --help Show help + +Examples: + $ umi-copilot "I want to" + + `); +} diff --git a/did-you-know/package.json b/did-you-know/package.json index 3a6eb8f0b3e1..731caf498087 100644 --- a/did-you-know/package.json +++ b/did-you-know/package.json @@ -16,6 +16,8 @@ "scripts": { "build": "father build", "dev": "father dev", + "doctor": "father doctor", + "release": "father doctor && esno ../scripts/release.ts --pkg did-you-know", "test": "jest" }, "devDependencies": { diff --git a/package.json b/package.json index 0a981c0a8308..8cd1f7a355d9 100644 --- a/package.json +++ b/package.json @@ -11,15 +11,18 @@ "codemod:build": "pnpm --filter @umijs/codemod build", "codemod:dev": "pnpm --filter @umijs/codemod build --watch", "codemod:jest": "cd codemod && jest", - "codemod:release": "umi-scripts releaseCodemod", + "codemod:release": "pnpm --filter @umijs/codemod release", "codemod:run": "BACON=none GIT_CHECK=none ./codemod/bin/umi-codemod.js --cwd codemod/fixtures/tmp", "codemod:test": "BACON=none GIT_CHECK=none umi-scripts testCodemod", + "copilot:build": "pnpm --filter @umijs/copilot build", + "copilot:dev": "pnpm --filter @umijs/copilot dev", + "copilot:release": "pnpm --filter @umijs/copilot release", "cov": "jest --coverage", "dep:update": "pnpm up --interactive --latest --recursive", "dev": "umi-scripts turbo dev --parallel", "didyouknow:build": "pnpm --filter @umijs/did-you-know build", "didyouknow:dev": "pnpm --filter @umijs/did-you-know dev", - "didyouknow:release": "umi-scripts releaseDidYouKnow", + "didyouknow:release": "pnpm --filter @umijs/did-you-know release", "doc:build": "pnpm doc:deps && umi build", "doc:deps": "pnpm doc:deps-ts && pnpm doc:deps-extra", "doc:deps-extra": "umi-scripts turbo build:extra --filter @umijs/plugin-docs...", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ff602730bb4c..e4491e1379a1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -143,6 +143,14 @@ importers: fast-glob: 3.2.12 kleur: 4.1.5 + copilot: + specifiers: + '@umijs/utils': workspace:* + zx: ^7.2.1 + dependencies: + '@umijs/utils': link:../packages/utils + zx: 7.2.1 + did-you-know: specifiers: terminal-link: ^3.0.0 @@ -12607,7 +12615,6 @@ packages: dependencies: '@types/jsonfile': 6.1.1 '@types/node': 18.11.18 - dev: true /@types/fs-extra/8.1.2: resolution: {integrity: sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==} @@ -12734,7 +12741,6 @@ packages: resolution: {integrity: sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==} dependencies: '@types/node': 18.11.18 - dev: true /@types/jsonwebtoken/9.0.0: resolution: {integrity: sha512-mM4TkDpA9oixqg1Fv2vVpOFyIVLJjm5x4k0V+K/rEsizfjD7Tk7LKk3GTtbB7KCfP0FEHQtsZqFxYA0+sijNVg==} @@ -12830,6 +12836,9 @@ packages: /@types/node/18.11.18: resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} + /@types/node/18.15.5: + resolution: {integrity: sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==} + /@types/node/18.7.4: resolution: {integrity: sha512-RzRcw8c0B8LzryWOR4Wj7YOTFXvdYKwvrb6xQQyuDfnlTxwYXGCV5RZ/TEbq5L5kn+w3rliHAUyRcG1RtbmTFg==} dev: true @@ -12859,7 +12868,6 @@ packages: /@types/ps-tree/1.1.2: resolution: {integrity: sha512-ZREFYlpUmPQJ0esjxoG1fMvB2HNaD3z+mjqdSosZvd3RalncI9NEur73P8ZJz4YQdL64CmV1w0RuqoRUlhQRBw==} - dev: true /@types/qs/6.9.7: resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} @@ -13069,6 +13077,9 @@ packages: resolution: {integrity: sha512-Jjakcv8Roqtio6w1gr0D7y6twbhx6gGgFGF5BLwajPpnOIOxFkakFhCq+LmyyeAz7BX6ULrjBOxdKaCDy+4+dQ==} dev: true + /@types/which/2.0.2: + resolution: {integrity: sha512-113D3mDkZDjo+EeUEHCFy0qniNc1ZpecGiAU7WSo7YDoSzolZIQKpYFHrPpjkB2nuyahcKfrmLXeQlh7gqJYdw==} + /@types/ws/8.5.4: resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==} dependencies: @@ -17818,6 +17829,10 @@ packages: engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} dev: true + /chalk/5.2.0: + resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + /change-case/4.1.2: resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==} dependencies: @@ -22001,7 +22016,6 @@ packages: split: 0.3.3 stream-combiner: 0.0.4 through: 2.3.8 - dev: true /eventemitter2/6.4.7: resolution: {integrity: sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==} @@ -22948,7 +22962,6 @@ packages: /from/0.1.7: resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} - dev: true /fromentries/1.3.2: resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==} @@ -22978,7 +22991,6 @@ packages: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.0 - dev: true /fs-extra/7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} @@ -23466,6 +23478,16 @@ packages: merge2: 1.4.1 slash: 4.0.0 + /globby/13.1.3: + resolution: {integrity: sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.2.12 + ignore: 5.2.0 + merge2: 1.4.1 + slash: 4.0.0 + /globby/6.1.0: resolution: {integrity: sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==} engines: {node: '>=0.10.0'} @@ -27078,7 +27100,6 @@ packages: /map-stream/0.1.0: resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} - dev: true /map-visit/1.0.0: resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} @@ -27963,6 +27984,9 @@ packages: /minimist/1.2.6: resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + /minimist/1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + /minipass-collect/1.0.2: resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} engines: {node: '>= 8'} @@ -28407,7 +28431,6 @@ packages: data-uri-to-buffer: 4.0.0 fetch-blob: 3.2.0 formdata-polyfill: 4.0.10 - dev: true /node-fetch/3.2.8: resolution: {integrity: sha512-KtpD1YhGszhntMpBDyp5lyagk8KIMopC1LEb7cQUAh7zcosaX5uK8HnbNb2i3NTQK3sIawCItS0uFC3QzcLHdg==} @@ -29653,7 +29676,6 @@ packages: resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} dependencies: through: 2.3.8 - dev: true /pbf/3.2.1: resolution: {integrity: sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==} @@ -31687,7 +31709,6 @@ packages: engines: {node: '>= 0.10'} dependencies: event-stream: 3.3.4 - dev: true /pseudomap/1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} @@ -37905,7 +37926,6 @@ packages: resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} dependencies: through: 2.3.8 - dev: true /split/1.0.1: resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==} @@ -38049,7 +38069,6 @@ packages: resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} dependencies: duplexer: 0.1.2 - dev: true /stream-http/2.8.3: resolution: {integrity: sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==} @@ -39454,7 +39473,7 @@ packages: resolution: {integrity: sha512-SLBg2GBKlR6bVtMgJJlud/o3waplKtL7skmLkExomIiaAtLGtVsoXIqP3SYdjbcH9lq/KVv7pMZeCBpLYOit6Q==} dependencies: json5: 2.2.3 - minimist: 1.2.6 + minimist: 1.2.8 strip-bom: 3.0.0 dev: true @@ -41237,6 +41256,10 @@ packages: webpack: 5.76.1_@swc+core@1.3.24 dev: true + /webpod/0.0.2: + resolution: {integrity: sha512-cSwwQIeg8v4i3p4ajHhwgR7N6VyxAf+KYSSsY6Pd3aETE+xEU4vbitz7qQkB0I321xnhDdgtxuiSfk5r/FVtjg==} + hasBin: true + /websocket-driver/0.7.4: resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} engines: {node: '>=0.8.0'} @@ -41357,6 +41380,13 @@ packages: dependencies: isexe: 2.0.0 + /which/3.0.0: + resolution: {integrity: sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + isexe: 2.0.0 + /wide-align/1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} dependencies: @@ -41762,3 +41792,24 @@ packages: which: 2.0.2 yaml: 2.2.1 dev: true + + /zx/7.2.1: + resolution: {integrity: sha512-TgKwppaMLMNAXHhlhbBh7rMoOSx3/9qqnkv8frmhVlSomEuWkDijh/BCmYntkoS7ZQyemApAUyEi24jIrrS+hA==} + engines: {node: '>= 16.0.0'} + hasBin: true + dependencies: + '@types/fs-extra': 11.0.1 + '@types/minimist': 1.2.2 + '@types/node': 18.15.5 + '@types/ps-tree': 1.1.2 + '@types/which': 2.0.2 + chalk: 5.2.0 + fs-extra: 11.1.0 + globby: 13.1.3 + minimist: 1.2.8 + node-fetch: 3.2.10 + ps-tree: 1.2.0 + webpod: 0.0.2 + which: 3.0.0 + yaml: 2.2.1 + dev: false diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 51957a3383d4..5ab5ae0861ad 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,6 +3,7 @@ packages: - 'examples/*' - 'libs/*' - 'codemod' + - 'copilot' - 'did-you-know' - 'scripts' - 'ui' diff --git a/scripts/releaseCodemod.ts b/scripts/releaseCodemod.ts deleted file mode 100644 index adf686048528..000000000000 --- a/scripts/releaseCodemod.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { logger } from '@umijs/utils'; -import getGitRepoInfo from 'git-repo-info'; -import { join } from 'path'; -import 'zx/globals'; - -function assert(v: unknown, message: string) { - if (!v) { - logger.error(message); - process.exit(1); - } -} - -(async () => { - const cwd = process.cwd(); - const pkg = '@umijs/codemod'; - const dirName = 'codemod'; - const { branch } = getGitRepoInfo(); - logger.info(`branch: ${branch}`); - logger.info(`cwd: ${cwd}`); - - // check git status - logger.event('check git status'); - const isGitClean = (await $`git status --porcelain`).stdout.trim().length; - assert(!isGitClean, 'git status is not clean'); - - // check git remote update - logger.event('check git remote update'); - await $`git fetch`; - const gitStatus = (await $`git status --short --branch`).stdout.trim(); - assert(!gitStatus.includes('behind'), `git status is behind remote`); - - // check npm ownership - logger.event('check npm ownership'); - const whoami = (await $`npm whoami`).stdout.trim(); - const owners = (await $`npm owner ls ${pkg}`).stdout - .trim() - .split('\n') - .map((line) => { - return line.split(' ')[0]; - }); - assert(owners.includes(whoami), `${pkg} is not owned by ${whoami}`); - - // bump version - logger.event(`bump version of ${pkg}`); - const pkgPath = join(cwd, dirName); - logger.info( - `current version: ${require(join(pkgPath, 'package.json')).version}`, - ); - const version = await question(`What's next version? `); - await $`cd ${pkgPath} && npm version ${version}`; - - // pnpm publish - logger.event('pnpm publish'); - $.verbose = false; - await $`cd ${pkgPath} && pnpm publish --no-git-checks`; - logger.info(`+ ${pkg}@${version}`); - $.verbose = true; - - // commit - logger.event('commit'); - await $`git commit --all --message "release: ${pkg}@${version}"`; - - // git push - logger.event('git push'); - await $`git push origin ${branch}`; -})(); diff --git a/scripts/releaseDidYouKnow.ts b/scripts/releaseDidYouKnow.ts deleted file mode 100644 index 2f0a7463c202..000000000000 --- a/scripts/releaseDidYouKnow.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { logger } from '@umijs/utils'; -import getGitRepoInfo from 'git-repo-info'; -import { join } from 'path'; -import 'zx/globals'; - -function assert(v: unknown, message: string) { - if (!v) { - logger.error(message); - process.exit(1); - } -} - -(async () => { - const cwd = process.cwd(); - const pkg = '@umijs/did-you-know'; - const dirName = 'did-you-know'; - const { branch } = getGitRepoInfo(); - logger.info(`branch: ${branch}`); - logger.info(`cwd: ${cwd}`); - - // check git status - logger.event('check git status'); - const isGitClean = (await $`git status --porcelain`).stdout.trim().length; - assert(!isGitClean, 'git status is not clean'); - - // check git remote update - logger.event('check git remote update'); - await $`git fetch`; - const gitStatus = (await $`git status --short --branch`).stdout.trim(); - assert(!gitStatus.includes('behind'), `git status is behind remote`); - - // check npm ownership - logger.event('check npm ownership'); - const whoami = (await $`npm whoami`).stdout.trim(); - const owners = (await $`npm owner ls ${pkg}`).stdout - .trim() - .split('\n') - .map((line) => { - return line.split(' ')[0]; - }); - assert(owners.includes(whoami), `${pkg} is not owned by ${whoami}`); - - // bump version - logger.event(`bump version of ${pkg}`); - const pkgPath = join(cwd, dirName); - logger.info( - `current version: ${require(join(pkgPath, 'package.json')).version}`, - ); - await $`cd ${pkgPath} && npm version patch`; - const version = require(path.join(pkgPath, 'package.json')).version; - - // pnpm publish - logger.event('pnpm publish'); - $.verbose = false; - await $`cd ${pkgPath} && pnpm publish --no-git-checks`; - logger.info(`+ ${pkg}@${version}`); - $.verbose = true; - - // commit - logger.event('commit'); - await $`git commit --all --message "release: ${pkg}@${version}"`; - - // git push - logger.event('git push'); - await $`git push origin ${branch}`; - - // tnpm sync - logger.event('tnpm sync'); - await $`tnpm sync ${pkg}`; -})(); diff --git a/scripts/releasePackage.ts b/scripts/releasePackage.ts new file mode 100644 index 000000000000..3c79f675a7d3 --- /dev/null +++ b/scripts/releasePackage.ts @@ -0,0 +1,23 @@ +import assert from 'assert'; +import getGitRepoInfo from 'git-repo-info'; +import 'zx/globals'; + +(async () => { + const { branch } = getGitRepoInfo(); + const pkgName = argv.pkg; + assert(pkgName, `pkg name is required, specify with --pkg=xxx`); + const pkgPath = path.join(__dirname, '..', pkgName); + assert(fs.existsSync(pkgPath), `pkg ${pkgName} not exists`); + await $`cd ${pkgPath} && npm run build`; + await $`cd ${pkgPath} && npm version patch`; + const newVersion = require(path.join(pkgPath, 'package.json')).version; + await $`cd ${pkgPath} && pnpm publish --no-git-checks`; + + // commit and tag and push + await $`git commit -am "release: ${pkgName}@${newVersion}"`; + await $`git tag ${pkgName}v${newVersion}`; + await $`git push origin ${branch} --tags`; +})().catch((e) => { + console.error(e); + process.exit(1); +});