Phase 1: Add ESLint/Prettier config + baseline auto-fixes
This commit is contained in:
@@ -38,16 +38,16 @@ module.exports = function(ctx) {
|
||||
const templateImage = template.docker.image.split(':')[0];
|
||||
for (const container of containers) {
|
||||
const containerImage = container.Image.split(':')[0];
|
||||
if (containerImage === templateImage || containerImage.endsWith('/' + templateImage)) {
|
||||
if (containerImage === templateImage || containerImage.endsWith(`/${ templateImage}`)) {
|
||||
const ports = container.Ports.filter(p => p.PublicPort).map(p => ({
|
||||
hostPort: p.PublicPort, containerPort: p.PrivatePort, protocol: p.Type
|
||||
hostPort: p.PublicPort, containerPort: p.PrivatePort, protocol: p.Type,
|
||||
}));
|
||||
return {
|
||||
id: container.Id, shortId: container.Id.slice(0, 12),
|
||||
name: container.Names[0]?.replace(/^\//, '') || 'unknown',
|
||||
image: container.Image, status: container.Status, state: container.State,
|
||||
ports, primaryPort: ports.length > 0 ? ports[0].hostPort : null,
|
||||
labels: container.Labels || {}
|
||||
labels: container.Labels || {},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ module.exports = function(ctx) {
|
||||
'{{PORT}}': config.port || template.defaultPort,
|
||||
'{{MEDIA_PATH}}': mediaPaths[0] || '/media',
|
||||
'{{TIMEZONE}}': ctx.siteConfig.timezone || 'UTC',
|
||||
'{{GENERATED_SECRET}}': crypto.randomBytes(32).toString('hex')
|
||||
'{{GENERATED_SECRET}}': crypto.randomBytes(32).toString('hex'),
|
||||
};
|
||||
|
||||
function replaceInObject(obj) {
|
||||
@@ -117,7 +117,7 @@ module.exports = function(ctx) {
|
||||
const basePath = `/${config.subdomain}`;
|
||||
// Some apps need the full URL, not just the path
|
||||
if (['GF_SERVER_ROOT_URL', 'GITEA__server__ROOT_URL'].includes(template.urlBaseEnv)) {
|
||||
processed.docker.environment[template.urlBaseEnv] = ctx.buildServiceUrl(config.subdomain) + '/';
|
||||
processed.docker.environment[template.urlBaseEnv] = `${ctx.buildServiceUrl(config.subdomain) }/`;
|
||||
} else {
|
||||
processed.docker.environment[template.urlBaseEnv] = basePath;
|
||||
}
|
||||
@@ -137,7 +137,7 @@ module.exports = function(ctx) {
|
||||
config.mediaPath.split(',').map(p => p.trim()).filter(Boolean).forEach(p => allowedRoots.push(path.resolve(p)));
|
||||
}
|
||||
const isAllowed = allowedRoots.some(root =>
|
||||
normalizedHost === root || normalizedHost.startsWith(root + path.sep)
|
||||
normalizedHost === root || normalizedHost.startsWith(root + path.sep),
|
||||
);
|
||||
if (!isAllowed) {
|
||||
ctx.log.warn('deploy', 'Custom volume host path rejected', { hostPath: override.hostPath, allowed: allowedRoots });
|
||||
@@ -162,76 +162,76 @@ module.exports = function(ctx) {
|
||||
c += ` root * ${sitePath}\n\n`;
|
||||
|
||||
if (tailscaleOnly) {
|
||||
c += ` @blocked not remote_ip 100.64.0.0/10\n`;
|
||||
c += ` respond @blocked "Access denied. Tailscale connection required." 403\n\n`;
|
||||
c += ' @blocked not remote_ip 100.64.0.0/10\n';
|
||||
c += ' respond @blocked "Access denied. Tailscale connection required." 403\n\n';
|
||||
}
|
||||
|
||||
if (apiProxy) {
|
||||
c += ` handle /api/* {\n`;
|
||||
c += ' handle /api/* {\n';
|
||||
c += ` reverse_proxy ${apiProxy}\n`;
|
||||
c += ` }\n\n`;
|
||||
c += ' }\n\n';
|
||||
}
|
||||
|
||||
c += ` @crt path *.crt\n`;
|
||||
c += ` handle @crt {\n`;
|
||||
c += ` header Content-Type application/x-x509-ca-cert\n`;
|
||||
c += ` header Content-Disposition "attachment; filename=\\"{file}\\""\n`;
|
||||
c += ` header Cache-Control "public, max-age=86400"\n`;
|
||||
c += ` file_server\n`;
|
||||
c += ` }\n\n`;
|
||||
c += ` @der path *.der\n`;
|
||||
c += ` handle @der {\n`;
|
||||
c += ` header Content-Type application/x-x509-ca-cert\n`;
|
||||
c += ` header Content-Disposition "attachment; filename=\\"{file}\\""\n`;
|
||||
c += ` header Cache-Control "public, max-age=86400"\n`;
|
||||
c += ` file_server\n`;
|
||||
c += ` }\n\n`;
|
||||
c += ` @mobileconfig path *.mobileconfig\n`;
|
||||
c += ` handle @mobileconfig {\n`;
|
||||
c += ` header Content-Type application/x-apple-aspen-config\n`;
|
||||
c += ` header Content-Disposition "attachment; filename=\\"{file}\\""\n`;
|
||||
c += ` header Cache-Control "public, max-age=86400"\n`;
|
||||
c += ` file_server\n`;
|
||||
c += ` }\n\n`;
|
||||
c += ` @ps1 path *.ps1\n`;
|
||||
c += ` handle @ps1 {\n`;
|
||||
c += ` header Content-Type text/plain\n`;
|
||||
c += ` header Content-Disposition "attachment; filename=\\"{file}\\""\n`;
|
||||
c += ` file_server\n`;
|
||||
c += ` }\n\n`;
|
||||
c += ` @sh path *.sh\n`;
|
||||
c += ` handle @sh {\n`;
|
||||
c += ` header Content-Type text/x-shellscript\n`;
|
||||
c += ` header Content-Disposition "attachment; filename=\\"{file}\\""\n`;
|
||||
c += ` file_server\n`;
|
||||
c += ` }\n\n`;
|
||||
c += ` # Static site with SPA fallback\n`;
|
||||
c += ` handle {\n`;
|
||||
c += ` @notFile not file {path}\n`;
|
||||
c += ` rewrite @notFile /index.html\n`;
|
||||
c += ` file_server\n`;
|
||||
c += ` }\n\n`;
|
||||
c += ` # No cache for HTML\n`;
|
||||
c += ` @htmlfiles {\n`;
|
||||
c += ` path *.html\n`;
|
||||
c += ` path /\n`;
|
||||
c += ` }\n`;
|
||||
c += ` header @htmlfiles Cache-Control "no-store"\n`;
|
||||
c += ' @crt path *.crt\n';
|
||||
c += ' handle @crt {\n';
|
||||
c += ' header Content-Type application/x-x509-ca-cert\n';
|
||||
c += ' header Content-Disposition "attachment; filename=\\"{file}\\""\n';
|
||||
c += ' header Cache-Control "public, max-age=86400"\n';
|
||||
c += ' file_server\n';
|
||||
c += ' }\n\n';
|
||||
c += ' @der path *.der\n';
|
||||
c += ' handle @der {\n';
|
||||
c += ' header Content-Type application/x-x509-ca-cert\n';
|
||||
c += ' header Content-Disposition "attachment; filename=\\"{file}\\""\n';
|
||||
c += ' header Cache-Control "public, max-age=86400"\n';
|
||||
c += ' file_server\n';
|
||||
c += ' }\n\n';
|
||||
c += ' @mobileconfig path *.mobileconfig\n';
|
||||
c += ' handle @mobileconfig {\n';
|
||||
c += ' header Content-Type application/x-apple-aspen-config\n';
|
||||
c += ' header Content-Disposition "attachment; filename=\\"{file}\\""\n';
|
||||
c += ' header Cache-Control "public, max-age=86400"\n';
|
||||
c += ' file_server\n';
|
||||
c += ' }\n\n';
|
||||
c += ' @ps1 path *.ps1\n';
|
||||
c += ' handle @ps1 {\n';
|
||||
c += ' header Content-Type text/plain\n';
|
||||
c += ' header Content-Disposition "attachment; filename=\\"{file}\\""\n';
|
||||
c += ' file_server\n';
|
||||
c += ' }\n\n';
|
||||
c += ' @sh path *.sh\n';
|
||||
c += ' handle @sh {\n';
|
||||
c += ' header Content-Type text/x-shellscript\n';
|
||||
c += ' header Content-Disposition "attachment; filename=\\"{file}\\""\n';
|
||||
c += ' file_server\n';
|
||||
c += ' }\n\n';
|
||||
c += ' # Static site with SPA fallback\n';
|
||||
c += ' handle {\n';
|
||||
c += ' @notFile not file {path}\n';
|
||||
c += ' rewrite @notFile /index.html\n';
|
||||
c += ' file_server\n';
|
||||
c += ' }\n\n';
|
||||
c += ' # No cache for HTML\n';
|
||||
c += ' @htmlfiles {\n';
|
||||
c += ' path *.html\n';
|
||||
c += ' path /\n';
|
||||
c += ' }\n';
|
||||
c += ' header @htmlfiles Cache-Control "no-store"\n';
|
||||
return c;
|
||||
}
|
||||
|
||||
// HTTPS block
|
||||
let config = `${domain} {\n`;
|
||||
config += ` tls internal\n\n`;
|
||||
config += ' tls internal\n\n';
|
||||
config += siteBlockContent();
|
||||
config += `}`;
|
||||
config += '}';
|
||||
|
||||
// HTTP companion block for devices that haven't trusted the CA yet
|
||||
if (httpAccess) {
|
||||
config += `\n\n# HTTP access for first-time certificate installation\n`;
|
||||
config += '\n\n# HTTP access for first-time certificate installation\n';
|
||||
config += `http://${domain} {\n`;
|
||||
config += siteBlockContent();
|
||||
config += `}`;
|
||||
config += '}';
|
||||
}
|
||||
|
||||
return config;
|
||||
@@ -254,7 +254,7 @@ module.exports = function(ctx) {
|
||||
} else if (healthPath && port && httpCheckFailed < 5) {
|
||||
try {
|
||||
const response = await ctx.fetchT(`http://localhost:${port}${healthPath}`, {
|
||||
signal: AbortSignal.timeout(3000), redirect: 'manual'
|
||||
signal: AbortSignal.timeout(3000), redirect: 'manual',
|
||||
});
|
||||
if (response.ok || (response.status >= 300 && response.status < 400)) {
|
||||
ctx.log.info('docker', 'Health check passed', { containerId, status: response.status });
|
||||
@@ -290,7 +290,7 @@ module.exports = function(ctx) {
|
||||
await ctx.caddy.reload(existing);
|
||||
return;
|
||||
}
|
||||
const result = await ctx.caddy.modify(c => c + `\n${config}\n`);
|
||||
const result = await ctx.caddy.modify(c => `${c }\n${config}\n`);
|
||||
if (!result.success) throw new Error(`[DC-303] Failed to add Caddy config for ${domain}: ${result.error}`);
|
||||
await ctx.caddy.verifySite(domain);
|
||||
}
|
||||
@@ -405,6 +405,6 @@ module.exports = function(ctx) {
|
||||
removeSubpathConfig,
|
||||
ensureMainDomainBlock,
|
||||
RESERVED_SUBPATHS,
|
||||
generateStaticSiteConfig
|
||||
generateStaticSiteConfig,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user