Closes the gap between "what tag did I deploy" and "what is actually running", and gives the schema a history that can be reasoned about across releases. Migrations - Baseline the existing schema as 0000_init (migrate diff --from-empty). The schema had only ever been applied with `prisma db push`, so no history existed and schema state was disconnected from app version. Existing databases must be baselined once with `migrate resolve --applied 0000_init`; the workflows print this remedy on P3005. - Run `prisma migrate deploy` as a deploy STEP, not the container CMD — as a CMD, N replicas would race each other applying the same migration. Version reporting - GET /version on the API reports the APP_VERSION / GIT_SHA / BUILD_DATE that build.yml already baked into both images but nothing ever read. - The web footer shows the web build and flags an api/web mismatch. The two cannot drift at build time (one matrix run) but can at deploy time. - Both deploy workflows now fail if the running API does not report the tag that was dispatched — a stack naming a tag is not proof of what is running. - scripts/set-version.mjs stamps every package.json, which had all sat at 0.1.0 while real releases shipped as v1.x. Pre-migrate backup - deploy/scripts/pre-migrate-backup.mjs dumps the database from INSIDE the still-running old API container over Portainer's Docker API, so the file lands in the volume the Operaciones restore screen reads. A dump taken on the CI runner would be unreachable by the only restore path we have. Verifies the artefact with `gzip -t` before letting the migration proceed. galactus - deploy/galactus/*.compose.yml: standalone-Docker ports of the Swarm stacks. Plain compose silently ignores `deploy:`, so restart_policy becomes `restart: unless-stopped` — without it nothing returns after a host reboot. - .gitea/workflows/deploy-galactus.yml drives endpoint 3 with its own secrets. Fixes - deploy.yml passed `endpoint_id` and `pull_image` to cssnr/portainer-stack-deploy-action, which has no such inputs (they are `endpoint` and `pull`). The endpoint was silently never set. docs/DEPLOY_AND_MIGRATIONS.md documents expand/contract as the rule for schema changes: Prisma has no down-migrations, so a code rollback never rolls the schema back, and restoring the replication master from a dump diverges every replica. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
67 lines
2.6 KiB
TypeScript
67 lines
2.6 KiB
TypeScript
import type { ReactNode } from "react";
|
|
import "./globals.css";
|
|
import { readBuildInfoFromEnv } from "@/lib/build-info";
|
|
|
|
export const metadata = {
|
|
title: "Jorge Cuadros & Asociados — Plataforma",
|
|
description:
|
|
"Plataforma interna unificada de clientes, servicios y seguros.",
|
|
};
|
|
|
|
// The browser talks to the API cross-origin, so it needs the API URL at
|
|
// runtime. NEXT_PUBLIC_* would bake it at build time (one URL per image); we
|
|
// want the URL to come from the deploy .env instead. So read it here on the
|
|
// server per request and inject it as window.__API_ORIGIN__ (see lib/api.ts).
|
|
// force-dynamic guarantees process.env is read at request time, never baked
|
|
// into a static prerender.
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export default function RootLayout({ children }: { children: ReactNode }) {
|
|
const apiOrigin =
|
|
process.env.API_ORIGIN ??
|
|
process.env.NEXT_PUBLIC_API_ORIGIN ??
|
|
"http://localhost:3001";
|
|
// Same reason as the API origin: read on the server per request so the built
|
|
// image is not pinned to one build identity in its client bundle.
|
|
const build = readBuildInfoFromEnv();
|
|
|
|
return (
|
|
<html lang="es">
|
|
<head>
|
|
{/* Must run before the app bundle so lib/api.ts sees it at import. */}
|
|
<script
|
|
dangerouslySetInnerHTML={{
|
|
__html:
|
|
`window.__API_ORIGIN__=${JSON.stringify(apiOrigin)};` +
|
|
`window.__APP_BUILD__=${JSON.stringify(build)};`,
|
|
}}
|
|
/>
|
|
{/* Text-size preference, applied before first paint so the page never
|
|
flashes at the default size. Mirrors lib/ui-scale.ts — keep the key
|
|
and the clamp in sync with it. */}
|
|
<script
|
|
dangerouslySetInnerHTML={{
|
|
__html:
|
|
`try{var s=parseFloat(localStorage.getItem("jc.ui-scale"));` +
|
|
`if(isFinite(s))document.documentElement.style.setProperty(` +
|
|
`"--ui-scale",String(Math.min(1.5,Math.max(0.9,s))));}catch(e){}`,
|
|
}}
|
|
/>
|
|
{/* Google Fonts via <link> so an offline build still runs with the
|
|
system fallback stacks defined in globals.css. */}
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link
|
|
rel="preconnect"
|
|
href="https://fonts.gstatic.com"
|
|
crossOrigin="anonymous"
|
|
/>
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,560;9..144,600&family=Work+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"
|
|
rel="stylesheet"
|
|
/>
|
|
</head>
|
|
<body>{children}</body>
|
|
</html>
|
|
);
|
|
}
|