chore: add Gitea push helper (Node/PowerShell)
This commit is contained in:
1 parent
22c1784bab
commit
67694183eb
1 file changed
+89
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* 创建/推送到 Gitea(默认 http://10.126.232.10:3000)。
|
||||
* 用法:
|
||||
* GITEA_TOKEN=<token> node scripts/push-to-gitea.mjs
|
||||
* 可选环境变量:GITEA_URL、GITEA_REPO、GITEA_PUBLIC=1
|
||||
* 令牌只从环境变量读取,不写入仓库文件;推送完成后 origin 会还原为不含凭据的 URL。
|
||||
*/
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
const base = (process.env.GITEA_URL || 'http://10.126.232.10:3000').replace(/\/+$/, '');
|
||||
const token = (process.env.GITEA_TOKEN || '').trim();
|
||||
const repo = process.env.GITEA_REPO || 'classhelper-island-refactor-prompt';
|
||||
const isPublic = process.env.GITEA_PUBLIC === '1';
|
||||
if (!token) {
|
||||
console.error('缺少环境变量 GITEA_TOKEN(Gitea 访问令牌)。');
|
||||
process.exit(2);
|
||||
}
|
||||
const headers = { Authorization: `token ${token}`, 'Content-Type': 'application/json', Accept: 'application/json' };
|
||||
|
||||
async function api(path, init = {}) {
|
||||
const res = await fetch(`${base}/api/v1${path}`, { ...init, headers, signal: AbortSignal.timeout(20000) });
|
||||
const text = await res.text();
|
||||
let data = null;
|
||||
try { data = text ? JSON.parse(text) : null; } catch { data = text; }
|
||||
return { res, data };
|
||||
}
|
||||
|
||||
function git(args, opts = {}) {
|
||||
return spawnSync('git', args, { stdio: 'inherit', ...opts });
|
||||
}
|
||||
|
||||
const main = async () => {
|
||||
console.log(`[1/4] 校验令牌:GET ${base}/api/v1/user`);
|
||||
const u = await api('/user');
|
||||
if (!u.res.ok || !u.data?.login) {
|
||||
throw new Error(`无法获取当前用户(HTTP ${u.res.status})。请检查 Gitea 地址、网络与令牌。`);
|
||||
}
|
||||
const login = u.data.login;
|
||||
console.log(` 当前用户:${login}`);
|
||||
|
||||
console.log(`[2/4] 创建仓库:${repo}(${isPublic ? '公开' : '私有'})`);
|
||||
const existing = await api(`/repos/${encodeURIComponent(login)}/${encodeURIComponent(repo)}`);
|
||||
if (existing.res.ok) {
|
||||
console.log(' 仓库已存在,直接推送。');
|
||||
} else if (existing.res.status !== 404) {
|
||||
console.log(` 仓库探测返回 HTTP ${existing.res.status},继续尝试创建。`);
|
||||
}
|
||||
if (!existing.res.ok) {
|
||||
const created = await api('/user/repos', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
name: repo,
|
||||
private: !isPublic,
|
||||
auto_init: false,
|
||||
description: 'ClassIsland / ClassHelper 灵动岛提示词套件(静态分析产物)',
|
||||
}),
|
||||
});
|
||||
if (created.res.ok) {
|
||||
console.log(` 已创建:${created.data.full_name}`);
|
||||
console.log(` 网页地址:${created.data.html_url}`);
|
||||
} else if (created.res.status === 409) {
|
||||
console.log(' 仓库已存在(409),继续推送。');
|
||||
} else {
|
||||
throw new Error(`创建仓库失败(HTTP ${created.res.status}):${JSON.stringify(created.data)}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[3/4] 推送 main 分支');
|
||||
const cleanUrl = `${base}/${login}/${repo}.git`;
|
||||
const scheme = base.split('://')[0];
|
||||
const host = base.split('://')[1];
|
||||
const authUrl = `${scheme}://${encodeURIComponent(login)}:${encodeURIComponent(token)}@${host}/${login}/${repo}.git`;
|
||||
git(['remote', 'remove', 'origin']);
|
||||
git(['remote', 'add', 'origin', authUrl]);
|
||||
try {
|
||||
const pushed = git(['push', '-u', 'origin', 'HEAD:main']);
|
||||
if (pushed.status !== 0) throw new Error(`git push 失败(exit ${pushed.status})`);
|
||||
} finally {
|
||||
git(['remote', 'set-url', 'origin', cleanUrl]);
|
||||
console.log(` 已将 origin 还原为不含凭据的地址:${cleanUrl}`);
|
||||
}
|
||||
console.log(`[4/4] 完成\n仓库:${cleanUrl}`);
|
||||
};
|
||||
|
||||
main().catch((e) => {
|
||||
console.error(`错误:${e.message}`);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in new issue
Block a user