CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Canceled after 0s
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Canceled after 0s
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Canceled after 0s
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Canceled after 0s
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Canceled after 0s
Fixes a real, previously-undiscovered build failure and a bigger
architectural gap found while testing an actual `docker build` of
proto/Dockerfile for the first time since the Payload migration:
1. Docker build failure: the (frontend)/[locale] pages use
generateStaticParams, so `next build` fully prerenders them (SSG) —
which calls the Payload Local API during the build. With no
MONGODB_URI/PAYLOAD_SECRET reachable in the build stage, `docker
build` failed outright ("missing secret key").
2. Bigger problem underneath: even if the build could reach a DB,
full SSG means a Payload admin edit would NOT appear on the public
site until a full rebuild + redeploy — directly undermining the
project's whole reason for migrating to Payload (self-service
content editing for the client).
Fix (user-confirmed direction: force-dynamic): dropped
generateStaticParams from (frontend)/[locale]/layout.tsx and
[locale]/[slug]/page.tsx, added `export const dynamic = 'force-dynamic'`
to layout.tsx + both page.tsx files. Every request now reads Payload
live — publishing in the admin is visible immediately, and the Docker
build no longer needs any DB connectivity at all (verified: a full
`docker build --target builder` now succeeds with zero env vars set).
Docker/Compose changes:
- docker-compose.staging.yml / docker-compose.prod.yml: wired
PAYLOAD_SECRET through to the app container (was documented in
.env.*.example since MITHOME-86 but never actually passed to the
container — Payload would have refused to start). No fallback,
same fail-loudly pattern as MONGODB_URI.
- Same two files: added a named `media_data_{staging,prod}` volume
mounted at /app/media — Payload's local upload storage (Media.ts)
writes there at the container's runtime cwd; without a volume,
`deploy.sh`'s `--force-recreate` would silently wipe every uploaded
logo/image on each deploy.
- docker-compose.dev.yml: was missing PAYLOAD_SECRET entirely (only
discovered because the same "missing secret key" error reproduces
there too) — added a dev-only literal value. Media persistence
already works there via the existing `./proto:/app` bind mount, no
volume needed. Also dropped the obsolete `version: '3.8'` key
(compose warns it's ignored).
- DOCKER.md: one-paragraph note on the new PAYLOAD_SECRET requirement
and where the admin account gets created.
Verified:
- `docker build --target builder` succeeds from a clean context with
zero environment variables (previously failed).
- `docker build --target runner` + `docker run` against the real dev
MongoDB (PAYLOAD_SECRET + MONGODB_URI supplied at runtime only):
/hu, /admin and /api/health all return 200 inside the container;
confirmed live in the browser that Payload content renders
correctly end-to-end through the production Next.js server, not
just `next dev`.
- `docker compose -f docker-compose.{staging,prod,dev}.yml config`
parses cleanly.
- Full gate green: tsc, lint, proto unit tests (51 passed),
scripts/pre-deploy-tests.sh (proto tests, tsc, lint, content schema,
plane-sync — all pass).
deploy.sh itself needs no changes: it already just runs
`docker compose up --build`, and that now works without any
build-time DB wiring.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
64 lines
2.3 KiB
TypeScript
64 lines
2.3 KiB
TypeScript
import { notFound } from 'next/navigation'
|
|
import Header from '../../../components/Header'
|
|
import Footer from '../../../components/Footer'
|
|
import { isLocale, localePath, type Locale } from '@/lib/i18n'
|
|
import { getCommonContent, getHomeContent } from '@/lib/payload-content'
|
|
import { siteConfig, getMainNavigation, getFooterNavigation, getFooterLegalLinks, getSiteDescription } from '@/config/site'
|
|
|
|
// WHY force-dynamic (MITHOME-97): ezek az oldalak a Payload Local API-t hívják
|
|
// (élő MongoDB-olvasás). generateStaticParams + SSG mellett a build időben
|
|
// sütött ki minden oldal, és a Payload adminban végzett publikálás csak egy
|
|
// teljes redeploy után jelent volna meg a publikus oldalon — ez pont az
|
|
// ellentéte az önkiszolgáló szerkesztés céljának, amiért a Payload-migráció
|
|
// történt. force-dynamic-kal minden kérés friss Payload-olvasást kap, és a
|
|
// Docker build sem függ többé egy build-idejű MongoDB-kapcsolattól.
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
export default async function LocaleLayout({
|
|
children,
|
|
params,
|
|
}: {
|
|
children: React.ReactNode
|
|
params: Promise<{ locale: string }>
|
|
}) {
|
|
const { locale: rawLocale } = await params
|
|
if (!isLocale(rawLocale)) notFound()
|
|
const locale: Locale = rawLocale
|
|
|
|
const [common, home] = await Promise.all([
|
|
getCommonContent(locale),
|
|
getHomeContent(locale),
|
|
])
|
|
|
|
const isStaging = process.env.NEXT_PUBLIC_DEPLOY_ENV === 'staging'
|
|
|
|
return (
|
|
<>
|
|
{isStaging && (
|
|
<div className="bg-amber-400 px-4 py-2 text-center text-xs font-extrabold tracking-[0.18em] text-amber-950 sm:text-sm">
|
|
{common.staging.banner}
|
|
</div>
|
|
)}
|
|
<Header
|
|
nav={getMainNavigation(locale)}
|
|
homeHref={localePath(locale)}
|
|
a11y={common.a11y}
|
|
/>
|
|
<main className="flex-1">
|
|
{children}
|
|
</main>
|
|
<Footer
|
|
nav={getFooterNavigation(locale)}
|
|
legalLinks={getFooterLegalLinks(locale)}
|
|
homeHref={localePath(locale)}
|
|
description={getSiteDescription(locale)}
|
|
contactEmail={siteConfig.contact.email}
|
|
footerAddress={common.footer.address}
|
|
footerCopyright={common.footer.copyright}
|
|
homeServices={home.services.items.map((item) => ({ id: item.id, title: item.title, icon: item.icon }))}
|
|
locale={locale}
|
|
/>
|
|
</>
|
|
)
|
|
}
|