Files
UFW-AbuseIPDB-Reporter/scripts/services/updates.js
T

92 lines
2.8 KiB
JavaScript

const simpleGit = require('simple-git');
const semver = require('semver');
const { CronJob } = require('cron');
const fs = require('node:fs');
const path = require('node:path');
const restartApp = require('./restartApp.js');
const logger = require('../logger.js');
const { SERVER_ID, AUTO_UPDATE_SCHEDULE, EXTENDED_LOGS } = require('../../config.js').MAIN;
const git = simpleGit();
const pkgPath = path.resolve(__dirname, '../../package.json');
const LOCK_FILE = path.resolve(__dirname, '../../.git/index.lock');
const STALE_LOCK_THRESHOLD = 60_000;
const getLocalVersion = () => {
delete require.cache[require.resolve(pkgPath)];
return require(pkgPath).version;
};
const cleanStaleLock = () => {
try {
const stat = fs.statSync(LOCK_FILE);
if (Date.now() - stat.mtimeMs > STALE_LOCK_THRESHOLD) {
fs.unlinkSync(LOCK_FILE);
logger.warn('Removed stale .git/index.lock file', { discord: true });
}
} catch (err) {
if (err.code !== 'ENOENT') logger.error(`Failed to check/remove index.lock: ${err.message}`);
}
};
const pull = async () => {
try {
if (SERVER_ID !== 'development') {
if (EXTENDED_LOGS) logger.info('Resetting local repository to HEAD (--hard)...');
await git.reset(['--hard']);
}
logger.info('Pulling the repository and the required submodule...');
// Get submodule status before update
const submoduleBefore = await git.raw(['submodule', 'status']);
// Pull main repo and update submodules
const pullResult = await git.pull();
await git.submoduleUpdate(['--init', '--recursive', '--remote', '--merge']);
// Get submodule status after update
const submoduleAfter = await git.raw(['submodule', 'status']);
const submoduleChanged = submoduleBefore !== submoduleAfter;
const { changes, insertions, deletions } = pullResult.summary;
const mainRepoChanged = changes > 0 || insertions > 0 || deletions > 0;
const hasChanges = mainRepoChanged || submoduleChanged;
if (hasChanges) {
const parts = [];
if (mainRepoChanged) parts.push(`Main repo - Changes: ${changes}; Insertions: ${insertions}; Deletions: ${deletions};`);
if (submoduleChanged) parts.push('Submodule updated.');
logger.success(`Updates pulled successfully! ${parts.join(' ')}`, { discord: true });
} else {
logger.info('No new updates detected');
}
return hasChanges;
} catch (err) {
logger.error(err.stack);
return null;
}
};
const pullAndRestart = async () => {
try {
cleanStaleLock();
const oldVersion = getLocalVersion();
const hasChanges = await pull();
if (!hasChanges) return;
const newVersion = getLocalVersion();
if (semver.neq(newVersion, oldVersion)) {
logger.success(`Version changed: ${oldVersion} → ${newVersion}`, { discord: true });
}
await restartApp();
} catch (err) {
logger.error(err.stack);
}
};
new CronJob(AUTO_UPDATE_SCHEDULE, pullAndRestart, null, true);
module.exports = pullAndRestart;