Compare commits
5 Commits
v1.0.0-rc.
...
v1.0.0-rc.
| Author | SHA1 | Date | |
|---|---|---|---|
| 406cf22050 | |||
| 5e82d6edc9 | |||
| 85375eefb0 | |||
| fe829b0c4c | |||
| 9ed08004af |
@@ -37,6 +37,13 @@ jobs:
|
|||||||
container:
|
container:
|
||||||
image: catthehacker/ubuntu:act-latest
|
image: catthehacker/ubuntu:act-latest
|
||||||
steps:
|
steps:
|
||||||
|
- name: 🧹 Maintenance (High Density Cleanup)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "Purging old build layers and dangling images..."
|
||||||
|
docker image prune -f
|
||||||
|
docker builder prune -f --filter "until=6h"
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -284,6 +291,10 @@ jobs:
|
|||||||
|
|
||||||
ssh root@alpha.mintel.me "docker system prune -f --filter 'until=24h'"
|
ssh root@alpha.mintel.me "docker system prune -f --filter 'until=24h'"
|
||||||
|
|
||||||
|
- name: 🧹 Post-Deploy Cleanup (Runner)
|
||||||
|
if: always()
|
||||||
|
run: docker builder prune -f --filter "until=1h"
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
# JOB 5: Notifications
|
# JOB 5: Notifications
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
11
.prettierignore
Normal file
11
.prettierignore
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Ignore Next.js auto-generated environment file
|
||||||
|
# It often uses different quote styles than our project config
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
|
# Ignore build output
|
||||||
|
.next
|
||||||
|
dist
|
||||||
|
out
|
||||||
|
|
||||||
|
# Ignore other potentially generated files
|
||||||
|
pnpm-lock.yaml
|
||||||
25
Dockerfile
25
Dockerfile
@@ -1,8 +1,8 @@
|
|||||||
# Stage 1: Builder
|
# Stage 1: Builder
|
||||||
FROM registry.infra.mintel.me/mintel/nextjs:latest AS builder
|
FROM node:20-alpine AS builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Clean the workspace in case the base image is dirty
|
# Clean the workspace
|
||||||
RUN rm -rf ./*
|
RUN rm -rf ./*
|
||||||
|
|
||||||
# Arguments for build-time configuration
|
# Arguments for build-time configuration
|
||||||
@@ -18,17 +18,20 @@ ENV DIRECTUS_URL=$DIRECTUS_URL
|
|||||||
ENV SKIP_RUNTIME_ENV_VALIDATION=true
|
ENV SKIP_RUNTIME_ENV_VALIDATION=true
|
||||||
ENV CI=true
|
ENV CI=true
|
||||||
|
|
||||||
# Enable pnpm
|
# Enable pnpm v10
|
||||||
RUN corepack enable
|
RUN corepack enable && corepack prepare pnpm@10.3.0 --activate
|
||||||
|
|
||||||
# Copy lockfile and manifest for dependency installation caching
|
# Copy lockfile and manifest for dependency installation caching
|
||||||
COPY pnpm-lock.yaml package.json .npmrc* ./
|
COPY pnpm-lock.yaml package.json .npmrc* ./
|
||||||
|
|
||||||
# Install dependencies with cache mount
|
# Configure private registry and install dependencies
|
||||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
--mount=type=secret,id=NPM_TOKEN \
|
--mount=type=secret,id=NPM_TOKEN \
|
||||||
export NPM_TOKEN=$(cat /run/secrets/NPM_TOKEN 2>/dev/null || echo $NPM_TOKEN) && \
|
export NPM_TOKEN=$(cat /run/secrets/NPM_TOKEN 2>/dev/null || echo $NPM_TOKEN) && \
|
||||||
pnpm install --frozen-lockfile
|
echo "@mintel:registry=https://npm.infra.mintel.me" > .npmrc && \
|
||||||
|
echo "//npm.infra.mintel.me/:_authToken=\${NPM_TOKEN}" >> .npmrc && \
|
||||||
|
pnpm install --frozen-lockfile && \
|
||||||
|
rm .npmrc
|
||||||
|
|
||||||
# Copy source code
|
# Copy source code
|
||||||
COPY . .
|
COPY . .
|
||||||
@@ -37,9 +40,17 @@ COPY . .
|
|||||||
RUN pnpm build
|
RUN pnpm build
|
||||||
|
|
||||||
# Stage 2: Runner
|
# Stage 2: Runner
|
||||||
FROM registry.infra.mintel.me/mintel/runtime:latest AS runner
|
FROM node:20-alpine AS runner
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install curl for health checks
|
||||||
|
RUN apk add --no-cache curl
|
||||||
|
|
||||||
|
# Create nextjs user and group
|
||||||
|
RUN addgroup --system --gid 1001 nodejs && \
|
||||||
|
adduser --system --uid 1001 nextjs && \
|
||||||
|
chown nextjs:nodejs /app
|
||||||
|
|
||||||
ENV HOSTNAME="0.0.0.0"
|
ENV HOSTNAME="0.0.0.0"
|
||||||
ENV PORT=3000
|
ENV PORT=3000
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|||||||
@@ -2,11 +2,18 @@ import { getRequestConfig } from 'next-intl/server';
|
|||||||
import * as Sentry from '@sentry/nextjs';
|
import * as Sentry from '@sentry/nextjs';
|
||||||
|
|
||||||
export default getRequestConfig(async ({ requestLocale }) => {
|
export default getRequestConfig(async ({ requestLocale }) => {
|
||||||
let locale = await requestLocale;
|
// Hardened locale validation: only allow 'en' or 'de'
|
||||||
|
// Use a temporary variable to validate before assigning to locale
|
||||||
|
const rawLocale = await requestLocale;
|
||||||
|
const supportedLocales = ['en', 'de'];
|
||||||
|
const locale =
|
||||||
|
typeof rawLocale === 'string' && supportedLocales.includes(rawLocale) ? rawLocale : 'en';
|
||||||
|
|
||||||
// Ensure that a valid locale is used
|
// Log to Sentry if we had to fallback, as it might indicate a routing issue
|
||||||
if (!locale || !['en', 'de'].includes(locale)) {
|
if (!rawLocale || !supportedLocales.includes(rawLocale as string)) {
|
||||||
locale = 'en';
|
console.warn(
|
||||||
|
`[i18n] Invalid or missing requestLocale received: "${rawLocale}". Falling back to "en".`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -26,6 +33,6 @@ export default getRequestConfig(async ({ requestLocale }) => {
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
return 'fallback';
|
return 'fallback';
|
||||||
}
|
},
|
||||||
} as any;
|
} as any;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -206,7 +206,7 @@
|
|||||||
"title": "Produktportfolio | Hochwertige Kabel für jede Anwendung",
|
"title": "Produktportfolio | Hochwertige Kabel für jede Anwendung",
|
||||||
"description": "Entdecken Sie unser umfassendes Sortiment an zertifizierten Kabeln: von Niederspannung über Mittel- und Hochspannung bis hin zu spezialisierten Solarkabeln."
|
"description": "Entdecken Sie unser umfassendes Sortiment an zertifizierten Kabeln: von Niederspannung über Mittel- und Hochspannung bis hin zu spezialisierten Solarkabeln."
|
||||||
},
|
},
|
||||||
"title": "Unsere Produkte",
|
"title": "Unsere <green>Produkte</green>",
|
||||||
"subtitle": "Entdecken Sie unser umfassendes Sortiment an hochwertigen Kabeln für jede Anwendung.",
|
"subtitle": "Entdecken Sie unser umfassendes Sortiment an hochwertigen Kabeln für jede Anwendung.",
|
||||||
"heroSubtitle": "Produktportfolio",
|
"heroSubtitle": "Produktportfolio",
|
||||||
"categoryLabel": "Kategorie",
|
"categoryLabel": "Kategorie",
|
||||||
@@ -393,4 +393,4 @@
|
|||||||
"cta": "Zurück zur Sicherheit"
|
"cta": "Zurück zur Sicherheit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,7 +206,7 @@
|
|||||||
"title": "Product Portfolio | High-Quality Cables for Every Application",
|
"title": "Product Portfolio | High-Quality Cables for Every Application",
|
||||||
"description": "Explore our comprehensive range of certified cables: from low voltage to medium and high voltage, as well as specialized solar cables."
|
"description": "Explore our comprehensive range of certified cables: from low voltage to medium and high voltage, as well as specialized solar cables."
|
||||||
},
|
},
|
||||||
"title": "Our Products",
|
"title": "Our <green>Products</green>",
|
||||||
"subtitle": "Explore our comprehensive range of high-quality cables designed for every application.",
|
"subtitle": "Explore our comprehensive range of high-quality cables designed for every application.",
|
||||||
"heroSubtitle": "Product Portfolio",
|
"heroSubtitle": "Product Portfolio",
|
||||||
"categoryLabel": "Category",
|
"categoryLabel": "Category",
|
||||||
@@ -393,4 +393,4 @@
|
|||||||
"cta": "Back to Safety"
|
"cta": "Back to Safety"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
next-env.d.ts
vendored
2
next-env.d.ts
vendored
@@ -1,6 +1,6 @@
|
|||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
import './.next/types/routes.d.ts';
|
import "./.next/types/routes.d.ts";
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ const dsn = process.env.SENTRY_DSN;
|
|||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn,
|
dsn,
|
||||||
enabled: Boolean(dsn),
|
enabled: Boolean(dsn),
|
||||||
tracesSampleRate: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// Adjust this value in production, or use tracesSampler for greater control
|
||||||
|
tracesSampleRate: 1,
|
||||||
|
|
||||||
|
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
||||||
|
debug: false,
|
||||||
|
});
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ const dsn = process.env.SENTRY_DSN;
|
|||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn,
|
dsn,
|
||||||
enabled: Boolean(dsn),
|
enabled: Boolean(dsn),
|
||||||
tracesSampleRate: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// Adjust this value in production, or use tracesSampler for greater control
|
||||||
|
tracesSampleRate: 1,
|
||||||
|
|
||||||
|
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
||||||
|
debug: false,
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user