GitHub(nextgroup2706/ken_nogi)は今後使わず自社Gitea運用に切替え。 NodeSrvは旧リポジトリの履歴を破棄しファイルのみ統合(Dokploy用サービスアカウントは 別途mygit-admin/NodeSrv.gitに履歴あり)。notepmエクスポート(12GB)とPleasanter インストーラzip(208MB)はサイズが大きいため.gitignoreで除外。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
131 lines
5.7 KiB
JavaScript
131 lines
5.7 KiB
JavaScript
/**
|
||
* apply-desired-config-full.js
|
||
* ------------------------------------------------------------
|
||
* この環境では updatesitesettings(部分更新)がHTTP 200を返しても実際には
|
||
* 反映されないことを確認済みのため、Scripts/Styles/ServerScripts/Processesの
|
||
* 反映には常にこちらを使う。
|
||
* ClaudePleasanter直下に置く共通実装。全プロジェクトの薄いラッパーから require される。
|
||
*
|
||
* build-desired-config.js が生成した desired_config.json の
|
||
* Scripts/Styles/ServerScripts/Processes を、現在のサイト全体(getsite)に
|
||
* 上書きマージし、updatesite(全体更新)で送信する。
|
||
* Columns/GridColumns/Permissions等、それ以外のSiteSettings・Title等は
|
||
* 現状のまま一切変更しない。
|
||
*
|
||
* 使い方:
|
||
* node build-desired-config.js site-{SiteId}_{サイト名} … 先にこちらを実行
|
||
* node apply-desired-config-full.js … 差分表示のみ(送信なし)
|
||
* node apply-desired-config-full.js --execute … 上記に加えて実際に送信する
|
||
* ------------------------------------------------------------
|
||
*/
|
||
|
||
const fs = require("fs");
|
||
const path = require("path");
|
||
const { findSiteDir, newModifyDir, latestModifyDir } = require("./site-paths");
|
||
const { resolveProjectRoot, loadServerConfig, loadSiteId } = require("./resolve-project");
|
||
|
||
const { baseDir, env } = resolveProjectRoot();
|
||
const execute = process.argv.includes("--execute");
|
||
|
||
function loadJson(p) {
|
||
return JSON.parse(fs.readFileSync(p, "utf-8"));
|
||
}
|
||
|
||
function maskApiKey(key) {
|
||
if (!key) return key;
|
||
return key.length > 8 ? key.slice(0, 4) + "****" + key.slice(-4) : "****";
|
||
}
|
||
|
||
function timestamp() {
|
||
return new Date().toISOString().replace(/[:.]/g, "-");
|
||
}
|
||
|
||
function diffList(curList, desList, key) {
|
||
(curList || []).forEach((c) => {
|
||
const d = (desList || []).find((x) => x.Id === c.Id);
|
||
const same = d && JSON.stringify(d) === JSON.stringify(c);
|
||
console.log(` ${key} Id:${c.Id} (${c.Title || c.Name || ""}) -> 変更${!same}`);
|
||
});
|
||
}
|
||
|
||
const config = loadServerConfig(env);
|
||
const desired = loadJson(path.join(baseDir, "desired_config.json"));
|
||
const SITE_ID = desired.SiteId || loadSiteId(baseDir);
|
||
const siteDir = findSiteDir(path.join(baseDir, "configs", env), SITE_ID);
|
||
|
||
(async () => {
|
||
console.log("[INFO] 現在のサイト情報を取得しています...");
|
||
const getUrl = `${config.BaseUrl.replace(/\/+$/, "")}/api/items/${SITE_ID}/getsite`;
|
||
const getRes = await fetch(getUrl, {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify({ ApiVersion: config.ApiVersion || "1.1", ApiKey: config.ApiKey }),
|
||
});
|
||
const getJson = await getRes.json();
|
||
if (getJson.StatusCode !== 200) {
|
||
console.error("[エラー] getsiteに失敗しました:", JSON.stringify(getJson).slice(0, 500));
|
||
process.exit(1);
|
||
}
|
||
const data = getJson.Response.Data;
|
||
console.log(`[OK] 取得しました(現在のVer: ${data.Ver}, UpdatedTime: ${data.UpdatedTime})`);
|
||
|
||
const siteSettings = JSON.parse(JSON.stringify(data.SiteSettings));
|
||
|
||
console.log("========================================");
|
||
console.log(` Scripts/Styles/ServerScripts/Processes 差し替え(updatesite全体更新)${execute ? "(実行)" : "(プレビューのみ)"}`);
|
||
console.log("========================================");
|
||
console.log(`Env: ${env}`);
|
||
console.log("--- Scripts ---");
|
||
diffList(siteSettings.Scripts, desired.SiteSettings.Scripts, "Script");
|
||
console.log("--- Styles ---");
|
||
diffList(siteSettings.Styles, desired.SiteSettings.Styles, "Style");
|
||
console.log("--- ServerScripts ---");
|
||
diffList(siteSettings.ServerScripts, desired.SiteSettings.ServerScripts, "ServerScript");
|
||
console.log("他のSiteSettings(Columns/GridColumns等)・Permissions・Title等は一切変更しません。");
|
||
|
||
siteSettings.Scripts = desired.SiteSettings.Scripts;
|
||
siteSettings.Styles = desired.SiteSettings.Styles;
|
||
siteSettings.ServerScripts = desired.SiteSettings.ServerScripts;
|
||
siteSettings.Processes = desired.SiteSettings.Processes;
|
||
|
||
const body = {
|
||
ApiVersion: config.ApiVersion || "1.1",
|
||
ApiKey: config.ApiKey,
|
||
SiteId: SITE_ID,
|
||
Title: data.Title,
|
||
ReferenceType: data.ReferenceType,
|
||
ParentId: data.ParentId,
|
||
InheritPermission: data.InheritPermission,
|
||
Permissions: data.Permissions,
|
||
SiteSettings: siteSettings,
|
||
};
|
||
|
||
const modifyDir = latestModifyDir(siteDir) || newModifyDir(siteDir, "desired-config-full-update");
|
||
const ts = timestamp();
|
||
const maskedBody = { ...body, ApiKey: maskApiKey(body.ApiKey) };
|
||
const previewPath = path.join(modifyDir, `site-${SITE_ID}_full_update_preview_${ts}.json`);
|
||
fs.writeFileSync(previewPath, JSON.stringify(maskedBody, null, 2), "utf-8");
|
||
console.log(`\n[OK] 送信予定内容を保存しました: ${previewPath}`);
|
||
|
||
if (!execute) {
|
||
console.log("\n[注意] --execute が指定されていないため、送信は行っていません。");
|
||
console.log("内容を確認の上、問題なければ次を実行してください: node apply-desired-config-full.js --execute");
|
||
process.exit(0);
|
||
}
|
||
|
||
console.log("\n実際に送信します(updatesite)...");
|
||
const url = `${config.BaseUrl.replace(/\/+$/, "")}/api/items/${SITE_ID}/updatesite`;
|
||
const res = await fetch(url, {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
});
|
||
const text = await res.text();
|
||
const resultOutPath = path.join(modifyDir, `site-${SITE_ID}_full_update_result_${ts}.json`);
|
||
fs.writeFileSync(resultOutPath, text, "utf-8");
|
||
|
||
console.log(`HTTP ${res.status} ${res.statusText}`);
|
||
console.log(`[OK] 応答を保存しました: ${resultOutPath}`);
|
||
console.log(text);
|
||
})();
|