Compare commits

...

2 Commits

Author SHA1 Message Date
f50f41530d deploy
Some checks failed
Build & Deploy KLZ Cables / build-and-deploy (push) Has been cancelled
2026-01-26 02:36:58 +01:00
f8274cad1b logs 2026-01-26 02:34:54 +01:00
3 changed files with 130 additions and 11 deletions

View File

@@ -39,9 +39,6 @@ jobs:
# docker push registry.infra.mintel.me/mintel/klz-cables.com:latest
- name: Deploy to production server
env:
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_PASS: ${{ secrets.REGISTRY_PASS }}
run: |
mkdir -p ~/.ssh
echo "${{ secrets.ALPHA_SSH_KEY }}" > ~/.ssh/id_ed25519
@@ -49,11 +46,11 @@ jobs:
ssh-keyscan -H alpha.mintel.me >> ~/.ssh/known_hosts 2>/dev/null
ssh -o StrictHostKeyChecking=accept-new deploy@alpha.mintel.me bash -c "'
ssh -o StrictHostKeyChecking=accept-new deploy@alpha.mintel.me "bash -s" << 'ENDSSH'
set -e
echo \"$REGISTRY_PASS\" | docker login registry.infra.mintel.me -u \"$REGISTRY_USER\" --password-stdin
echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin
cd /home/deploy/sites/klz-cables.com
docker compose pull
docker compose up -d --force-recreate --remove-orphans
docker image prune -f
'"
ENDSSH

View File

@@ -12,17 +12,62 @@ let singleton: AppServices | undefined;
export function getServerAppServices(): AppServices {
if (singleton) return singleton;
// Create logger first to log initialization
const logger = new PinoLoggerService('server');
// Log environment variables (safely masked)
const envLog = {
// Mask sensitive values - show only last 4 characters or '***' for empty
NEXT_PUBLIC_UMAMI_WEBSITE_ID: process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID
? `***${process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID.slice(-4)}`
: 'not set',
SENTRY_DSN: process.env.SENTRY_DSN
? `***${process.env.SENTRY_DSN.slice(-4)}`
: 'not set',
REDIS_URL: process.env.REDIS_URL
? `***${process.env.REDIS_URL.slice(-4)}`
: 'not set',
REDIS_KEY_PREFIX: process.env.REDIS_KEY_PREFIX ?? 'klz:',
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
NODE_ENV: process.env.NODE_ENV ?? 'not set',
// Safe to show - no sensitive data
NEXT_PUBLIC_BASE_URL: process.env.NEXT_PUBLIC_BASE_URL ?? 'not set',
};
logger.info('Initializing server application services', {
environment: envLog,
timestamp: new Date().toISOString(),
});
const umamiEnabled = Boolean(process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID);
const sentryEnabled = Boolean(process.env.SENTRY_DSN);
logger.info('Service configuration', {
umamiEnabled,
sentryEnabled,
redisEnabled: Boolean(process.env.REDIS_URL),
});
const analytics = umamiEnabled
? new UmamiAnalyticsService({ enabled: true })
: new NoopAnalyticsService();
if (umamiEnabled) {
logger.info('Umami analytics service initialized');
} else {
logger.info('Noop analytics service initialized (analytics disabled)');
}
const errors = sentryEnabled
? new GlitchtipErrorReportingService({ enabled: true })
: new NoopErrorReportingService();
if (sentryEnabled) {
logger.info('GlitchTip error reporting service initialized');
} else {
logger.info('Noop error reporting service initialized (error reporting disabled)');
}
const redisUrl = process.env.REDIS_URL;
const cache = redisUrl
? new RedisCacheService({
@@ -31,9 +76,23 @@ export function getServerAppServices(): AppServices {
})
: new MemoryCacheService();
const logger = new PinoLoggerService('server');
if (redisUrl) {
logger.info('Redis cache service initialized', {
keyPrefix: process.env.REDIS_KEY_PREFIX ?? 'klz:'
});
} else {
logger.info('Memory cache service initialized (Redis not configured)');
}
logger.info('Pino logger service initialized', {
name: 'server',
level: process.env.LOG_LEVEL ?? 'info',
});
singleton = new AppServices(analytics, errors, cache, logger);
logger.info('All application services initialized successfully');
return singleton;
}

View File

@@ -68,11 +68,56 @@ export function getAppServices(): AppServices {
// Return cached instance if available
if (singleton) return singleton;
// Create logger first to log initialization
const logger =
typeof window === 'undefined'
? new PinoLoggerService('server')
: new NoopLoggerService();
// Log environment variables (safely masked)
const envLog = {
// Mask sensitive values - show only last 4 characters or '***' for empty
NEXT_PUBLIC_UMAMI_WEBSITE_ID: process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID
? `***${process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID.slice(-4)}`
: 'not set',
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN
? `***${process.env.NEXT_PUBLIC_SENTRY_DSN.slice(-4)}`
: 'not set',
SENTRY_DSN: process.env.SENTRY_DSN
? `***${process.env.SENTRY_DSN.slice(-4)}`
: 'not set',
// Safe to show - no sensitive data
NEXT_PUBLIC_BASE_URL: process.env.NEXT_PUBLIC_BASE_URL ?? 'not set',
NODE_ENV: process.env.NODE_ENV ?? 'not set',
};
// Log initialization
if (typeof window === 'undefined') {
// Server-side
logger.info('Initializing server application services', {
environment: envLog,
timestamp: new Date().toISOString(),
});
} else {
// Client-side
logger.info('Initializing client application services', {
environment: envLog,
timestamp: new Date().toISOString(),
});
}
// Determine which services to enable based on environment variables
const umamiEnabled = Boolean(process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID);
const sentryClientEnabled = Boolean(process.env.NEXT_PUBLIC_SENTRY_DSN);
const sentryServerEnabled = Boolean(process.env.SENTRY_DSN);
logger.info('Service configuration', {
umamiEnabled,
sentryClientEnabled,
sentryServerEnabled,
isServer: typeof window === 'undefined',
});
// Create analytics service (Umami or no-op)
// Use dynamic import to avoid importing server-only code in client components
const analytics = umamiEnabled
@@ -82,6 +127,12 @@ export function getAppServices(): AppServices {
})()
: new NoopAnalyticsService();
if (umamiEnabled) {
logger.info('Umami analytics service initialized');
} else {
logger.info('Noop analytics service initialized (analytics disabled)');
}
// Create error reporting service (GlitchTip/Sentry or no-op)
// Server-side and client-side have separate DSNs
const errors =
@@ -93,17 +144,29 @@ export function getAppServices(): AppServices {
? new GlitchtipErrorReportingService({ enabled: true })
: new NoopErrorReportingService();
if (typeof window === 'undefined' && sentryServerEnabled) {
logger.info('GlitchTip error reporting service initialized (server)');
} else if (typeof window !== 'undefined' && sentryClientEnabled) {
logger.info('GlitchTip error reporting service initialized (client)');
} else {
logger.info('Noop error reporting service initialized (error reporting disabled)');
}
// IMPORTANT: This module is imported by client components.
// Do not import Node-only modules (like the `redis` client) here.
// Use [`getServerAppServices()`](lib/services/create-services.server.ts:1) on the server.
const cache = new MemoryCacheService();
logger.info('Memory cache service initialized');
const logger =
typeof window === 'undefined'
? new PinoLoggerService('server')
: new NoopLoggerService();
logger.info('Pino logger service initialized', {
name: typeof window === 'undefined' ? 'server' : 'client',
level: process.env.LOG_LEVEL ?? 'info',
});
// Create and cache the singleton
singleton = new AppServices(analytics, errors, cache, logger);
logger.info('All application services initialized successfully');
return singleton;
}