[add] 設定settings/actions/secrets
This commit is contained in:
301
run.php
Normal file
301
run.php
Normal file
@@ -0,0 +1,301 @@
|
||||
<?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("✅ 任務完成");
|
||||
Reference in New Issue
Block a user