90 lines
3.5 KiB
JavaScript
90 lines
3.5 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* 创建/推送到 Gitea(默认 http://210.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://210.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);
|
||
});
|