302 lines
11 KiB
PHP
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.

<?php
// run.php
require 'vendor/autoload.php';
use Google\Client;
use Google\Service\Sheets;
$GITEA_URL = 'https://git.catan.com.tw/api/v1';
$GITEA_TOKEN = '96ed6b6d33931b122c7f12f94153594be0d75b32';
$SERVICE_KEY = __DIR__ . '/google-service-key.json';
$SHEET_ID = '1e-8Cj3Szkb-P0lTKQTeeaS_wI4S7KLS4wyzf5PjNyHQ';
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
function logMsg($msg) {
echo "data: $msg\n\n";
@ob_flush();
flush();
}
function getExcelValue($excelRef, $orgInput) {
global $SERVICE_KEY, $SHEET_ID;
if (!preg_match('/^excel:(\d+):\$(\w)$/', $excelRef, $m)) return null;
$gid = $m[1];
$targetCol = strtoupper($m[2]);
$colIndex = ord($targetCol) - 65;
try {
$client = new Client();
$client->setAuthConfig($SERVICE_KEY);
$client->addScope(\Google\Service\Sheets::SPREADSHEETS_READONLY);
$service = new \Google\Service\Sheets($client);
$spreadsheet = $service->spreadsheets->get($SHEET_ID);
$sheetName = null;
foreach ($spreadsheet->getSheets() as $sheet) {
if ($sheet->getProperties()->getSheetId() === intval($gid)) {
$sheetName = $sheet->getProperties()->getTitle();
break;
}
}
if (!$sheetName) { logMsg("⚠️ 找不到 GID: $gid"); return null; }
$response = $service->spreadsheets_values->get($SHEET_ID, $sheetName);
$values = $response->getValues() ?? [];
$lastNonEmptyCol = []; // 保存每個欄位最後非空值
foreach ($values as $r => &$row) {
// 保證列長度至少到目標欄位
for ($c = 0; $c <= $colIndex; $c++) {
$cell = $row[$c] ?? '';
$cell = trim($cell);
if ($cell !== '') {
$lastNonEmptyCol[$c] = $cell;
} else if (isset($lastNonEmptyCol[$c])) {
$row[$c] = $lastNonEmptyCol[$c]; // 更新列
} else {
$row[$c] = ''; // 避免未設定
}
// logMsg("DEBUG row={$r} col={$c} value='{$row[$c]}'");
}
$cellOrg = $row[0] ?? '';
if ($cellOrg === $orgInput) {
$value = $row[$colIndex] ?? '';
// logMsg("DEBUG 找到 org='{$orgInput}',回傳 col={$colIndex} 值='{$value}'");
return $value;
}
}
unset($row);
logMsg("⚠️ Excel 找不到 org={$orgInput} 的資料 (sheet='{$sheetName}')");
return '';
} catch (\Exception $e) {
logMsg("⚠️ Excel 讀取錯誤: " . $e->getMessage());
return '';
}
}
function fetchJSON($url, $method='GET', $data=null) {
global $GITEA_TOKEN;
$ch = curl_init($url);
$headers = ["Content-Type: application/json"];
if ($GITEA_TOKEN) $headers[] = "Authorization: token $GITEA_TOKEN";
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if ($method === 'POST') curl_setopt($ch, CURLOPT_POST, true);
if ($method === 'PUT') curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
if ($method === 'PATCH') curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
if ($data) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$res = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return [$code, json_decode($res, true)];
}
function createTeams($org) {
global $GITEA_URL;
$teams = json_decode(file_get_contents('teams.json'), true) ?? [];
logMsg("🟢 開始執行 createTeams...");
// 先抓全部團隊
[$codeAll, $allTeams] = fetchJSON("$GITEA_URL/orgs/$org/teams", 'GET');
$allTeams = $allTeams ?? [];
foreach ($teams as $team) {
$foundTeam = null;
foreach ($allTeams as $t) {
if (strcasecmp($t['name'], $team['name']) === 0) {
$foundTeam = $t;
break;
}
}
if ($foundTeam) {
logMsg("🔄 團隊已存在,更新權限: {$team['name']}");
// 更新權限
fetchJSON("$GITEA_URL/teams/{$foundTeam['id']}", 'PATCH', [
'units_map' => $team['units_map'] ?? [],
'permission' => $team['permission'] ?? 'write'
]);
// 補齊成員
[$codeMembers, $resMembers] = fetchJSON("$GITEA_URL/teams/{$foundTeam['id']}/members", 'GET');
$existingMembers = array_column($resMembers ?? [], 'username');
foreach ($team['members'] ?? [] as $member) {
if (!in_array($member, $existingMembers)) {
[$codeAdd, $resAdd] = fetchJSON("$GITEA_URL/teams/{$foundTeam['id']}/members/$member", 'PUT');
if ($codeAdd === 204) {
logMsg("  ✅ 新增成員: $member");
} else {
logMsg("  ⚠️ 新增成員失敗: $member" . json_encode($resAdd, JSON_UNESCAPED_UNICODE));
}
}
}
} else {
logMsg(" 建立團隊: {$team['name']}");
[$codeCreate, $resCreate] = fetchJSON("$GITEA_URL/orgs/$org/teams", 'POST', [
'name' => $team['name'],
'units_map' => $team['units_map'] ?? [],
'permission' => $team['permission'] ?? 'write'
]);
if ($codeCreate === 201) {
$teamId = $resCreate['id'];
foreach ($team['members'] ?? [] as $member) {
[$codeAdd, $resAdd] = fetchJSON("$GITEA_URL/teams/$teamId/members/$member", 'PUT');
if ($codeAdd === 204) {
logMsg("  ✅ 新增成員: $member");
} else {
logMsg("  ⚠️ 新增成員失敗: $member" . json_encode($resAdd, JSON_UNESCAPED_UNICODE));
}
}
} else {
logMsg("⚠️ 建立團隊失敗: {$team['name']}" . json_encode($resCreate, JSON_UNESCAPED_UNICODE));
}
}
}
logMsg("✅ 所有團隊設定完成!");
}
function createRepos($org) {
global $GITEA_URL;
$repos = json_decode(file_get_contents('repos.json'), true) ?? [];
logMsg("🟢 開始執行 createRepos...");
// 先抓全部 repo避免重複建立
[$codeAll, $allRepos] = fetchJSON("$GITEA_URL/orgs/$org/repos");
$allRepos = $allRepos ?? [];
foreach ($repos as $repo) {
$repoExists = false;
foreach ($allRepos as $r) {
if ($r['name'] === $repo['name']) {
$repoExists = true;
break;
}
}
if ($repoExists) {
logMsg("⚠️ 儲存庫已存在,略過建立:{$repo['name']}");
continue;
}
$payload = [
'name' => $repo['name'],
'description' => $repo['description'] ?? '',
'default_branch' => $repo['default_branch'] ?? 'master',
'private' => false,
'auto_init' => true
];
[$codeCreate, $resCreate] = fetchJSON("$GITEA_URL/orgs/$org/repos", 'POST', $payload);
if ($codeCreate === 201) {
$repoName = $resCreate['name'];
logMsg("✅ 建立儲存庫:{$repoName}");
// 加入團隊
foreach ($repo['teams'] ?? [] as $teamName) {
[$codeTeams, $teamsList] = fetchJSON("$GITEA_URL/orgs/$org/teams");
$targetTeam = null;
foreach ($teamsList ?? [] as $t) {
if ($t['name'] === $teamName) {
$targetTeam = $t;
break;
}
}
if ($targetTeam) {
[$codeAdd, $resAdd] = fetchJSON("$GITEA_URL/teams/{$targetTeam['id']}/repos/$org/$repoName", 'PUT');
if (in_array($codeAdd, [200,204])) {
logMsg("  👥 已加入團隊:{$teamName}");
} else {
logMsg("  ⚠️ 加入團隊失敗:{$teamName}" . json_encode($resAdd, JSON_UNESCAPED_UNICODE));
}
} else {
logMsg("  ⚠️ 找不到團隊:{$teamName}");
}
}
// 建立 Issue
if (!empty($repo['issue'])) {
$issuePayload = [
'title' => $repo['issue']['title'] ?? '',
'body' => $repo['issue']['content'] ?? ''
];
[$codeIssue, $resIssue] = fetchJSON("$GITEA_URL/repos/$org/$repoName/issues", 'POST', $issuePayload);
if ($codeIssue === 201) logMsg("  📌 已建立 Issue{$issuePayload['title']}");
else logMsg("  ⚠️ 建立 Issue 失敗:{$issuePayload['title']}" . json_encode($resIssue, JSON_UNESCAPED_UNICODE));
}
} else {
logMsg("⚠️ 建立儲存庫失敗:{$repo['name']}" . json_encode($resCreate, JSON_UNESCAPED_UNICODE));
}
}
logMsg("✅ 所有儲存庫處理完成!");
}
function setActions($org) {
global $GITEA_URL;
$actions = json_decode(file_get_contents('actions_settings.json'), true) ?? [];
logMsg("🟢 開始執行 setActions...");
$projectSecrets = $actions['project_settings']['secrets'] ?? [];
logMsg("🔧 設定 project");
foreach($projectSecrets as $key=>$value) {
$finalValue = (is_string($value) && str_starts_with($value,'excel:'))
? getExcelValue($value,$org)
: $value;
if(trim($finalValue)==='') { logMsg("  ⚠️ 略過空值 Project Secret: $key"); continue; }
[$code,$res] = fetchJSON("$GITEA_URL/orgs/$org/actions/secrets/$key",'PUT',['data'=>$finalValue]);
if (in_array($code, [200,204,201])) logMsg("  ✅ Project Secret 設定成功: $key");
else logMsg("  ⚠️ Project Secret 設定失敗: $key".json_encode($res,JSON_UNESCAPED_UNICODE));
}
$reposArr = $actions['repos'] ?? [];
foreach($reposArr as $repo) {
$repoName = $repo['name'];
logMsg("🔧 設定 repo: $repoName");
$secrets = $repo['secrets'] ?? [];
foreach($secrets as $key=>$value) {
$finalValue = (is_string($value) && str_starts_with($value,'excel:'))
? getExcelValue($value,$org)
: $value;
if(trim($finalValue)==='') { logMsg("  ⚠️ 略過空值 Repo Secret: $key"); continue; }
[$code,$res] = fetchJSON("$GITEA_URL/repos/$org/$repoName/actions/secrets/$key",'PUT',['data'=>$finalValue]);
if (in_array($code, [200,204,201])) logMsg("  ✅ Repo Secret 設定成功: $key");
else logMsg("  ⚠️ Repo Secret 設定失敗: $key".json_encode($res,JSON_UNESCAPED_UNICODE));
}
}
logMsg("✅ 所有 Actions 設定完成!");
}
$org = $_GET['org'] ?? '';
$action = $_GET['action'] ?? '';
if (!$org) { logMsg("❌ 請輸入組織名稱"); exit; }
switch($action) {
case 'createTeams': createTeams($org); break;
case 'createRepos': createRepos($org); break;
case 'setActions': setActions($org); break;
default: logMsg("⚠️ 未知操作: $action"); break;
}
logMsg("✅ 任務完成");