Compare commits

...

2 Commits

Author SHA1 Message Date
f8b7d4f59d feat: add asset sync scripts and fix payload seeding
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 8s
Build & Deploy / 🧪 QA (push) Successful in 2m2s
Build & Deploy / 🏗️ Build (push) Failing after 4m13s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / ⚡ Performance & Accessibility (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-02-26 02:39:18 +01:00
7fb4d306c3 chore: fix staging routing, memory limits and nextjs config
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 6s
Build & Deploy / 🧪 QA (push) Successful in 1m44s
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / ⚡ Performance & Accessibility (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
Build & Deploy / 🏗️ Build (push) Has been cancelled
2026-02-26 02:37:29 +01:00
7 changed files with 131 additions and 12 deletions

View File

@@ -346,6 +346,8 @@ jobs:
SITE_DIR="/home/deploy/sites/klz-cables.com"
elif [[ "$TARGET" == "testing" ]]; then
SITE_DIR="/home/deploy/sites/testing.klz-cables.com"
elif [[ "$TARGET" == "staging" ]]; then
SITE_DIR="/home/deploy/sites/staging.klz-cables.com"
else
SITE_DIR="/home/deploy/sites/branch.klz-cables.com/${SLUG:-unknown}"
fi

View File

@@ -41,6 +41,8 @@ CMD ["pnpm", "dev:local"]
# Build application
# Stage 3: Builder (Production)
FROM base AS builder
# Limit memory to 2GB to prevent ResourceExhausted on 4GB runner
ENV NODE_OPTIONS="--max-old-space-size=2048"
RUN pnpm build
# Stage 3: Runner

View File

@@ -66,6 +66,14 @@ services:
- "traefik.http.middlewares.${PROJECT_NAME:-klz}-auth.forwardauth.authResponseHeaders=X-Auth-User"
- "traefik.docker.network=infra"
# Gatekeeper Public Router (Login/Auth UI)
- "traefik.http.routers.${PROJECT_NAME:-klz}-gatekeeper.rule=(${TRAEFIK_HOST_RULE:-Host(`${TRAEFIK_HOST:-klz-cables.com}`)}) && PathRegexp(`^/(login|gatekeeper)(/.*)?`)"
- "traefik.http.routers.${PROJECT_NAME:-klz}-gatekeeper.entrypoints=${TRAEFIK_ENTRYPOINT:-web}"
- "traefik.http.routers.${PROJECT_NAME:-klz}-gatekeeper.tls.certresolver=${TRAEFIK_CERT_RESOLVER:-}"
- "traefik.http.routers.${PROJECT_NAME:-klz}-gatekeeper.tls=${TRAEFIK_TLS:-false}"
- "traefik.http.routers.${PROJECT_NAME:-klz}-gatekeeper.service=${PROJECT_NAME:-klz}-gatekeeper-svc"
- "traefik.http.routers.${PROJECT_NAME:-klz}-gatekeeper.priority=2001"
klz-db:
image: postgres:15-alpine
restart: unless-stopped

View File

@@ -14,7 +14,6 @@ const nextConfig = {
experimental: {
optimizePackageImports: ['lucide-react', 'framer-motion', '@/components/ui'],
},
swcMinify: false,
reactStrictMode: false,
productionBrowserSourceMaps: false,
logging: {
@@ -75,14 +74,11 @@ const nextConfig = {
key: 'Permissions-Policy',
value: 'camera=(), microphone=(), geolocation=(), interest-cohort=()',
},
];
if (isProd) {
secureHeaders.push({
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload',
});
}
},
];
return [
{

View File

@@ -110,15 +110,18 @@
"check:security": "tsx ./scripts/check-security.ts",
"check:links": "bash ./scripts/check-links.sh",
"check:assets": "tsx ./scripts/check-broken-assets.ts",
"cms:branding:local": "DIRECTUS_URL=${DIRECTUS_URL:-http://cms.klz.localhost} npx tsx --env-file=.env scripts/setup-directus-branding.ts",
"cms:branding:testing": "DIRECTUS_URL=https://cms.testing.klz-cables.com npx tsx --env-file=.env scripts/setup-directus-branding.ts",
"cms:branding:staging": "DIRECTUS_URL=https://cms.staging.klz-cables.com npx tsx --env-file=.env scripts/setup-directus-branding.ts",
"cms:branding:prod": "DIRECTUS_URL=https://cms.klz-cables.com npx tsx --env-file=.env scripts/setup-directus-branding.ts",
"cms:bootstrap": "pnpm run cms:branding:local",
"pdf:datasheets": "tsx ./scripts/generate-pdf-datasheets.ts",
"pdf:datasheets:legacy": "tsx ./scripts/generate-pdf-datasheets-pdf-lib.ts",
"cms:migrate": "payload migrate",
"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",
"assets:push:prod": "bash ./scripts/assets-sync.sh local prod",
"assets:pull:testing": "bash ./scripts/assets-sync.sh testing local",
"assets:pull:staging": "bash ./scripts/assets-sync.sh staging local",
"assets:pull:prod": "bash ./scripts/assets-sync.sh prod local",
"assets:sync:testing-to-staging": "bash ./scripts/assets-sync.sh testing staging",
"assets:sync:staging-to-prod": "bash ./scripts/assets-sync.sh staging prod",
"pagespeed:test": "tsx ./scripts/pagespeed-sitemap.ts",
"pagespeed:audit": "./scripts/audit-local.sh",
"pagespeed:urls": "tsx -e \"import sitemap from './app/sitemap'; sitemap().then(urls => console.log(urls.map(u => u.url).join('\\n')))\"",

86
scripts/assets-sync.sh Executable file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/env bash
# ────────────────────────────────────────────────────────────────────────────
# Asset Sync Tool
# Syncs media files between environments without touching the database.
# ────────────────────────────────────────────────────────────────────────────
set -euo pipefail
# Load environment variables
if [ -f .env ]; then
set -a; source .env; set +a
fi
# ── Configuration ──────────────────────────────────────────────────────────
SOURCE_ENV="${1:-}" # local | testing | staging | prod
TARGET_ENV="${2:-}" # testing | staging | prod
SSH_HOST="root@alpha.mintel.me"
LOCAL_MEDIA_DIR="./public/media"
DRY_RUN=""
CHECKSUM=""
if [[ "$*" == *"--dry-run"* ]]; then
DRY_RUN="--dry-run"
echo "🏃 DRY RUN MODE ENABLED"
fi
if [[ "$*" == *"--checksum"* ]]; then
CHECKSUM="-c"
echo "🔍 CHECKSUM MODE ENABLED (Slower but more reliable)"
fi
# ── Resolve Paths ──────────────────────────────────────────────────────────
get_media_path() {
case "$1" in
local) echo "$LOCAL_MEDIA_DIR" ;;
testing) echo "/var/lib/docker/volumes/klz-testing_klz_media_data/_data" ;;
staging) echo "/var/lib/docker/volumes/klz-staging_klz_media_data/_data" ;;
prod|production) echo "/var/lib/docker/volumes/klz-cablescom_klz_media_data/_data" ;;
*) echo "❌ Unknown environment: $1"; exit 1 ;;
esac
}
get_app_container() {
case "$1" in
testing) echo "klz-testing-klz-app-1" ;;
staging) echo "klz-staging-klz-app-1" ;;
prod|production) echo "klz-cablescom-klz-app-1" ;;
*) echo "" ;;
esac
}
SRC_PATH=$(get_media_path "$SOURCE_ENV")
TGT_PATH=$(get_media_path "$TARGET_ENV")
TGT_CONTAINER=$(get_app_container "$TARGET_ENV")
echo "🚀 Syncing assets: $SOURCE_ENV$TARGET_ENV"
echo "📂 Source: $SRC_PATH"
echo "📂 Target: $TGT_PATH"
# ── Execution ──────────────────────────────────────────────────────────────
if [[ ! -d "$SRC_PATH" ]] && [[ "$SOURCE_ENV" == "local" ]]; then
echo "❌ Source directory does not exist: $SRC_PATH"
exit 1
fi
if [[ "$SOURCE_ENV" == "local" ]]; then
# Local → Remote
echo "📡 Running rsync..."
rsync -avzi $CHECKSUM --delete --progress $DRY_RUN "$SRC_PATH/" "$SSH_HOST:$TGT_PATH/"
elif [[ "$TARGET_ENV" == "local" ]]; then
# Remote → Local
mkdir -p "$LOCAL_MEDIA_DIR"
echo "📡 Running rsync..."
rsync -avzi $CHECKSUM --delete --progress $DRY_RUN "$SSH_HOST:$SRC_PATH/" "$TGT_PATH/"
else
# Remote → Remote (e.g., testing → staging)
echo "📡 Running remote rsync..."
ssh "$SSH_HOST" "rsync -avzi $CHECKSUM --delete --progress $DRY_RUN $SRC_PATH/ $TGT_PATH/"
fi
# Fix ownership on remote target if it's not local
if [[ "$TARGET_ENV" != "local" && -z "$DRY_RUN" ]]; then
echo "🔑 Fixing media file permissions on $TARGET_ENV..."
ssh "$SSH_HOST" "docker exec -u 0 $TGT_CONTAINER chown -R 1001:65533 /app/public/media/ 2>/dev/null || true"
fi
echo "✅ Asset sync complete!"

22
scripts/seed-payload.ts Normal file
View File

@@ -0,0 +1,22 @@
/**
* CLI wrapper for seeding the Payload CMS database.
* Usage: pnpm tsx scripts/seed-payload.ts
*/
import { getPayload } from 'payload';
import configPromise from '../payload.config';
import { seedDatabase } from '../src/payload/seed';
async function run() {
const payload = await getPayload({ config: configPromise });
console.log('🌱 Starting database seed...');
await seedDatabase(payload);
console.log('✅ Seeding complete.');
process.exit(0);
}
run().catch((err) => {
console.error('❌ Seeding failed:', err);
process.exit(1);
});