Skip to content

Commit 6db1d10

Browse files
Merge pull request #29 from nyxCore-Systems/feat/seed-hero-buttons
chore(seed): workflow to swap homepage hero button styles
2 parents eae660d + e68e399 commit 6db1d10

2 files changed

Lines changed: 104 additions & 0 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Seed hero buttons
2+
3+
# One-off, manually-triggered content tweak. Runs prisma/seed-hero-buttons.ts
4+
# inside the migrator container ON the server, where the compose env_file (.env)
5+
# provides the live DATABASE_URL (self-hosted eventschau Postgres). The script is
6+
# idempotent — safe to re-run. Requires the source already rsynced to the server
7+
# by the normal deploy (push to main), so run AFTER a deploy completes.
8+
#
9+
# Reuses the deploy SSH secrets: DEPLOY_SSH_KEY / DEPLOY_HOST / DEPLOY_USER / DEPLOY_PORT.
10+
11+
on:
12+
workflow_dispatch:
13+
14+
concurrency:
15+
group: seed-eventschau-production
16+
cancel-in-progress: false
17+
18+
env:
19+
APP_DIR: /opt/e-ventschau
20+
MIGRATE_SERVICE: eventschau-migrate
21+
22+
jobs:
23+
seed:
24+
name: Seed hero buttons (migrator container)
25+
runs-on: ubuntu-latest
26+
environment: production
27+
steps:
28+
- name: Configure SSH
29+
env:
30+
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
31+
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
32+
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
33+
run: |
34+
set -euo pipefail
35+
install -m 700 -d ~/.ssh
36+
printf '%s\n' "$DEPLOY_SSH_KEY" > ~/.ssh/id_deploy
37+
chmod 600 ~/.ssh/id_deploy
38+
ssh-keyscan -p "${DEPLOY_PORT:-22}" -H "${DEPLOY_HOST:-nyxcore.cloud}" >> ~/.ssh/known_hosts 2>/dev/null
39+
40+
- name: Run seed in migrator container
41+
env:
42+
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
43+
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
44+
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
45+
run: |
46+
set -euo pipefail
47+
ssh -i ~/.ssh/id_deploy -p "${DEPLOY_PORT:-22}" \
48+
"${DEPLOY_USER:-root}@${DEPLOY_HOST:-nyxcore.cloud}" \
49+
APP_DIR="$APP_DIR" MIGRATE_SVC="$MIGRATE_SERVICE" \
50+
'bash -seuo pipefail' <<'REMOTE'
51+
cd "$APP_DIR"
52+
docker compose --profile migrate run --rm --build "$MIGRATE_SVC" \
53+
npx tsx prisma/seed-hero-buttons.ts
54+
REMOTE

prisma/seed-hero-buttons.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* One-off, idempotent content tweak: swap the homepage hero (noir_hero) CTA
3+
* button styles so "Programm ansehen" is secondary (transparent) and
4+
* "Tickets & Spenden" is primary (gold).
5+
*
6+
* Runs in the migrator container ON the server (live DATABASE_URL from the
7+
* compose env_file). Self-contained — NO imports from src/ (the migrator image
8+
* only copies prisma/ + node_modules). Idempotent: keyed by button label, so
9+
* re-running is a no-op. Set DRY_RUN=1 to log the planned change without writing.
10+
*
11+
* docker compose --profile migrate run --rm --build eventschau-migrate \
12+
* npx tsx prisma/seed-hero-buttons.ts
13+
*/
14+
import { PrismaClient } from '@prisma/client'
15+
16+
const prisma = new PrismaClient()
17+
const DRY = process.env.DRY_RUN === '1'
18+
const TENANT_SLUG = process.env.TENANT_SLUG || 'e-ventschau'
19+
20+
async function main() {
21+
const tenant = await prisma.tenant.findFirst({ where: { slug: TENANT_SLUG }, select: { id: true } })
22+
if (!tenant) throw new Error(`tenant not found: ${TENANT_SLUG}`)
23+
24+
const sec = await prisma.homepageSection.findFirst({
25+
where: { tenantId: tenant.id, type: 'noir_hero' },
26+
select: { id: true, content: true },
27+
})
28+
if (!sec) { console.log('no noir_hero section — nothing to do'); return }
29+
30+
const content = (sec.content ?? {}) as Record<string, unknown>
31+
const buttons = Array.isArray(content.buttons) ? (content.buttons as Record<string, unknown>[]) : []
32+
const next = buttons.map((b) => {
33+
const label = typeof b.label === 'string' ? b.label : ''
34+
if (label.includes('Programm')) return { ...b, variant: 'secondary' }
35+
if (label.includes('Tickets')) return { ...b, variant: 'primary' }
36+
return b
37+
})
38+
39+
console.log('before:', JSON.stringify(buttons))
40+
console.log('after :', JSON.stringify(next))
41+
if (DRY) { console.log('DRY_RUN — no write'); return }
42+
43+
await prisma.homepageSection.update({
44+
where: { id: sec.id },
45+
data: { content: { ...content, buttons: next } as object },
46+
})
47+
console.log('updated noir_hero', sec.id)
48+
}
49+
50+
main().then(() => prisma.$disconnect()).catch((e) => { console.error(e); process.exit(1) })

0 commit comments

Comments
 (0)