|
|
|
@@ -13,6 +13,8 @@
|
|
|
|
|
* proddash.json in the data directory (this machine's overrides), or env vars:
|
|
|
|
|
* PORT (default: value in proddash.json, else 24500)
|
|
|
|
|
* PRODDASH_PASSCODE (overrides adminPasscode in proddash.json)
|
|
|
|
|
* PRODDASH_FORGE (overrides `forge`: "github", or a Gitea/Forgejo base
|
|
|
|
|
* URL such as http://10.3.8.90:3000)
|
|
|
|
|
* PRODDASH_DATA_DIR (where module config + layouts are kept; see below)
|
|
|
|
|
*/
|
|
|
|
|
'use strict';
|
|
|
|
@@ -765,14 +767,52 @@ function parseRepoSetting(value, fallbackBranch) {
|
|
|
|
|
|
|
|
|
|
const REPO = parseRepoSetting(process.env.PRODDASH_REPO || shellConfig.repo, shellConfig.branch)
|
|
|
|
|
|| parseRepoSetting('michaelmcgary2008/ProdDash', 'main');
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Which server the code comes from. GitHub unless `forge` names another —
|
|
|
|
|
* give it a Gitea (or Forgejo) base URL, "http://10.3.8.90:3000", and updates
|
|
|
|
|
* and module installs come from there instead. The two hosts differ only in
|
|
|
|
|
* how an archive URL is spelled: the tarball itself is the same, pax header
|
|
|
|
|
* and commit sha included, so everything downstream is untouched.
|
|
|
|
|
*/
|
|
|
|
|
function parseForge(value) {
|
|
|
|
|
const s = String(value || '').trim().replace(/\/+$/, '');
|
|
|
|
|
if (!s || s.toLowerCase() === 'github') {
|
|
|
|
|
return { kind: 'github', base: 'https://github.com', archiveBase: 'https://codeload.github.com' };
|
|
|
|
|
}
|
|
|
|
|
if (!/^https?:\/\//i.test(s)) return null;
|
|
|
|
|
// A GitHub URL still means codeload for archives.
|
|
|
|
|
if (/^https?:\/\/(www\.)?github\.com$/i.test(s)) {
|
|
|
|
|
return { kind: 'github', base: s, archiveBase: 'https://codeload.github.com' };
|
|
|
|
|
}
|
|
|
|
|
return { kind: 'gitea', base: s, archiveBase: s };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FORGE = parseForge(process.env.PRODDASH_FORGE || shellConfig.forge) || parseForge('github');
|
|
|
|
|
/** Where branch archives come from; tests point this at a local mock. */
|
|
|
|
|
const ARCHIVE_BASE = String(process.env.PRODDASH_ARCHIVE_BASE || 'https://codeload.github.com').replace(/\/+$/, '');
|
|
|
|
|
const ARCHIVE_BASE = String(process.env.PRODDASH_ARCHIVE_BASE || FORGE.archiveBase).replace(/\/+$/, '');
|
|
|
|
|
const REMOTE_TTL_MS = 10 * 60 * 1000;
|
|
|
|
|
const REMOTE_CHECK_MS = 6 * 60 * 60 * 1000;
|
|
|
|
|
const MAX_ARCHIVE_BYTES = 80 * 1024 * 1024;
|
|
|
|
|
|
|
|
|
|
function tarballUrl() {
|
|
|
|
|
return `${ARCHIVE_BASE}/${REPO.owner}/${REPO.repo}/tar.gz/${encodeURIComponent(REPO.branch)}`;
|
|
|
|
|
const branch = encodeURIComponent(REPO.branch);
|
|
|
|
|
return FORGE.kind === 'gitea'
|
|
|
|
|
? `${ARCHIVE_BASE}/${REPO.owner}/${REPO.repo}/archive/${branch}.tar.gz`
|
|
|
|
|
: `${ARCHIVE_BASE}/${REPO.owner}/${REPO.repo}/tar.gz/${branch}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** The page a human should read to see what changed between two commits. */
|
|
|
|
|
function forgeCompareUrl(from, to) {
|
|
|
|
|
return `${FORGE.base}/${REPO.owner}/${REPO.repo}/compare/${from}...${to}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** The commit list for the branch we follow. */
|
|
|
|
|
function forgeCommitsUrl() {
|
|
|
|
|
const branch = encodeURIComponent(REPO.branch);
|
|
|
|
|
return FORGE.kind === 'gitea'
|
|
|
|
|
? `${FORGE.base}/${REPO.owner}/${REPO.repo}/commits/branch/${branch}`
|
|
|
|
|
: `${FORGE.base}/${REPO.owner}/${REPO.repo}/commits/${branch}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function httpError(status, message) {
|
|
|
|
@@ -929,11 +969,11 @@ function shellStatus() {
|
|
|
|
|
else if (local.branch !== REPO.branch) blocker = `this checkout is on branch "${local.branch}", not "${REPO.branch}"`;
|
|
|
|
|
else if (local.dirty) blocker = 'this checkout has local changes — commit or discard them first';
|
|
|
|
|
}
|
|
|
|
|
const gh = `https://github.com/${REPO.owner}/${REPO.repo}`;
|
|
|
|
|
return {
|
|
|
|
|
version: SHELL_VERSION,
|
|
|
|
|
repo: `${REPO.owner}/${REPO.repo}`,
|
|
|
|
|
branch: REPO.branch,
|
|
|
|
|
forge: FORGE.base,
|
|
|
|
|
local: { isGit: local.isGit, sha: local.sha, branch: local.branch, dirty: local.dirty },
|
|
|
|
|
remote: { version: remote.version, sha: remote.sha, checkedAt: remote.checkedAt, error: remote.error },
|
|
|
|
|
updateAvailable: versionBehind || commitsBehind,
|
|
|
|
@@ -941,8 +981,8 @@ function shellStatus() {
|
|
|
|
|
method: local.isGit ? 'git' : 'archive',
|
|
|
|
|
updateBlocker: blocker,
|
|
|
|
|
changesUrl: local.sha && remote.sha
|
|
|
|
|
? `${gh}/compare/${local.sha.slice(0, 12)}...${remote.sha.slice(0, 12)}`
|
|
|
|
|
: `${gh}/commits/${REPO.branch}`,
|
|
|
|
|
? forgeCompareUrl(local.sha.slice(0, 12), remote.sha.slice(0, 12))
|
|
|
|
|
: forgeCommitsUrl(),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1693,7 +1733,7 @@ server.on('listening', () => {
|
|
|
|
|
? ' Modules : ' + ids.map((id) => id + (isEnabled(id) ? '' : ' (disabled)') + (manifests.get(id).incompatible ? ' (needs newer ProdDash)' : '')).join(', ')
|
|
|
|
|
: ' Modules : none installed');
|
|
|
|
|
console.log(' Settings : ' + DATA_DIR + (DATA_DIR === REPO_CONFIG_DIR ? ' (inside the app folder)' : ''));
|
|
|
|
|
console.log(' Repo : ' + REPO.owner + '/' + REPO.repo + '@' + REPO.branch);
|
|
|
|
|
console.log(' Repo : ' + REPO.owner + '/' + REPO.repo + '@' + REPO.branch + ' (' + FORGE.base + ')');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// A restart hands the port over from the exiting ProdDash: wait for it.
|
|
|
|
|