Compare commits

...

4 Commits

Author SHA1 Message Date
ce6436ab0a fix: manual migration for Agbs collection to resolve staging 500 error and cleanup failures
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 7s
Build & Deploy / 🧪 QA (push) Successful in 1m17s
Build & Deploy / 🏗️ Build (push) Successful in 3m46s
Build & Deploy / 🚀 Deploy (push) Successful in 15s
Build & Deploy / 🧪 Post-Deploy Verification (push) Failing after 5m8s
Build & Deploy / 🔔 Notify (push) Successful in 3s
2026-04-27 14:14:43 +02:00
de0089f068 fix(ci): align PAYLOAD_SECRET for post-deploy cleanup and enhance diagnostics
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 7s
Build & Deploy / 🧪 QA (push) Successful in 1m18s
Build & Deploy / 🏗️ Build (push) Successful in 3m53s
Build & Deploy / 🚀 Deploy (push) Successful in 21s
Build & Deploy / 🧪 Post-Deploy Verification (push) Failing after 5m33s
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-04-27 13:58:26 +02:00
263640bce5 fix: resolve lint warnings in AgbHistoryBlock and PayloadRichText
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 9s
Build & Deploy / 🧪 QA (push) Successful in 1m18s
Build & Deploy / 🏗️ Build (push) Successful in 4m20s
Build & Deploy / 🚀 Deploy (push) Successful in 20s
Build & Deploy / 🧪 Post-Deploy Verification (push) Failing after 5m3s
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-04-27 12:39:46 +02:00
1cc8fa4db4 chore: update payload types
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 7s
Build & Deploy / 🏗️ Build (push) Has been cancelled
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
Build & Deploy / 🧪 QA (push) Has been cancelled
2026-04-27 12:38:23 +02:00
9 changed files with 138 additions and 35 deletions

View File

@@ -532,7 +532,7 @@ jobs:
env:
NEXT_PUBLIC_BASE_URL: ${{ needs.prepare.outputs.next_public_url }}
GATEKEEPER_PASSWORD: ${{ secrets.GATEKEEPER_PASSWORD || 'klz2026' }}
PAYLOAD_SECRET: ${{ secrets.PAYLOAD_SECRET || vars.PAYLOAD_SECRET }}
PAYLOAD_SECRET: ${{ secrets.PAYLOAD_SECRET || vars.PAYLOAD_SECRET || 'you-need-to-set-a-payload-secret' }}
PUPPETEER_EXECUTABLE_PATH: /usr/bin/chromium
run: pnpm run check:forms

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { getPayload } from 'payload';
import configPromise from '@payload-config';
import { Container, Card, Heading } from '@/components/ui';
import { Heading } from '@/components/ui';
export const AgbHistoryBlock: React.FC<{ title: string }> = async ({ title }) => {
const payload = await getPayload({ config: configPromise });

View File

@@ -796,8 +796,8 @@ const jsxConverters: JSXConverters = {
</Section>
);
},
imageGallery: ({ node }: any) => <Gallery />,
'block-imageGallery': ({ node }: any) => <Gallery />,
imageGallery: ({ node: _node }: any) => <Gallery />,
'block-imageGallery': ({ node: _node }: any) => <Gallery />,
categoryGrid: ({ node }: any) => {
const cats = node.fields.categories || [];
return (

View File

@@ -116,6 +116,7 @@
"pdf:datasheets": "tsx ./scripts/generate-pdf-datasheets.ts",
"pdf:datasheets:legacy": "tsx ./scripts/generate-pdf-datasheets-pdf-lib.ts",
"cms:migrate": "payload migrate",
"cms:migrate:create": "payload migrate:create",
"cms:seed": "tsx ./scripts/seed-payload.ts",
"assets:push:testing": "bash ./scripts/assets-sync.sh local testing",
"assets:push:staging": "bash ./scripts/assets-sync.sh local staging",
@@ -139,7 +140,7 @@
"prepare": "husky",
"preinstall": "npx only-allow pnpm"
},
"version": "2.3.22-rc.2",
"version": "2.3.22-rc.4",
"pnpm": {
"onlyBuiltDependencies": [
"@parcel/watcher",

View File

@@ -73,6 +73,7 @@ export interface Config {
'form-submissions': FormSubmission;
products: Product;
pages: Page;
'agbs-collection': AgbsCollection;
'payload-kv': PayloadKv;
'payload-locked-documents': PayloadLockedDocument;
'payload-preferences': PayloadPreference;
@@ -86,8 +87,11 @@ export interface Config {
'form-submissions': FormSubmissionsSelect<false> | FormSubmissionsSelect<true>;
products: ProductsSelect<false> | ProductsSelect<true>;
pages: PagesSelect<false> | PagesSelect<true>;
'agbs-collection': AgbsCollectionSelect<false> | AgbsCollectionSelect<true>;
'payload-kv': PayloadKvSelect<false> | PayloadKvSelect<true>;
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
'payload-locked-documents':
| PayloadLockedDocumentsSelect<false>
| PayloadLockedDocumentsSelect<true>;
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
};
@@ -358,6 +362,19 @@ export interface Page {
createdAt: string;
_status?: ('draft' | 'published') | null;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "agbs-collection".
*/
export interface AgbsCollection {
id: number;
title: string;
versionDate: string;
file: number | Media;
isCurrent?: boolean | null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-kv".
@@ -405,6 +422,10 @@ export interface PayloadLockedDocument {
| ({
relationTo: 'pages';
value: number | Page;
} | null)
| ({
relationTo: 'agbs-collection';
value: number | AgbsCollection;
} | null);
globalSlug?: string | null;
user: {
@@ -592,6 +613,18 @@ export interface PagesSelect<T extends boolean = true> {
createdAt?: T;
_status?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "agbs-collection_select".
*/
export interface AgbsCollectionSelect<T extends boolean = true> {
title?: T;
versionDate?: T;
file?: T;
isCurrent?: T;
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-kv_select".
@@ -980,7 +1013,6 @@ export interface Auth {
[k: string]: unknown;
}
declare module 'payload' {
export interface GeneratedTypes extends Config {}
}
}

View File

@@ -115,8 +115,10 @@ async function main() {
// Intercept Next.js chunks and data to bypass Varnish 404-caching
// Includes standard /_next/ and subpath /gatekeeper/_next/
if (
(url.includes('/_next/static/') || url.includes('/_next/data/') || url.includes('/gatekeeper/_next/')) &&
!url.includes('?cb=') &&
(url.includes('/_next/static/') ||
url.includes('/_next/data/') ||
url.includes('/gatekeeper/_next/')) &&
!url.includes('?cb=') &&
!url.includes('&cb=')
) {
const buster = `cb=${Date.now()}`;
@@ -154,10 +156,10 @@ async function main() {
const navigateWithRetry = async (url: string, label: string) => {
chunkErrorsDetected = false;
console.log(`\n🧪 Testing ${label} on: ${url}`);
// First attempt: Wait for network to be relatively idle
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
// REDIRECTION CHECK: Logging redirected landing page
const finalUrl = page.url();
if (finalUrl !== url && !finalUrl.includes(url)) {
@@ -167,7 +169,9 @@ async function main() {
if (chunkErrorsDetected) {
const buster = `cb=${Date.now()}`;
const cbUrl = finalUrl.includes('?') ? `${finalUrl}&${buster}` : `${finalUrl}?${buster}`;
console.warn(` ⚠️ Assets failed to load (Varnish staleness suspected). Retrying with cache-buster: ${cbUrl}`);
console.warn(
` ⚠️ Assets failed to load (Varnish staleness suspected). Retrying with cache-buster: ${cbUrl}`,
);
chunkErrorsDetected = false;
await page.goto(cbUrl, { waitUntil: 'networkidle2', timeout: 30000 });
}
@@ -266,10 +270,10 @@ async function main() {
console.log(` 🔔 Alert text: ${alertText}`);
// Detection robust for both English and German versions
const isError =
alertText?.toLowerCase().includes('failed') ||
const isError =
alertText?.toLowerCase().includes('failed') ||
alertText?.toLowerCase().includes('wrong') ||
alertText?.toLowerCase().includes('fehlgeschlagen') ||
alertText?.toLowerCase().includes('fehlgeschlagen') ||
alertText?.toLowerCase().includes('schief gelaufen') ||
alertText?.toLowerCase().includes('fehler');
@@ -329,10 +333,10 @@ async function main() {
const alertText = await page.$eval('[role="alert"]', (el) => el.textContent);
console.log(` 🔔 Alert text: ${alertText}`);
const isError =
alertText?.toLowerCase().includes('failed') ||
const isError =
alertText?.toLowerCase().includes('failed') ||
alertText?.toLowerCase().includes('wrong') ||
alertText?.toLowerCase().includes('fehlgeschlagen') ||
alertText?.toLowerCase().includes('fehlgeschlagen') ||
alertText?.toLowerCase().includes('schief gelaufen') ||
alertText?.toLowerCase().includes('fehler');
@@ -349,9 +353,15 @@ async function main() {
// 5. Cleanup: Delete test submissions from Payload CMS
console.log(`\n🧹 Starting cleanup of test submissions...`);
const payloadSecret = process.env.PAYLOAD_SECRET;
if (!payloadSecret) {
console.warn(` ⚠️ PAYLOAD_SECRET not found in environment. Cleanup will likely fail with 403.`);
console.warn(
` ⚠️ PAYLOAD_SECRET not found in environment. Cleanup will likely fail with 403 if the server expects a secret.`,
);
} else {
console.log(
` 🔐 PAYLOAD_SECRET found (${payloadSecret.substring(0, 3)}...). Sending x-e2e-secret header.`,
);
}
try {
@@ -361,7 +371,7 @@ async function main() {
// Fetch test submissions with bypass header
const searchResponse = await axios.get(searchUrl, {
headers: {
headers: {
Cookie: `klz_gatekeeper_session=${gatekeeperPassword}`,
'x-e2e-secret': payloadSecret || '',
},
@@ -373,29 +383,31 @@ async function main() {
for (const doc of testSubmissions) {
try {
await axios.delete(`${apiUrl}/${doc.id}`, {
headers: {
headers: {
Cookie: `klz_gatekeeper_session=${gatekeeperPassword}`,
'x-e2e-secret': payloadSecret || '',
},
});
console.log(` ✅ Deleted submission: ${doc.id} (${doc.name})`);
} catch (delErr: any) {
console.warn(
` ⚠️ Cleanup attempt on ${doc.id} failed: ${delErr.message}`,
);
console.warn(` ⚠️ Cleanup attempt on ${doc.id} failed: ${delErr.message}`);
}
}
if (testSubmissions.length > 0) {
console.log(`✅ Cleanup completed successfully.`);
}
} catch (err: any) {
if (err.response?.status === 403) {
console.error(
` ❌ Cleanup failed with 403 Forbidden. Ensure FormSubmissions access control and PAYLOAD_SECRET are aligned.`,
);
console.error(` ❌ Cleanup failed with 403 Forbidden.`);
console.error(` Detail: The server rejected the x-e2e-secret header.`);
console.error(` Server Response: ${JSON.stringify(err.response.data)}`);
} else {
console.error(` ❌ Cleanup fetch failed: ${err.message}`);
if (err.response) {
console.error(` Status: ${err.response.status}`);
console.error(` Body: ${JSON.stringify(err.response.data)}`);
}
}
}

View File

@@ -1,5 +0,0 @@
{
"id": "20260225_003500_add_pages_collection",
"name": "20260225_003500_add_pages_collection",
"batch": 3
}

View File

@@ -0,0 +1,56 @@
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres';
export async function up({ db }: MigrateUpArgs): Promise<void> {
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "agbs_collection" (
"id" serial PRIMARY KEY NOT NULL,
"version_date" timestamp(3) with time zone NOT NULL,
"file_id" integer NOT NULL,
"is_current" boolean DEFAULT false,
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
);
CREATE TABLE IF NOT EXISTS "agbs_collection_locales" (
"id" serial PRIMARY KEY NOT NULL,
"title" varchar,
"_locale" "enum__locales" NOT NULL,
"_parent_id" integer NOT NULL
);
DO $$ BEGIN
ALTER TABLE "agbs_collection_locales" ADD CONSTRAINT "agbs_collection_locales_locale_parent_id_unique" UNIQUE("_locale", "_parent_id");
EXCEPTION WHEN duplicate_object THEN null; END $$;
DO $$ BEGIN
ALTER TABLE "agbs_collection_locales" ADD CONSTRAINT "agbs_collection_locales_parent_id_fk"
FOREIGN KEY ("_parent_id") REFERENCES "agbs_collection"("id") ON DELETE cascade;
EXCEPTION WHEN duplicate_object THEN null; END $$;
DO $$ BEGIN
ALTER TABLE "agbs_collection" ADD CONSTRAINT "agbs_collection_file_id_media_id_fk"
FOREIGN KEY ("file_id") REFERENCES "public"."media"("id") ON DELETE set null;
EXCEPTION WHEN duplicate_object THEN null; END $$;
CREATE INDEX IF NOT EXISTS "agbs_collection_updated_at_idx" ON "agbs_collection" USING btree ("updated_at");
CREATE INDEX IF NOT EXISTS "agbs_collection_created_at_idx" ON "agbs_collection" USING btree ("created_at");
-- Add to payload_locked_documents_rels
ALTER TABLE "payload_locked_documents_rels" ADD COLUMN IF NOT EXISTS "agbs_collection_id" integer;
DO $$ BEGIN
ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_agbs_collection_fk"
FOREIGN KEY ("agbs_collection_id") REFERENCES "public"."agbs_collection"("id") ON DELETE cascade;
EXCEPTION WHEN duplicate_object THEN null; END $$;
CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_agbs_collection_id_idx"
ON "payload_locked_documents_rels" USING btree ("agbs_collection_id");
`);
}
export async function down({ db }: MigrateDownArgs): Promise<void> {
await db.execute(sql`
ALTER TABLE "payload_locked_documents_rels" DROP CONSTRAINT IF EXISTS "payload_locked_documents_rels_agbs_collection_fk";
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "agbs_collection_id";
DROP TABLE IF EXISTS "agbs_collection_locales" CASCADE;
DROP TABLE IF EXISTS "agbs_collection" CASCADE;
`);
}

View File

@@ -5,6 +5,8 @@ import * as migration_20260225_175000_native_localization from './20260225_17500
import * as migration_20260305_215000_products_featured_image from './20260305_215000_products_featured_image';
import * as migration_20260312_120000_pages_redirect_fields from './20260312_120000_pages_redirect_fields';
import * as migration_20260427_123000_add_agbs_collection from './20260427_123000_add_agbs_collection';
export const migrations = [
{
up: migration_20260223_195005_products_collection.up,
@@ -36,4 +38,9 @@ export const migrations = [
down: migration_20260312_120000_pages_redirect_fields.down,
name: '20260312_120000_pages_redirect_fields',
},
{
up: migration_20260427_123000_add_agbs_collection.up,
down: migration_20260427_123000_add_agbs_collection.down,
name: '20260427_123000_add_agbs_collection',
},
];