env
All checks were successful
Build & Deploy KLZ Cables / build-and-deploy (push) Successful in 3m46s
All checks were successful
Build & Deploy KLZ Cables / build-and-deploy (push) Successful in 3m46s
This commit is contained in:
16
.env
16
.env
@@ -1,11 +1,10 @@
|
|||||||
# Application
|
# Application
|
||||||
NODE_ENV=production
|
NODE_ENV=production
|
||||||
NEXT_PUBLIC_BASE_URL=https://klz-cables.com
|
NEXT_PUBLIC_BASE_URL=https://klz-cables.com
|
||||||
|
UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
|
||||||
|
NEXT_PUBLIC_UMAMI_WEBSITE_ID=59a7db94-0100-4c7e-98ef-99f45b17f9c3
|
||||||
|
SENTRY_DSN=https://c10957d0182245b1a2a806ac2d34a197@errors.infra.mintel.me/1
|
||||||
LOG_LEVEL=info
|
LOG_LEVEL=info
|
||||||
PDF_DEBUG_EXCEL=0
|
|
||||||
PDF_LOCALE=
|
|
||||||
PDF_MATCH=
|
|
||||||
PDF_LIMIT=0
|
|
||||||
|
|
||||||
# WooCommerce & WordPress
|
# WooCommerce & WordPress
|
||||||
WOOCOMMERCE_URL=https://klz-cables.com
|
WOOCOMMERCE_URL=https://klz-cables.com
|
||||||
@@ -13,15 +12,8 @@ WOOCOMMERCE_CONSUMER_KEY=ck_38d97df86880e8fefbd54ab5cdf47a9c5a9e5b39
|
|||||||
WOOCOMMERCE_CONSUMER_SECRET=cs_d675ee2ac2ec7c22de84ae5451c07e42b1717759
|
WOOCOMMERCE_CONSUMER_SECRET=cs_d675ee2ac2ec7c22de84ae5451c07e42b1717759
|
||||||
WORDPRESS_APP_PASSWORD="DlJH 49dp fC3a Itc3 Sl7Z Wz0k"
|
WORDPRESS_APP_PASSWORD="DlJH 49dp fC3a Itc3 Sl7Z Wz0k"
|
||||||
|
|
||||||
# Umami Analytics
|
|
||||||
NEXT_PUBLIC_UMAMI_WEBSITE_ID=59a7db94-0100-4c7e-98ef-99f45b17f9c3
|
|
||||||
UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
|
|
||||||
|
|
||||||
# GlitchTip (Sentry protocol)
|
|
||||||
SENTRY_DSN=https://c10957d0182245b1a2a806ac2d34a197@errors.infra.mintel.me/1
|
|
||||||
|
|
||||||
# Redis Cache
|
# Redis Cache
|
||||||
REDIS_URL=
|
REDIS_URL=redis://redis:6379/2
|
||||||
REDIS_KEY_PREFIX=klz:
|
REDIS_KEY_PREFIX=klz:
|
||||||
|
|
||||||
# SMTP Configuration
|
# SMTP Configuration
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
echo "📦 Build Arguments:"
|
echo "📦 Build Arguments:"
|
||||||
echo " • NEXT_PUBLIC_UMAMI_WEBSITE_ID: ${{ secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID != '' && '***' || 'NOT SET' }}"
|
echo " • NEXT_PUBLIC_UMAMI_WEBSITE_ID: ${{ secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID != '' && '***' || 'NOT SET' }}"
|
||||||
|
echo " • NEXT_PUBLIC_UMAMI_SCRIPT_URL: ${{ secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL != '' && '***' || 'NOT SET' }}"
|
||||||
echo " • SENTRY_DSN: ${{ secrets.SENTRY_DSN != '' && '***' || 'NOT SET' }}"
|
echo " • SENTRY_DSN: ${{ secrets.SENTRY_DSN != '' && '***' || 'NOT SET' }}"
|
||||||
echo " • NEXT_PUBLIC_SENTRY_DSN: ${{ secrets.NEXT_PUBLIC_SENTRY_DSN != '' && '***' || 'NOT SET' }}"
|
|
||||||
echo " • NEXT_PUBLIC_BASE_URL: ${{ secrets.NEXT_PUBLIC_BASE_URL != '' && '***' || 'NOT SET' }}"
|
echo " • NEXT_PUBLIC_BASE_URL: ${{ secrets.NEXT_PUBLIC_BASE_URL != '' && '***' || 'NOT SET' }}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "⏱️ Build started at: $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
|
echo "⏱️ Build started at: $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
|
||||||
@@ -87,8 +87,8 @@ jobs:
|
|||||||
--pull \
|
--pull \
|
||||||
--platform linux/arm64 \
|
--platform linux/arm64 \
|
||||||
--build-arg NEXT_PUBLIC_UMAMI_WEBSITE_ID="${{ secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID }}" \
|
--build-arg NEXT_PUBLIC_UMAMI_WEBSITE_ID="${{ secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID }}" \
|
||||||
|
--build-arg NEXT_PUBLIC_UMAMI_SCRIPT_URL="${{ secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL }}" \
|
||||||
--build-arg SENTRY_DSN="${{ secrets.SENTRY_DSN }}" \
|
--build-arg SENTRY_DSN="${{ secrets.SENTRY_DSN }}" \
|
||||||
--build-arg NEXT_PUBLIC_SENTRY_DSN="${{ secrets.NEXT_PUBLIC_SENTRY_DSN }}" \
|
|
||||||
--build-arg NEXT_PUBLIC_BASE_URL="${{ secrets.NEXT_PUBLIC_BASE_URL }}" \
|
--build-arg NEXT_PUBLIC_BASE_URL="${{ secrets.NEXT_PUBLIC_BASE_URL }}" \
|
||||||
-t registry.infra.mintel.me/mintel/klz-cables.com:latest \
|
-t registry.infra.mintel.me/mintel/klz-cables.com:latest \
|
||||||
--push .
|
--push .
|
||||||
@@ -160,11 +160,13 @@ jobs:
|
|||||||
MAIL_RECIPIENTS='${{ secrets.MAIL_RECIPIENTS }}' \
|
MAIL_RECIPIENTS='${{ secrets.MAIL_RECIPIENTS }}' \
|
||||||
MAIL_USERNAME='${{ secrets.MAIL_USERNAME }}' \
|
MAIL_USERNAME='${{ secrets.MAIL_USERNAME }}' \
|
||||||
NEXT_PUBLIC_BASE_URL='${{ secrets.NEXT_PUBLIC_BASE_URL }}' \
|
NEXT_PUBLIC_BASE_URL='${{ secrets.NEXT_PUBLIC_BASE_URL }}' \
|
||||||
NEXT_PUBLIC_SENTRY_DSN='${{ secrets.NEXT_PUBLIC_SENTRY_DSN }}' \
|
|
||||||
NEXT_PUBLIC_UMAMI_WEBSITE_ID='${{ secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID }}' \
|
NEXT_PUBLIC_UMAMI_WEBSITE_ID='${{ secrets.NEXT_PUBLIC_UMAMI_WEBSITE_ID }}' \
|
||||||
|
NEXT_PUBLIC_UMAMI_SCRIPT_URL='${{ secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL }}' \
|
||||||
NODE_ENV='${{ secrets.NODE_ENV }}' \
|
NODE_ENV='${{ secrets.NODE_ENV }}' \
|
||||||
SENTRY_DSN='${{ secrets.SENTRY_DSN }}' \
|
SENTRY_DSN='${{ secrets.SENTRY_DSN }}' \
|
||||||
sudo -u deploy -H -E /home/deploy/deploy.sh"
|
REDIS_URL='${{ secrets.REDIS_URL }}' \
|
||||||
|
REDIS_KEY_PREFIX='${{ secrets.REDIS_KEY_PREFIX }}' \
|
||||||
|
/home/deploy/deploy.sh"
|
||||||
|
|
||||||
DEPLOY_EXIT_CODE=$?
|
DEPLOY_EXIT_CODE=$?
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -25,12 +25,11 @@ ENV NEXT_TELEMETRY_DISABLED=1
|
|||||||
ARG NEXT_PUBLIC_UMAMI_WEBSITE_ID
|
ARG NEXT_PUBLIC_UMAMI_WEBSITE_ID
|
||||||
ARG NEXT_PUBLIC_UMAMI_SCRIPT_URL
|
ARG NEXT_PUBLIC_UMAMI_SCRIPT_URL
|
||||||
ARG SENTRY_DSN
|
ARG SENTRY_DSN
|
||||||
ARG NEXT_PUBLIC_SENTRY_DSN
|
|
||||||
ARG NEXT_PUBLIC_BASE_URL
|
ARG NEXT_PUBLIC_BASE_URL
|
||||||
|
|
||||||
ENV NEXT_PUBLIC_UMAMI_WEBSITE_ID=$NEXT_PUBLIC_UMAMI_WEBSITE_ID
|
ENV NEXT_PUBLIC_UMAMI_WEBSITE_ID=$NEXT_PUBLIC_UMAMI_WEBSITE_ID
|
||||||
ENV NEXT_PUBLIC_UMAMI_SCRIPT_URL=$NEXT_PUBLIC_UMAMI_SCRIPT_URL
|
ENV NEXT_PUBLIC_UMAMI_SCRIPT_URL=$NEXT_PUBLIC_UMAMI_SCRIPT_URL
|
||||||
ENV SENTRY_DSN=$SENTRY_DSN
|
ENV SENTRY_DSN=$SENTRY_DSN
|
||||||
ENV NEXT_PUBLIC_SENTRY_DSN=$NEXT_PUBLIC_SENTRY_DSN
|
|
||||||
ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
|
ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
|
||||||
|
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|||||||
4
docker-compose.override.yml
Normal file
4
docker-compose.override.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
services:
|
||||||
|
app:
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
@@ -57,24 +57,19 @@ services:
|
|||||||
retries: 5
|
retries: 5
|
||||||
start_period: 30s
|
start_period: 30s
|
||||||
environment:
|
environment:
|
||||||
# Umami
|
- NODE_ENV=${NODE_ENV:-production}
|
||||||
|
- NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL:?NEXT_PUBLIC_BASE_URL is required}
|
||||||
- NEXT_PUBLIC_UMAMI_WEBSITE_ID=${NEXT_PUBLIC_UMAMI_WEBSITE_ID}
|
- NEXT_PUBLIC_UMAMI_WEBSITE_ID=${NEXT_PUBLIC_UMAMI_WEBSITE_ID}
|
||||||
- NEXT_PUBLIC_UMAMI_SCRIPT_URL=${NEXT_PUBLIC_UMAMI_SCRIPT_URL:-https://analytics.infra.mintel.me/script.js}
|
- NEXT_PUBLIC_UMAMI_SCRIPT_URL=${NEXT_PUBLIC_UMAMI_SCRIPT_URL}
|
||||||
# GlitchTip (Sentry protocol)
|
|
||||||
- SENTRY_DSN=${SENTRY_DSN}
|
- SENTRY_DSN=${SENTRY_DSN}
|
||||||
- NEXT_PUBLIC_SENTRY_DSN=${NEXT_PUBLIC_SENTRY_DSN}
|
|
||||||
# Redis (app-spezifischer DB-Index)
|
|
||||||
- REDIS_URL=${REDIS_URL:-redis://redis:6379/2}
|
|
||||||
- REDIS_KEY_PREFIX=${REDIS_KEY_PREFIX:-klz:}
|
|
||||||
# Mail
|
|
||||||
- MAIL_HOST=${MAIL_HOST}
|
- MAIL_HOST=${MAIL_HOST}
|
||||||
- MAIL_PORT=${MAIL_PORT}
|
- MAIL_PORT=${MAIL_PORT:-587}
|
||||||
- MAIL_USERNAME=${MAIL_USERNAME}
|
- MAIL_USERNAME=${MAIL_USERNAME}
|
||||||
- MAIL_PASSWORD=${MAIL_PASSWORD}
|
- MAIL_PASSWORD=${MAIL_PASSWORD}
|
||||||
- MAIL_FROM=${MAIL_FROM}
|
- MAIL_FROM=${MAIL_FROM}
|
||||||
- MAIL_RECIPIENTS=${MAIL_RECIPIENTS}
|
- MAIL_RECIPIENTS=${MAIL_RECIPIENTS}
|
||||||
# App
|
- REDIS_URL=${REDIS_URL}
|
||||||
- NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL}
|
- REDIS_KEY_PREFIX=${REDIS_KEY_PREFIX}
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
infra:
|
infra:
|
||||||
|
|||||||
@@ -111,16 +111,33 @@ Next.js App (port 3000)
|
|||||||
|
|
||||||
### Build-time (in Dockerfile/Workflow)
|
### Build-time (in Dockerfile/Workflow)
|
||||||
|
|
||||||
|
These variables are baked into the Docker image during the build process.
|
||||||
|
|
||||||
|
- `NEXT_PUBLIC_BASE_URL` (Required)
|
||||||
- `NEXT_PUBLIC_UMAMI_WEBSITE_ID`
|
- `NEXT_PUBLIC_UMAMI_WEBSITE_ID`
|
||||||
- `NEXT_PUBLIC_UMAMI_SCRIPT_URL`
|
- `NEXT_PUBLIC_UMAMI_SCRIPT_URL`
|
||||||
- `NEXT_PUBLIC_SENTRY_DSN`
|
- `SENTRY_DSN`
|
||||||
|
|
||||||
### Runtime (in docker-compose.yml)
|
### Runtime (in docker-compose.yml)
|
||||||
|
|
||||||
|
These variables are passed to the container at runtime.
|
||||||
|
|
||||||
|
- `NODE_ENV` (Defaults to `production`)
|
||||||
|
- `NEXT_PUBLIC_BASE_URL` (Must be passed again at runtime for server-side use)
|
||||||
- `SENTRY_DSN`
|
- `SENTRY_DSN`
|
||||||
|
- `MAIL_HOST`
|
||||||
|
- `MAIL_PORT`
|
||||||
|
- `MAIL_USERNAME`
|
||||||
|
- `MAIL_PASSWORD`
|
||||||
|
- `MAIL_FROM`
|
||||||
|
- `MAIL_RECIPIENTS`
|
||||||
- `REDIS_URL`
|
- `REDIS_URL`
|
||||||
- `REDIS_KEY_PREFIX`
|
- `REDIS_KEY_PREFIX`
|
||||||
|
|
||||||
|
### Local Development
|
||||||
|
|
||||||
|
For local development, use a `.env` file. The `docker-compose.override.yml` file automatically loads this file for the `app` service.
|
||||||
|
|
||||||
## Monitoring
|
## Monitoring
|
||||||
|
|
||||||
### Health Checks
|
### Health Checks
|
||||||
|
|||||||
@@ -12,20 +12,40 @@ const getEnv = (key: string, defaultValue?: string): string | undefined => {
|
|||||||
return (process.env as any)[key] || defaultValue;
|
return (process.env as any)[key] || defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof process === 'undefined') return defaultValue;
|
|
||||||
if (typeof process === 'undefined') return defaultValue;
|
if (typeof process === 'undefined') return defaultValue;
|
||||||
|
|
||||||
// In Docker/Production, variables are in process.env
|
// In Docker/Production, variables are in process.env
|
||||||
// In local development, they might be in .env
|
// In local development, they might be in .env
|
||||||
const value = process.env[key];
|
const value = process.env[key];
|
||||||
|
|
||||||
if (value !== undefined && value !== '') {
|
// Check for quoted values (common when passed via SSH/Docker)
|
||||||
return value;
|
if (typeof value === 'string') {
|
||||||
|
const trimmed = value.trim();
|
||||||
|
if ((trimmed.startsWith("'") && trimmed.endsWith("'")) ||
|
||||||
|
(trimmed.startsWith('"') && trimmed.endsWith('"'))) {
|
||||||
|
return trimmed.slice(1, -1);
|
||||||
|
}
|
||||||
|
if (trimmed !== '') return trimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isProduction = getEnv('NODE_ENV') === 'production';
|
||||||
|
|
||||||
|
// Required variables in production
|
||||||
|
if (isProduction && typeof window === 'undefined') {
|
||||||
|
const required = [
|
||||||
|
'NEXT_PUBLIC_BASE_URL',
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const key of required) {
|
||||||
|
if (!getEnv(key)) {
|
||||||
|
throw new Error(`Missing required environment variable: ${key}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
env: getEnv('NODE_ENV', 'development'),
|
env: getEnv('NODE_ENV', 'development'),
|
||||||
isProduction: getEnv('NODE_ENV') === 'production',
|
isProduction: getEnv('NODE_ENV') === 'production',
|
||||||
@@ -37,7 +57,7 @@ export const config = {
|
|||||||
analytics: {
|
analytics: {
|
||||||
umami: {
|
umami: {
|
||||||
websiteId: getEnv('NEXT_PUBLIC_UMAMI_WEBSITE_ID'),
|
websiteId: getEnv('NEXT_PUBLIC_UMAMI_WEBSITE_ID'),
|
||||||
scriptUrl: getEnv('UMAMI_SCRIPT_URL', 'https://analytics.infra.mintel.me/script.js'),
|
scriptUrl: getEnv('NEXT_PUBLIC_UMAMI_SCRIPT_URL', 'https://analytics.infra.mintel.me/script.js'),
|
||||||
// The proxied path used in the frontend
|
// The proxied path used in the frontend
|
||||||
proxyPath: '/stats/script.js',
|
proxyPath: '/stats/script.js',
|
||||||
enabled: Boolean(getEnv('NEXT_PUBLIC_UMAMI_WEBSITE_ID')),
|
enabled: Boolean(getEnv('NEXT_PUBLIC_UMAMI_WEBSITE_ID')),
|
||||||
@@ -74,16 +94,6 @@ export const config = {
|
|||||||
from: getEnv('MAIL_FROM'),
|
from: getEnv('MAIL_FROM'),
|
||||||
recipients: getEnv('MAIL_RECIPIENTS', '')?.split(',').filter(Boolean) || [],
|
recipients: getEnv('MAIL_RECIPIENTS', '')?.split(',').filter(Boolean) || [],
|
||||||
},
|
},
|
||||||
|
|
||||||
woocommerce: {
|
|
||||||
url: getEnv('WOOCOMMERCE_URL'),
|
|
||||||
consumerKey: getEnv('WOOCOMMERCE_CONSUMER_KEY'),
|
|
||||||
consumerSecret: getEnv('WOOCOMMERCE_CONSUMER_SECRET'),
|
|
||||||
},
|
|
||||||
|
|
||||||
wordpress: {
|
|
||||||
appPassword: getEnv('WORDPRESS_APP_PASSWORD'),
|
|
||||||
},
|
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ const nextConfig = {
|
|||||||
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
|
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
|
||||||
},
|
},
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
const umamiUrl = (process.env.UMAMI_SCRIPT_URL || 'https://analytics.infra.mintel.me').replace('/script.js', '');
|
const umamiUrl = (process.env.NEXT_PUBLIC_UMAMI_SCRIPT_URL || 'https://analytics.infra.mintel.me').replace('/script.js', '');
|
||||||
const glitchtipUrl = process.env.SENTRY_DSN
|
const glitchtipUrl = process.env.SENTRY_DSN
|
||||||
? new URL(process.env.SENTRY_DSN).origin
|
? new URL(process.env.SENTRY_DSN).origin
|
||||||
: 'https://errors.infra.mintel.me';
|
: 'https://errors.infra.mintel.me';
|
||||||
|
|||||||
Reference in New Issue
Block a user