更新依赖版本;重构代码以使用环境变量中的令牌;添加身份验证中间件以增强安全性
This commit is contained in:
8
bun.lock
8
bun.lock
@@ -5,16 +5,16 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "to-my-gitea",
|
"name": "to-my-gitea",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kevisual/cnb": "^0.0.53",
|
"@kevisual/cnb": "^0.0.56",
|
||||||
"@kevisual/context": "^0.0.8",
|
"@kevisual/context": "^0.0.8",
|
||||||
"@kevisual/gitea": "^0.0.6",
|
"@kevisual/gitea": "^0.0.6",
|
||||||
"@kevisual/router": "^0.1.4",
|
"@kevisual/router": "^0.1.6",
|
||||||
"dayjs": "^1.11.20",
|
"dayjs": "^1.11.20",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@kevisual/cnb": ["@kevisual/cnb@0.0.53", "https://registry.npmmirror.com/@kevisual/cnb/-/cnb-0.0.53.tgz", { "dependencies": { "@kevisual/query": "^0.0.53", "@kevisual/router": "^0.1.3", "@kevisual/use-config": "^1.0.30", "@opencode-ai/sdk": "^1.2.27", "es-toolkit": "^1.45.1", "nanoid": "^5.1.7", "unstorage": "^1.17.4", "ws": "npm:@kevisual/ws" }, "bin": { "cnb": "bin/index.js", "cloud": "bin/index.js", "cloud-npc": "bin/npc.js" } }, "sha512-moDiUkWNaHtOvQ2WXhILD2o7OdKv+/QW6fb4Iq8VXPBI+AYdVN4kmdBSIXR1RGulbYX82gaZcjypC/4vYDD/PQ=="],
|
"@kevisual/cnb": ["@kevisual/cnb@0.0.56", "https://registry.npmmirror.com/@kevisual/cnb/-/cnb-0.0.56.tgz", { "dependencies": { "@kevisual/query": "^0.0.53", "@kevisual/router": "^0.1.3", "@kevisual/use-config": "^1.0.30", "@opencode-ai/sdk": "^1.2.27", "es-toolkit": "^1.45.1", "nanoid": "^5.1.7", "unstorage": "^1.17.4", "ws": "npm:@kevisual/ws" }, "bin": { "cnb": "bin/index.js", "cloud": "bin/index.js", "cloud-npc": "bin/npc.js" } }, "sha512-Pa70TI/zVC7DOSecrRztB8QrRlf+iuFCGDH/O3YEQw/eMoyDdBtIxR3Ewnsu+n+BN0od6jcsSOhDW6kzqeX8cA=="],
|
||||||
|
|
||||||
"@kevisual/context": ["@kevisual/context@0.0.8", "https://registry.npmmirror.com/@kevisual/context/-/context-0.0.8.tgz", {}, "sha512-DTJpyHI34NE76B7g6f+QlIqiCCyqI2qkBMQE736dzeRDGxOjnbe2iQY9W+Rt2PE6kmymM3qyOmSfNovyWyWrkA=="],
|
"@kevisual/context": ["@kevisual/context@0.0.8", "https://registry.npmmirror.com/@kevisual/context/-/context-0.0.8.tgz", {}, "sha512-DTJpyHI34NE76B7g6f+QlIqiCCyqI2qkBMQE736dzeRDGxOjnbe2iQY9W+Rt2PE6kmymM3qyOmSfNovyWyWrkA=="],
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
"@kevisual/query": ["@kevisual/query@0.0.53", "https://registry.npmmirror.com/@kevisual/query/-/query-0.0.53.tgz", {}, "sha512-PAhpCLBr0emz0lGNlTVHMbJiC5wrtGLbInPddRzgKE35fiyNt+SWSsUWABiD0DeNrLN/OxWyAFobt880Z/e5MQ=="],
|
"@kevisual/query": ["@kevisual/query@0.0.53", "https://registry.npmmirror.com/@kevisual/query/-/query-0.0.53.tgz", {}, "sha512-PAhpCLBr0emz0lGNlTVHMbJiC5wrtGLbInPddRzgKE35fiyNt+SWSsUWABiD0DeNrLN/OxWyAFobt880Z/e5MQ=="],
|
||||||
|
|
||||||
"@kevisual/router": ["@kevisual/router@0.1.4", "https://registry.npmmirror.com/@kevisual/router/-/router-0.1.4.tgz", { "dependencies": { "crypto-js": "^4.2.0", "es-toolkit": "^1.45.1", "zod": "^4.3.6" } }, "sha512-/Gz3N4KAyCRQmy+FgtK8OEhainYxBnck97LSKeazHLzQ5lOoQs46XCGDYR/AjrCuDTuUrmfD/l1u9pFe2rjN8Q=="],
|
"@kevisual/router": ["@kevisual/router@0.1.6", "https://registry.npmmirror.com/@kevisual/router/-/router-0.1.6.tgz", { "dependencies": { "crypto-js": "^4.2.0", "es-toolkit": "^1.45.1", "zod": "^4.3.6" } }, "sha512-uQYxDd4j0ZKuuPXduSMSvckjEKi99hVRp7vz5AUFVDVbEBmNQBgDGbwmz9+X/DR/Gjx++x3m8XvYcAwuEzPOKw=="],
|
||||||
|
|
||||||
"@kevisual/use-config": ["@kevisual/use-config@1.0.30", "https://registry.npmmirror.com/@kevisual/use-config/-/use-config-1.0.30.tgz", { "dependencies": { "@kevisual/load": "^0.0.6" }, "peerDependencies": { "dotenv": "^17" } }, "sha512-kPdna0FW/X7D600aMdiZ5UTjbCo6d8d4jjauSc8RMmBwUU6WliFDSPUNKVpzm2BsDX5Nth1IXFPYMqH+wxqAmw=="],
|
"@kevisual/use-config": ["@kevisual/use-config@1.0.30", "https://registry.npmmirror.com/@kevisual/use-config/-/use-config-1.0.30.tgz", { "dependencies": { "@kevisual/load": "^0.0.6" }, "peerDependencies": { "dotenv": "^17" } }, "sha512-kPdna0FW/X7D600aMdiZ5UTjbCo6d8d4jjauSc8RMmBwUU6WliFDSPUNKVpzm2BsDX5Nth1IXFPYMqH+wxqAmw=="],
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"cli": "bun run src/cli.ts "
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
|
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
|
||||||
@@ -12,10 +12,10 @@
|
|||||||
"packageManager": "pnpm@10.32.1",
|
"packageManager": "pnpm@10.32.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kevisual/cnb": "^0.0.53",
|
"@kevisual/cnb": "^0.0.56",
|
||||||
"@kevisual/context": "^0.0.8",
|
"@kevisual/context": "^0.0.8",
|
||||||
"@kevisual/gitea": "^0.0.6",
|
"@kevisual/gitea": "^0.0.6",
|
||||||
"@kevisual/router": "^0.1.5",
|
"@kevisual/router": "^0.1.6",
|
||||||
"dayjs": "^1.11.20"
|
"dayjs": "^1.11.20"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ export const app = useContextKey("app", () => {
|
|||||||
});
|
});
|
||||||
return app;
|
return app;
|
||||||
});
|
});
|
||||||
|
export const token = useKey("CNB_API_KEY") || useKey('CNB_TOKEN')
|
||||||
|
|
||||||
export const cnb = useContextKey("cnb", () => {
|
export const cnb = useContextKey("cnb", () => {
|
||||||
const token = useKey("CNB_API_KEY") || useKey('CNB_TOKEN')
|
|
||||||
return new CNB({ token });
|
return new CNB({ token });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
export * from './app.ts';
|
export * from './app.ts';
|
||||||
|
import { app } from './app.ts';
|
||||||
import './routes/cnb.ts';
|
import './routes/cnb.ts';
|
||||||
import './routes/sync.ts';
|
import './routes/sync.ts';
|
||||||
|
|
||||||
|
app.createAuth((ctx) => { });
|
||||||
|
app.createRouteList()
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { useRepoInfoEnv } from '@kevisual/cnb';
|
||||||
import { app, cnb } from '../app';
|
import { app, cnb } from '../app';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
@@ -17,6 +18,7 @@ app.route({
|
|||||||
path: 'cnb',
|
path: 'cnb',
|
||||||
key: 'list-today',
|
key: 'list-today',
|
||||||
description: '获取今日更新的仓库列表',
|
description: '获取今日更新的仓库列表',
|
||||||
|
middleware: ['auth']
|
||||||
}).define(async (ctx) => {
|
}).define(async (ctx) => {
|
||||||
const res = await cnb.repo.getRepoList({ status: 'active', page_size: 100 });
|
const res = await cnb.repo.getRepoList({ status: 'active', page_size: 100 });
|
||||||
const list = res.data || [];
|
const list = res.data || [];
|
||||||
@@ -46,6 +48,7 @@ app.route({
|
|||||||
path: 'cnb',
|
path: 'cnb',
|
||||||
key: 'report',
|
key: 'report',
|
||||||
description: '上报仓库信息',
|
description: '上报仓库信息',
|
||||||
|
middleware: ['auth'],
|
||||||
metadata: {
|
metadata: {
|
||||||
args: {
|
args: {
|
||||||
repoList: z.array(repoSchema).describe('仓库列表')
|
repoList: z.array(repoSchema).describe('仓库列表')
|
||||||
@@ -63,16 +66,28 @@ app.route({
|
|||||||
infoTable += `| ${repo.path} | [链接](${repo.web_url}) | ${repo.description} | ${topics} | ${repo.updatedAt} |\n`;
|
infoTable += `| ${repo.path} | [链接](${repo.web_url}) | ${repo.description} | ${topics} | ${repo.updatedAt} |\n`;
|
||||||
});
|
});
|
||||||
console.log('上报的仓库信息表格:\n', infoTable);
|
console.log('上报的仓库信息表格:\n', infoTable);
|
||||||
|
const repoInfo = useRepoInfoEnv();
|
||||||
|
let afterInfo = '来源:CNB,';
|
||||||
|
if (repoInfo) {
|
||||||
|
afterInfo += `构建仓库:[${repoInfo.repoSlug}](${repoInfo.repoUrlHttps})`;
|
||||||
|
}
|
||||||
cnb.issue.createIssue('kevisual/kevisual', {
|
cnb.issue.createIssue('kevisual/kevisual', {
|
||||||
title: `仓库信息上报 - ${dayjs().format('YYYY-MM-DD HH:mm:ss')}`,
|
title: `仓库信息上报 - ${dayjs().format('YYYY-MM-DD HH:mm:ss')}`,
|
||||||
body: `以下是上报的仓库信息:\n\n${infoTable}`,
|
body: `以下是上报的仓库信息:\n\n${infoTable}\n\n${afterInfo}`,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
labels: ['report']
|
labels: ['report']
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}).addTo(app)
|
}).addTo(app)
|
||||||
|
app.route({
|
||||||
const closeOldReports = async () => {
|
path: 'cnb',
|
||||||
|
key: 'close-old-reports',
|
||||||
|
middleware: ['auth'],
|
||||||
|
description: '关闭过期的报告',
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
await closeOldReports();
|
||||||
|
}).addTo(app)
|
||||||
|
export const closeOldReports = async () => {
|
||||||
const res = await cnb.issue.getList('kevisual/kevisual', {
|
const res = await cnb.issue.getList('kevisual/kevisual', {
|
||||||
state: 'open',
|
state: 'open',
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -80,10 +95,17 @@ const closeOldReports = async () => {
|
|||||||
});
|
});
|
||||||
const issues = res.data || [];
|
const issues = res.data || [];
|
||||||
const oneDayAgo = dayjs().subtract(1, 'day');
|
const oneDayAgo = dayjs().subtract(1, 'day');
|
||||||
|
let closedCount = 0;
|
||||||
for (const issue of issues) {
|
for (const issue of issues) {
|
||||||
const updatedAt = dayjs(issue.updated_at);
|
const updatedAt = dayjs(issue.updated_at);
|
||||||
if (updatedAt.isBefore(oneDayAgo)) {
|
if (updatedAt.isBefore(oneDayAgo)) {
|
||||||
await cnb.issue.updateIssue('kevisual/kevisual', issue.number, { state: 'closed', state_reason: 'done' });
|
const res = await cnb.issue.updateIssue('kevisual/kevisual', issue.number, { state: 'closed', state_reason: 'completed' });
|
||||||
|
if (res.code !== 200) {
|
||||||
|
console.error(`关闭 issue ${issue.number} 失败`, res);
|
||||||
|
} else {
|
||||||
|
closedCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log(`已处理 ${issues.length} 个报告,关闭了 ${closedCount} 个过期报告`);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { app, gitea, rootPath } from '../app'
|
import { app, gitea, rootPath, token } from '../app'
|
||||||
import { Repo } from './cnb';
|
import { Repo } from './cnb';
|
||||||
import { execSync } from 'node:child_process';
|
import { execSync } from 'node:child_process';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
@@ -8,6 +8,7 @@ import { useKey } from '@kevisual/context';
|
|||||||
app.route({
|
app.route({
|
||||||
path: 'repo',
|
path: 'repo',
|
||||||
key: 'sync',
|
key: 'sync',
|
||||||
|
middleware: ['auth'],
|
||||||
description: '同步仓库数据',
|
description: '同步仓库数据',
|
||||||
}).define(async (ctx) => {
|
}).define(async (ctx) => {
|
||||||
const res = await app.run({ path: 'cnb', key: 'list-today' });
|
const res = await app.run({ path: 'cnb', key: 'list-today' });
|
||||||
@@ -49,7 +50,16 @@ app.route({
|
|||||||
const sync = async (repo: Repo) => {
|
const sync = async (repo: Repo) => {
|
||||||
const cwd = path.join(rootPath, repo.name);
|
const cwd = path.join(rootPath, repo.name);
|
||||||
if (!fs.existsSync(cwd)) {
|
if (!fs.existsSync(cwd)) {
|
||||||
execSync(`git clone ${repo.web_url} ${cwd}`);
|
const webUrl = repo.web_url;
|
||||||
|
let cloneUrl: string;
|
||||||
|
if (webUrl.startsWith('http://')) {
|
||||||
|
cloneUrl = webUrl.replace('http://', `http://cnb:${token}@`);
|
||||||
|
} else if (webUrl.startsWith('https://')) {
|
||||||
|
cloneUrl = webUrl.replace('https://', `https://cnb:${token}@`);
|
||||||
|
} else {
|
||||||
|
cloneUrl = webUrl;
|
||||||
|
}
|
||||||
|
execSync(`git clone ${cloneUrl} ${cwd}`);
|
||||||
}
|
}
|
||||||
// 添加一个remote 叫做gitea的远程仓库,指向gitea的地址
|
// 添加一个remote 叫做gitea的远程仓库,指向gitea的地址
|
||||||
const remoteUrl = repo.giteaUrl!;
|
const remoteUrl = repo.giteaUrl!;
|
||||||
|
|||||||
Reference in New Issue
Block a user