docs: Gemini consult — build.sh fragility + deployment pipeline
7 questions covering: - Separating file copy from yarn compile - React component validation before production - ErrorBoundary for injected components - Eliminating deployment drift - Pre-commit hooks for PHP syntax - Pre-compiled bundle viability - BuiltByBit industry standards
This commit is contained in:
169
docs/consultations/gemini-build-pipeline-2026-04-13.md
Normal file
169
docs/consultations/gemini-build-pipeline-2026-04-13.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# Gemini Consultation: ModpackChecker Build Pipeline Fragility
|
||||
|
||||
**Date:** April 13, 2026 (late night)
|
||||
**From:** Michael (The Wizard) + Claude (Chronicler #84 — The Meridian)
|
||||
**To:** Gemini (Architectural Partner)
|
||||
**Re:** build.sh is causing production incidents — we need a bulletproof deployment pipeline
|
||||
|
||||
---
|
||||
|
||||
## Hey Gemini! 👋
|
||||
|
||||
It's very late and we just had a production incident. We're deploying ModpackChecker v1.1.0 on a live Pterodactyl panel and the new React widget caused the server info card to disappear entirely for users. We had to emergency-revert. The root cause is our build.sh doing too many things in one shot with no safety net. We need your help designing a bulletproof deployment pipeline before we try again.
|
||||
|
||||
---
|
||||
|
||||
## The Product
|
||||
|
||||
ModpackChecker is a Blueprint extension for Pterodactyl Panel 1.12.2. It has:
|
||||
- **PHP backend** — Laravel artisan commands, API controllers, services
|
||||
- **Admin Blade view** — PHP/Blade template for the admin settings page
|
||||
- **React TSX frontend** — Two components:
|
||||
- `ModpackVersionCard.tsx` — injected into the server console page
|
||||
- `UpdateBadge.tsx` — injected into the dashboard server list
|
||||
|
||||
Blueprint extensions install via `blueprint -install modpackchecker`, which copies files and then calls our `build.sh`.
|
||||
|
||||
---
|
||||
|
||||
## The Current build.sh (Full Source)
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Runs during blueprint -install from Pterodactyl root
|
||||
|
||||
# 1. Detect Node version, set NODE_OPTIONS for Node 17+
|
||||
NODE_MAJOR_VERSION=$(node -v | grep -oE '[0-9]+' | head -1)
|
||||
if [ "$NODE_MAJOR_VERSION" -ge 17 ]; then
|
||||
export NODE_OPTIONS=--openssl-legacy-provider
|
||||
fi
|
||||
|
||||
# 2. Copy wrapper.tsx → ModpackVersionCard.tsx
|
||||
EXT_DIR=".blueprint/extensions/modpackchecker"
|
||||
cp "$EXT_DIR/views/server/wrapper.tsx" resources/scripts/components/server/ModpackVersionCard.tsx
|
||||
|
||||
# 3. Inject import + component into AfterInformation.tsx (only if not already there)
|
||||
AFTER_INFO="resources/scripts/blueprint/components/Server/Terminal/AfterInformation.tsx"
|
||||
if ! grep -q "ModpackVersionCard" "$AFTER_INFO"; then
|
||||
sed -i '/\/* blueprint\/import \*\//a import ModpackVersionCard from "@/components/server/ModpackVersionCard";' "$AFTER_INFO"
|
||||
sed -i 's|{/\* blueprint/react \*/}|{/* blueprint/react */}\n <ModpackVersionCard />|' "$AFTER_INFO"
|
||||
fi
|
||||
|
||||
# 4. Copy UpdateBadge.tsx + inject into ServerRow.tsx
|
||||
cp "$EXT_DIR/views/dashboard/UpdateBadge.tsx" resources/scripts/components/dashboard/UpdateBadge.tsx
|
||||
if ! grep -q "UpdateBadge" resources/scripts/components/dashboard/ServerRow.tsx; then
|
||||
sed -i '1i import UpdateBadge from "@/components/dashboard/UpdateBadge";' resources/scripts/components/dashboard/ServerRow.tsx
|
||||
sed -i 's|{server.name}</p>|{server.name}<UpdateBadge serverUuid={server.uuid} /></p>|' resources/scripts/components/dashboard/ServerRow.tsx
|
||||
fi
|
||||
|
||||
# 5. Copy PHP files (services, controllers, commands)
|
||||
cp "$EXT_DIR/app/Services/LicenseService.php" app/Services/
|
||||
cp "$EXT_DIR/app/Services/ModpackApiService.php" app/Services/
|
||||
cp "$EXT_DIR/app/Console/Commands/CheckModpackUpdates.php" app/Console/Commands/
|
||||
cp "$EXT_DIR/app/Console/Commands/ValidateLicense.php" app/Console/Commands/
|
||||
cp "$EXT_DIR/app/Http/Controllers/ModpackAPIController.php" app/Http/Controllers/
|
||||
|
||||
# 6. Overwrite Blueprint's auto-generated admin controller
|
||||
cp "$EXT_DIR/admin/controller.php" "app/Http/Controllers/Admin/Extensions/modpackchecker/modpackcheckerExtensionController.php"
|
||||
|
||||
# 7. Clear caches
|
||||
php artisan optimize:clear
|
||||
|
||||
# 8. yarn build:production (2-5 minutes)
|
||||
yarn build:production
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What Happened Tonight
|
||||
|
||||
We shipped v1.1.0 with a redesigned React widget. During deployment:
|
||||
|
||||
1. We ran `blueprint -install modpackchecker` — SUCCESS, copied the new TSX
|
||||
2. We then manually re-ran `bash build.sh` to ensure the PHP files were copied
|
||||
3. Step 2 **overwrote** `ModpackVersionCard.tsx` with the new widget correctly
|
||||
4. `yarn build:production` compiled successfully
|
||||
5. BUT: the compiled bundle caused the server info card to disappear entirely
|
||||
|
||||
The new widget rendered nothing (or threw a silent React error that unmounted the whole card). We emergency-reverted to the old widget by writing the old TSX directly and rebuilding yarn.
|
||||
|
||||
**The result:** We now have v1.1.0 backend deployed (new DB columns, new endpoints, better detection) but v1.0.0 frontend widget still in production. The product is half-upgraded.
|
||||
|
||||
---
|
||||
|
||||
## The Problems
|
||||
|
||||
### Problem 1: No Staging / Safety Check
|
||||
The build runs directly on the production panel. There's no way to verify the compiled output renders correctly before it goes live. The only test is "does the panel explode."
|
||||
|
||||
### Problem 2: Build.sh Does Too Many Things
|
||||
It copies files AND injects into Pterodactyl source AND compiles frontend in one atomic step. If anything goes wrong mid-way, the panel is in an inconsistent state.
|
||||
|
||||
### Problem 3: Multiple Deployment Paths Create Drift
|
||||
We have two deployment patterns that fight each other:
|
||||
- `blueprint -install modpackchecker` (calls build.sh automatically)
|
||||
- Manual: copy individual PHP/TSX files + run yarn build separately
|
||||
|
||||
When we mix these, files get overwritten at different points and the final state is unpredictable.
|
||||
|
||||
### Problem 4: The `*/6` Docblock Keeps Coming Back
|
||||
Our PHP file `CheckModpackUpdates.php` has `*/6` in a docblock comment which PHP sometimes parses as end-of-comment + stray tokens. We've patched it THREE times on the server because build.sh keeps copying from a repo file that still has it (fixed in one copy, not the other).
|
||||
|
||||
### Problem 5: No Rollback
|
||||
When the panel broke tonight, there was no "undo" — we had to manually reconstruct the previous TSX from memory and rebuild yarn. A 90-second compile to fix something that took 10 seconds to break.
|
||||
|
||||
### Problem 6: Blueprint's Auto-Generated Controller Gets Overwritten
|
||||
Blueprint generates its own controller at `app/Http/Controllers/Admin/Extensions/modpackchecker/`. Our build.sh overwrites it with our version (which has LicenseService DI). But `blueprint -install` runs first and generates the file BEFORE our build.sh overwrites it — so the sequence is correct, but fragile. If Blueprint ever changes when it calls build.sh, we break.
|
||||
|
||||
---
|
||||
|
||||
## Our Constraints
|
||||
|
||||
1. **We're selling this on BuiltByBit** — customers install via `blueprint -install modpackchecker`. We cannot require them to do complex post-install steps.
|
||||
2. **We cannot assume SSH access** on customer panels — some customers are on managed hosting.
|
||||
3. **Pterodactyl 1.12.2 + Blueprint beta-2026-01** — these are fixed targets.
|
||||
4. **yarn build:production takes 90 seconds to 3 minutes** — on every install, every update.
|
||||
5. **Node.js version varies** — we handle this with `--openssl-legacy-provider` for Node 17+.
|
||||
6. **We have one source of truth** (`firefrost-services` git repo) but multiple deployment surfaces (Dev Panel, Live Panel, customer panels).
|
||||
|
||||
---
|
||||
|
||||
## Specific Questions
|
||||
|
||||
1. **How should we structure the build pipeline to separate "copy files" from "compile frontend"?**
|
||||
Right now it's all in build.sh. Should there be a separate `install.sh` (file operations) and `compile.sh` (yarn build), called in sequence? How do other Blueprint extensions handle this?
|
||||
|
||||
2. **Is there a way to validate a React component compiles without breaking the production bundle?**
|
||||
Before we run `yarn build:production` on a live panel, can we do a dry-run or type-check that would catch errors? `tsc --noEmit` perhaps? Or a simple syntax check?
|
||||
|
||||
3. **How should we handle the "new widget breaks the panel" failure mode?**
|
||||
Tonight the new TSX caused the server card to disappear entirely with no console error we could see. React swallowed the error silently. Should we wrap our component in an `ErrorBoundary`? What's the right defensive pattern for injected Blueprint components?
|
||||
|
||||
4. **What's the cleanest way to handle the multiple deployment paths (blueprint -install vs manual)?**
|
||||
We need one canonical deploy procedure that works whether the Chronicler is deploying to a customer panel OR to our own panels during development. How do we eliminate the "drift" problem?
|
||||
|
||||
5. **The `*/6` docblock problem** — is there a pre-commit hook or linting check that would catch PHP syntax errors like this before they reach the repo? We keep fixing it manually on the server.
|
||||
|
||||
6. **Should we ship a pre-compiled JS bundle instead of requiring yarn build on the customer's panel?**
|
||||
Gemini previously rejected this (it would overwrite Pterodactyl's `public/assets/main.js` and break other extensions). But is there a safe way to do it — like a separate bundle entry point that doesn't conflict with the main bundle? Or inject via a `<script>` tag in the admin view?
|
||||
|
||||
7. **For a BuiltByBit product, what's the industry standard for Blueprint extension deployment?**
|
||||
Do other successful Blueprint extensions require `yarn build`? Or do they avoid frontend injection entirely? We may be the only extension that does both deep PHP integration AND React component injection.
|
||||
|
||||
---
|
||||
|
||||
## Context That Might Help
|
||||
|
||||
- Blueprint beta-2026-01 calls build.sh automatically during `blueprint -install`
|
||||
- build.sh runs from the Pterodactyl root directory (`/var/www/pterodactyl/`)
|
||||
- `EXT_DIR` is `.blueprint/extensions/modpackchecker` — the extension files are there pre-install
|
||||
- We have two panels: Dev Panel (64.50.188.128) and Live Panel (45.94.168.138)
|
||||
- The Chronicler deploys via Trinity Core MCP (SSH). Customers deploy themselves.
|
||||
- Tonight's incident: new widget disappeared the server card. Root cause unknown — possibly a missing dependency, bad import, or runtime React error. We reverted before debugging.
|
||||
|
||||
---
|
||||
|
||||
Thanks Gemini. We're exhausted and the panel is stable but half-upgraded. Help us build this right so next time we don't have a midnight incident. 🔥❄️
|
||||
|
||||
— Michael (The Wizard) + Claude (Chronicler #84 — The Meridian)
|
||||
**Firefrost Gaming | Fire + Frost + Foundation = Where Love Builds Legacy** 💙🔥❄️
|
||||
Reference in New Issue
Block a user