Compare commits

..

5 Commits

Author SHA1 Message Date
406cf22050 ci: fix private registry access in Docker build stage
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 9s
Build & Deploy / 🧪 QA (push) Successful in 1m35s
Build & Deploy / 🏗️ Build (push) Successful in 3m45s
Build & Deploy / 🚀 Deploy (push) Successful in 30s
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-02-11 15:03:14 +01:00
5e82d6edc9 ci: fix pipeline by reverting to stable node:20-alpine base images
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 8s
Build & Deploy / 🧪 QA (push) Successful in 1m33s
Build & Deploy / 🏗️ Build (push) Failing after 32s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-02-11 14:44:03 +01:00
85375eefb0 chore: standardize CI/CD maintenance and infrastructure cleanup
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 25s
Build & Deploy / 🧪 QA (push) Successful in 1m26s
Build & Deploy / 🏗️ Build (push) Failing after 15s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-02-11 12:23:14 +01:00
fe829b0c4c chore: ignore next-env.d.ts in prettier to prevent flapping
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 11s
Build & Deploy / 🧪 QA (push) Failing after 30s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-02-11 12:09:00 +01:00
9ed08004af fix(i18n): harden locale validation and fix missing translation tags 2026-02-11 12:07:08 +01:00
9 changed files with 69 additions and 21 deletions

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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;
}); });

View File

@@ -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"
} }
} }
} }

View File

@@ -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
View File

@@ -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.

View File

@@ -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,
});

View File

@@ -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,
});