Files
kitchen-agent/updater.js
2025-10-23 19:02:56 -04:00

95 lines
3.2 KiB
JavaScript

const path = require('path');
const os = require('os');
const fetch = require('node-fetch');
const {
GITEA_TOKEN,
REPO_URL = 'https://repo.cloud.thinklink.ai/thinklink/kitchen-agent.git',
REPO_BRANCH = 'main',
PM2_APP = 'kitchen-agent'
} = process.env;
const repositoryNormalized = REPO_URL.endsWith('.git') ? REPO_URL : `${REPO_URL}.git`;
const updaterOptions = {
repository: repositoryNormalized,
branch: REPO_BRANCH,
token: GITEA_TOKEN,
// place updates in OS temp dir to avoid permission/self-copy issues
tempLocation: path.join(os.tmpdir(), 'kitchen-agent-updates'),
// only include files that actually exist in the upstream repo; module uses unlinkSync
ignoreFiles: ['.env'],
executeOnComplete: process.platform === 'win32'
? `IF EXIST package-lock.json (npm ci --omit=dev) ELSE (npm install --omit=dev) & pm2 reload ${PM2_APP}`
: `[ -f package-lock.json ] && npm ci --omit=dev || npm install --omit=dev; pm2 reload ${PM2_APP}`,
exitOnComplete: false
};
let updaterInstance = null;
async function getUpdater() {
if (updaterInstance) { return updaterInstance; }
const mod = await import('auto-git-update');
const AutoGitUpdate = mod && mod.default ? mod.default : mod;
updaterInstance = new AutoGitUpdate(updaterOptions);
return updaterInstance;
}
async function checkAndUpdate() {
try {
const updater = await getUpdater();
const isGithub = /github\.com/i.test(repositoryNormalized);
let needsUpdate = false;
if (!isGithub) {
// Use Gitea-aware version check to avoid library's GitHub-only path
const localVersion = (() => {
try { return require('./package.json').version || null; } catch (_) { return null; }
})();
const base = repositoryNormalized.replace(/\.git$/i, '');
const rawUrl = `${base}/raw/branch/${REPO_BRANCH}/package.json`;
async function tryFetch(url) {
const headers = GITEA_TOKEN ? { Authorization: `token ${GITEA_TOKEN}` } : undefined;
const r = await fetch(url, { headers });
if (r.ok) return r.json();
return null;
}
let remotePkg = await tryFetch(rawUrl);
if (!remotePkg && GITEA_TOKEN) {
remotePkg = (await tryFetch(`${rawUrl}?token=${GITEA_TOKEN}`))
|| (await tryFetch(`${rawUrl}?access_token=${GITEA_TOKEN}`));
}
const remoteVersion = remotePkg && remotePkg.version ? String(remotePkg.version) : null;
if (!remoteVersion) {
console.error('[auto-update] Unable to read remote version from Gitea raw endpoint');
} else if (!localVersion || remoteVersion !== String(localVersion)) {
console.log(`[auto-update] Update available: ${localVersion || 'unknown'} -> ${remoteVersion}`);
needsUpdate = true;
}
if (needsUpdate) {
await updater.forceUpdate();
} else {
console.log('[auto-update] Up to date');
}
return;
}
// GitHub-based repos: use library's compareVersions, then forceUpdate to avoid double compare
const res = await updater.compareVersions();
if (res && res.upToDate === false) {
await updater.forceUpdate();
} else {
console.log('[auto-update] Up to date');
}
} catch (err) {
console.error('[auto-update] failed:', err);
}
}
module.exports = { checkAndUpdate };