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
|
||||
NODE_ENV=production
|
||||
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
|
||||
PDF_DEBUG_EXCEL=0
|
||||
PDF_LOCALE=
|
||||
PDF_MATCH=
|
||||
PDF_LIMIT=0
|
||||
|
||||
# WooCommerce & WordPress
|
||||
WOOCOMMERCE_URL=https://klz-cables.com
|
||||
@@ -13,15 +12,8 @@ WOOCOMMERCE_CONSUMER_KEY=ck_38d97df86880e8fefbd54ab5cdf47a9c5a9e5b39
|
||||
WOOCOMMERCE_CONSUMER_SECRET=cs_d675ee2ac2ec7c22de84ae5451c07e42b1717759
|
||||
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_URL=
|
||||
REDIS_URL=redis://redis:6379/2
|
||||
REDIS_KEY_PREFIX=klz:
|
||||
|
||||
# SMTP Configuration
|
||||
|
||||
@@ -74,8 +74,8 @@ jobs:
|
||||
echo ""
|
||||
echo "📦 Build Arguments:"
|
||||
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 " • NEXT_PUBLIC_SENTRY_DSN: ${{ secrets.NEXT_PUBLIC_SENTRY_DSN != '' && '***' || 'NOT SET' }}"
|
||||
echo " • NEXT_PUBLIC_BASE_URL: ${{ secrets.NEXT_PUBLIC_BASE_URL != '' && '***' || 'NOT SET' }}"
|
||||
echo ""
|
||||
echo "⏱️ Build started at: $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
|
||||
@@ -87,8 +87,8 @@ jobs:
|
||||
--pull \
|
||||
--platform linux/arm64 \
|
||||
--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 NEXT_PUBLIC_SENTRY_DSN="${{ secrets.NEXT_PUBLIC_SENTRY_DSN }}" \
|
||||
--build-arg NEXT_PUBLIC_BASE_URL="${{ secrets.NEXT_PUBLIC_BASE_URL }}" \
|
||||
-t registry.infra.mintel.me/mintel/klz-cables.com:latest \
|
||||
--push .
|
||||
@@ -160,11 +160,13 @@ jobs:
|
||||
MAIL_RECIPIENTS='${{ secrets.MAIL_RECIPIENTS }}' \
|
||||
MAIL_USERNAME='${{ secrets.MAIL_USERNAME }}' \
|
||||
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_SCRIPT_URL='${{ secrets.NEXT_PUBLIC_UMAMI_SCRIPT_URL }}' \
|
||||
NODE_ENV='${{ secrets.NODE_ENV }}' \
|
||||
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=$?
|
||||
echo ""
|
||||
|
||||
@@ -25,12 +25,11 @@ ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ARG NEXT_PUBLIC_UMAMI_WEBSITE_ID
|
||||
ARG NEXT_PUBLIC_UMAMI_SCRIPT_URL
|
||||
ARG SENTRY_DSN
|
||||
ARG NEXT_PUBLIC_SENTRY_DSN
|
||||
ARG NEXT_PUBLIC_BASE_URL
|
||||
|
||||
ENV NEXT_PUBLIC_UMAMI_WEBSITE_ID=$NEXT_PUBLIC_UMAMI_WEBSITE_ID
|
||||
ENV NEXT_PUBLIC_UMAMI_SCRIPT_URL=$NEXT_PUBLIC_UMAMI_SCRIPT_URL
|
||||
ENV SENTRY_DSN=$SENTRY_DSN
|
||||
ENV NEXT_PUBLIC_SENTRY_DSN=$NEXT_PUBLIC_SENTRY_DSN
|
||||
ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
|
||||
|
||||
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
|
||||
start_period: 30s
|
||||
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_SCRIPT_URL=${NEXT_PUBLIC_UMAMI_SCRIPT_URL:-https://analytics.infra.mintel.me/script.js}
|
||||
# GlitchTip (Sentry protocol)
|
||||
- NEXT_PUBLIC_UMAMI_SCRIPT_URL=${NEXT_PUBLIC_UMAMI_SCRIPT_URL}
|
||||
- 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_PORT=${MAIL_PORT}
|
||||
- MAIL_PORT=${MAIL_PORT:-587}
|
||||
- MAIL_USERNAME=${MAIL_USERNAME}
|
||||
- MAIL_PASSWORD=${MAIL_PASSWORD}
|
||||
- MAIL_FROM=${MAIL_FROM}
|
||||
- MAIL_RECIPIENTS=${MAIL_RECIPIENTS}
|
||||
# App
|
||||
- NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL}
|
||||
- REDIS_URL=${REDIS_URL}
|
||||
- REDIS_KEY_PREFIX=${REDIS_KEY_PREFIX}
|
||||
|
||||
networks:
|
||||
infra:
|
||||
|
||||
@@ -108,18 +108,35 @@ Next.js App (port 3000)
|
||||
- `staging.klz-cables.com` - Staging
|
||||
|
||||
## Environment Variables
|
||||
|
||||
|
||||
### 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_SCRIPT_URL`
|
||||
- `NEXT_PUBLIC_SENTRY_DSN`
|
||||
|
||||
### Runtime (in docker-compose.yml)
|
||||
|
||||
- `SENTRY_DSN`
|
||||
|
||||
### 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`
|
||||
- `MAIL_HOST`
|
||||
- `MAIL_PORT`
|
||||
- `MAIL_USERNAME`
|
||||
- `MAIL_PASSWORD`
|
||||
- `MAIL_FROM`
|
||||
- `MAIL_RECIPIENTS`
|
||||
- `REDIS_URL`
|
||||
- `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
|
||||
|
||||
|
||||
@@ -12,20 +12,40 @@ const getEnv = (key: string, defaultValue?: string): string | undefined => {
|
||||
return (process.env as any)[key] || defaultValue;
|
||||
}
|
||||
|
||||
if (typeof process === 'undefined') return defaultValue;
|
||||
if (typeof process === 'undefined') return defaultValue;
|
||||
|
||||
// In Docker/Production, variables are in process.env
|
||||
// In local development, they might be in .env
|
||||
const value = process.env[key];
|
||||
|
||||
if (value !== undefined && value !== '') {
|
||||
return value;
|
||||
// Check for quoted values (common when passed via SSH/Docker)
|
||||
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;
|
||||
};
|
||||
|
||||
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 = {
|
||||
env: getEnv('NODE_ENV', 'development'),
|
||||
isProduction: getEnv('NODE_ENV') === 'production',
|
||||
@@ -37,7 +57,7 @@ export const config = {
|
||||
analytics: {
|
||||
umami: {
|
||||
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
|
||||
proxyPath: '/stats/script.js',
|
||||
enabled: Boolean(getEnv('NEXT_PUBLIC_UMAMI_WEBSITE_ID')),
|
||||
@@ -74,16 +94,6 @@ export const config = {
|
||||
from: getEnv('MAIL_FROM'),
|
||||
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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -322,7 +322,7 @@ const nextConfig = {
|
||||
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
|
||||
},
|
||||
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
|
||||
? new URL(process.env.SENTRY_DSN).origin
|
||||
: 'https://errors.infra.mintel.me';
|
||||
|
||||
Reference in New Issue
Block a user