GiteaRepoManager/index.html
2025-08-14 10:49:59 +08:00

296 lines
7.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8" />
<title>手動輸入組織,批次建立 Gitea 儲存庫與團隊</title>
<style>
body {
font-family: sans-serif;
}
#log {
white-space: pre-wrap;
background: #f0f0f0;
padding: 1em;
border-radius: 8px;
height: 100%;
overflow-y: auto;
margin-top: 1em;
}
label,
input {
font-size: 1rem;
}
input {
margin-left: 0.5em;
}
button {
margin-left: 1em;
}
</style>
</head>
<body>
<h2>
輸入組織名稱並從 JSON 建立儲存庫+設定團隊
<br />
PS.請先建好團隊(或使用下方按鈕批次建立)
</h2>
<label for="orgInput">組織名稱:</label>
<input type="text" id="orgInput" placeholder="請輸入組織名稱" />
<button onclick="loadAndCreateTeams()">創建團隊</button>
<button onclick="loadAndCreateRepos()">開始建立儲存庫</button>
<div id="log"></div>
<script>
const accessToken = "96ed6b6d33931b122c7f12f94153594be0d75b32";
const proxy = "https://cors-anywhere.bir840124.workers.dev/?url=";
const giteaAPIBase = "https://git.catan.com.tw/api/v1";
const logBox = document.getElementById("log");
function log(message) {
logBox.textContent += message + "\n";
logBox.scrollTop = logBox.scrollHeight;
}
// 建立儲存庫功能
async function loadAndCreateRepos() {
logBox.textContent = "";
const orgInput = document.getElementById("orgInput").value.trim();
if (!orgInput) {
alert("請輸入組織名稱");
return;
}
log(`✅ 開始建立儲存庫:${orgInput}`);
try {
const res = await fetch("repos.json");
const repoList = await res.json();
for (const repo of repoList) {
repo.org = orgInput;
await createRepoWithSettings(repo);
}
log("✅ 所有儲存庫處理完成!");
} catch (err) {
log("❌ 讀取 repos.json 失敗:" + err.message);
}
}
async function repoExists(org, repoName) {
const url = `${giteaAPIBase}/orgs/${org}/repos`;
const res = await fetch(proxy + url, {
headers: { "Authorization": `token ${accessToken}` }
});
if (!res.ok) {
throw new Error(`查詢儲存庫失敗,狀態碼:${res.status}`);
}
const repos = await res.json();
return repos.some(r => r.name === repoName);
}
async function createRepoWithSettings(repo) {
if (await repoExists(repo.org, repo.name)) {
log(`⚠️ 儲存庫已存在,略過建立:${repo.org}/${repo.name}`);
return;
}
const createUrl = `${giteaAPIBase}/orgs/${repo.org}/repos`;
const payload = {
name: repo.name,
description: repo.description || "",
default_branch: repo.default_branch || "master",
private: false,
auto_init: true
};
try {
const response = await fetch(proxy + createUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `token ${accessToken}`
},
body: JSON.stringify(payload)
});
const data = await response.json();
if (response.ok) {
log(`✅ 建立儲存庫:${repo.org}/${repo.name}`);
if (repo.teams?.length > 0) {
for (const team of repo.teams) {
await addTeamToRepo(repo.org, repo.name, team);
}
}
// 新增:建立 Issue
if (repo.issue) {
await createIssue(repo.org, repo.name, repo.issue);
}
} else {
log(`⚠️ 建立失敗:${repo.org}/${repo.name} - ${data.message}`);
}
} catch (err) {
log(`❌ 建立錯誤:${repo.org}/${repo.name} - ${err.message}`);
}
}
async function createIssue(org, repoName, issue) {
const url = `${giteaAPIBase}/repos/${org}/${repoName}/issues`;
const payload = {
title: issue.title || "",
body: issue.content || ""
};
try {
const res = await fetch(proxy + url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `token ${accessToken}`
},
body: JSON.stringify(payload)
});
if (res.ok) {
log(`📌 已建立 Issue${issue.title}`);
} else {
const data = await res.json();
log(`⚠️ 建立 Issue 失敗:${data.message || res.statusText}`);
}
} catch (err) {
log(`❌ 建立 Issue 錯誤:${err.message}`);
}
}
async function addTeamToRepo(org, repo, teamName) {
const teamsURL = `${giteaAPIBase}/orgs/${org}/teams`;
const teamRes = await fetch(proxy + teamsURL, {
headers: { "Authorization": `token ${accessToken}` }
});
const teams = await teamRes.json();
const targetTeam = teams.find(t => t.name === teamName);
if (!targetTeam) {
log(`⚠️ 找不到團隊:${teamName}`);
return;
}
const url = `${giteaAPIBase}/teams/${targetTeam.id}/repos/${org}/${repo}`;
const res = await fetch(proxy + url, {
method: "PUT",
headers: { "Authorization": `token ${accessToken}` }
});
if (res.ok) {
log(`👥 加入團隊:${teamName}`);
} else {
log(`⚠️ 加團隊失敗:${teamName}`);
}
}
// 創建團隊功能
async function loadAndCreateTeams() {
logBox.textContent = "";
const orgInput = document.getElementById("orgInput").value.trim();
if (!orgInput) {
alert("請輸入組織名稱");
return;
}
log(`✅ 開始建立團隊:${orgInput}`);
try {
const res = await fetch("teams.json");
const teamList = await res.json();
for (const team of teamList) {
await createTeam(orgInput, team);
}
log("✅ 所有團隊建立完成!");
} catch (err) {
log("❌ 讀取 teams.json 失敗:" + err.message);
}
}
async function createTeam(org, team) {
const url = `${giteaAPIBase}/orgs/${org}/teams`;
const payload = {
name: team.name,
description: team.description || "",
permission: "none",
units: team.units || [],
units_map: team.units_map || {},
can_create_org_repo: false,
includes_all_repositories: false
};
try {
const response = await fetch(proxy + url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `token ${accessToken}`
},
body: JSON.stringify(payload)
});
const data = await response.json();
if (response.ok) {
log(`✅ 團隊建立成功:${team.name}`);
if (team.members?.length > 0) {
for (const username of team.members) {
await addMemberToTeam(data.id, username);
}
}
} else if (data.message?.includes("team already exists")) {
log(`⚠️ 團隊已存在,略過:${team.name}`);
} else {
log(`⚠️ 建立團隊失敗:${team.name} - ${data.message}`);
}
} catch (err) {
log(`❌ 團隊建立錯誤:${team.name} - ${err.message}`);
}
}
async function addMemberToTeam(teamId, username) {
const url = `${giteaAPIBase}/teams/${teamId}/members/${username}`;
try {
const res = await fetch(proxy + url, {
method: "PUT",
headers: { "Authorization": `token ${accessToken}` }
});
if (res.ok) {
log(`👤 新增成員:${username}`);
} else {
const data = await res.json();
log(`⚠️ 新增成員失敗:${username} - ${data.message || res.statusText}`);
}
} catch (err) {
log(`❌ 新增成員錯誤:${username} - ${err.message}`);
}
}
async function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
</script>
</body>
</html>