chore(ci,docs): retire staging — dev→beta→main ladder + beta-first self-host plan - #670
Conversation
…lf-host plan - promotion-guard: ALLOWED now [main]=beta [beta]=dev; trigger branches [main, beta]; comments + error message updated for the dev→beta→main ladder - TWIZRR_SELF_HOST_DEPLOYMENT: beta = disposable rehearsal (Contabo VPS 8), prod on a dedicated box later, early-access via allowlist on prod (no beta→prod data migration); spec table, env matrix, and Phase 5/6 reframed beta-vs-prod Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 7 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe promotion workflow now enforces ChangesBeta-First Promotion and Deployment
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
.github/workflows/promotion-guard.yml (1)
12-16: 🔒 Security & Privacy | 🔵 TrivialMake the ruleset dependency a release prerequisite.
This workflow only validates pull requests; it cannot prevent direct pushes or merges when
guardis not required. Require theguardcheck in both thebetaandmainrulesets before relying on this ladder.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/promotion-guard.yml around lines 12 - 16, Update the repository’s beta and main branch rulesets to require the guard status check before treating this promotion workflow as a release prerequisite. Ensure the guard check is configured as a required status check in both rulesets, covering direct pushes and merges that bypass optional validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/promotion-guard.yml:
- Line 49: Update the nearby rationale for the ALLOWED mapping in the workflow
to reference “beta <- dev” instead of “staging <- dev,” preserving the existing
mapping and workflow behavior.
In `@TWIZRR_SELF_HOST_DEPLOYMENT.md`:
- Around line 85-95: Clarify the Contabo IPv4 guidance in the two-box deployment
section: state that each dedicated beta or production box has its own origin
IPv4, and limit any shared-one-IP wording to the single-box beta setup. Keep the
separate-box production requirement unchanged.
- Line 293: Update the WEB_URL / APP_URL / FRONTEND_URL deployment matrix
entries to use complete per-app origins instead of wildcard or placeholder
values: beta should list https://twizrr.com, https://app.beta.twizrr.com, and
https://admin.beta.twizrr.com, while production should list https://twizrr.com,
https://app.twizrr.com, and https://admin.twizrr.com.
- Line 21: Update both Hetzner plan references in
TWIZRR_SELF_HOST_DEPLOYMENT.md, including the deployment comparison and the
detailed recommendation, replacing deprecated CX42 with orderable CX43 and
updating the listed specifications and price to match CX43.
- Around line 295-296: Update the deployment environment-variable documentation
so PAYSTACK_WEBHOOK_SECRET is explicitly configured separately for beta and
production, rather than relying on PAYSTACK_SECRET_KEY fallback. Document
setting each webhook secret only in the matching twizrr-backend environment and
list distinct Paystack dashboard webhook URLs for beta and production.
---
Nitpick comments:
In @.github/workflows/promotion-guard.yml:
- Around line 12-16: Update the repository’s beta and main branch rulesets to
require the guard status check before treating this promotion workflow as a
release prerequisite. Ensure the guard check is configured as a required status
check in both rulesets, covering direct pushes and merges that bypass optional
validation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: df9ac081-0d4e-4523-bbd8-1a6c6641caab
📒 Files selected for processing (2)
.github/workflows/promotion-guard.ymlTWIZRR_SELF_HOST_DEPLOYMENT.md
|
|
||
| # Allowed source for each protected target branch. | ||
| declare -A ALLOWED=( [main]="beta" [beta]="staging" [staging]="dev" ) | ||
| declare -A ALLOWED=( [main]="beta" [beta]="dev" ) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Update the stale staging reference.
The mapping is correct, but the nearby rationale still mentions staging <- dev. Change it to beta <- dev so the workflow documentation matches the enforced ladder.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/promotion-guard.yml at line 49, Update the nearby
rationale for the ALLOWED mapping in the workflow to reference “beta <- dev”
instead of “staging <- dev,” preserving the existing mapping and workflow
behavior.
| | `PAYSTACK_*` / `NEXT_PUBLIC_PAYSTACK_PUBLIC_KEY` | **test** keys | **live** keys | | ||
| | `NEXT_PUBLIC_API_URL` | `https://api.staging.twizrr.com` | `https://api.twizrr.com` | | ||
| | `NEXT_PUBLIC_API_URL` | `https://api.beta.twizrr.com` | `https://api.twizrr.com` | |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Files matching deployment docs:"
git ls-files | rg -n 'TWIZRR_SELF_HOST_DEPLOYMENT\.md|deploy|deployment|paystack|PAYSTACK' || true
echo
echo "Relevant lines in TWIZRR_SELF_HOST_DEPLOYMENT.md around 260-320:"
if [ -f TWIZRR_SELF_HOST_DEPLOYMENT.md ]; then
sed -n '260,320p' TWIZRR_SELF_HOST_DEPLOYMENT.md | cat -n -v
fi
echo
echo "Search for PAYSTACK_WEBHOOK_SECRET in repository:"
rg -n "PAYSTACK_WEBHOOK_SECRET|paystack|PAYSTACK|webhook" TWIZRR_SELF_HOST_DEPLOYMENT.md . --glob '!node_modules' --glob '!dist' --glob '!build' | head -200Repository: coded-devs/twizrr
Length of output: 28248
🌐 Web query:
Paystack webhook signature verification secret key different for sandbox live webhook secret key dashboard
💡 Result:
Yes, Paystack uses different secret keys for its sandbox (test) and live environments [1][2]. Because the webhook signature is generated using your secret key [3][4], the key used to verify the signature must match the environment from which the webhook was sent [1][2]. When configuring your webhook handler, ensure that your application uses the corresponding secret key based on the environment: 1. Test Mode: Use your Test Secret Key (prefixed with sk_test_) to verify signatures for webhooks received in the test environment [1][2]. 2. Live Mode: Use your Live Secret Key (prefixed with sk_live_) to verify signatures for webhooks received in the production environment [1][2]. You can find both sets of keys in your Paystack Dashboard under Settings > API Keys & Webhooks [1][2][4]. It is recommended to use environment variables to manage these keys securely and prevent the accidental use of test keys in production [5][6]. Failure to use the correct key for the respective environment will result in signature verification errors [5].
Citations:
- 1: https://support.paystack.com/en/articles/2123458
- 2: https://paystack.com/docs/api/authentication/
- 3: https://paystack.com/docs/payments/webhooks/
- 4: https://hookdeck.com/webhooks/platforms/guide-to-paystack-webhooks-features-and-best-practices
- 5: https://codeinktechnologies.com/companynews/paystack-webhook-handler-nodejs-never-drop-event
- 6: https://blog.bitsrc.io/getting-started-with-paystack-webhooks-in-nodejs-a-step-by-step-guide-494b3358dbf7
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Search Paystack secret/env var usage:"
rg -n "PAYSTACK_SECRET_KEY|PAYSTACK_WEBHOOK_SECRET|secretKey|webhook" apps backend packages apps/backend/src --glob '!node_modules' --glob '!dist' --glob '!build' 2>/dev/null | head -250 || true
echo
echo "Relevant deployment webhook instructions around line 343:"
sed -n '330,350p' TWIZRR_SELF_HOST_DEPLOYMENT.md | cat -n -vRepository: coded-devs/twizrr
Length of output: 34443
Make PAYSTACK_WEBHOOK_SECRET beta/production-specific.
The backend falls back to PAYSTACK_SECRET_KEY when no webhook secret is set, and Paystack signs webhooks with each environment’s secret key. Keep PAYSTACK_WEBHOOK_SECRET separate from the beta and production secret keys, set them in twizrr-backend only for the matching environment, and configure the beta and prod dashboard webhook URLs separately.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@TWIZRR_SELF_HOST_DEPLOYMENT.md` around lines 295 - 296, Update the deployment
environment-variable documentation so PAYSTACK_WEBHOOK_SECRET is explicitly
configured separately for beta and production, rather than relying on
PAYSTACK_SECRET_KEY fallback. Document setting each webhook secret only in the
matching twizrr-backend environment and list distinct Paystack dashboard webhook
URLs for beta and production.
Source: MCP tools
…ity, concrete matrix origins - Hetzner CX42/CX32 are deprecated (Jan 2026) → CX43 / CX33; growth path CX43→CX53 - clarify 1-IPv4 scope: beta box = one origin IP for all its surfaces; prod box gets its own - env matrix: replace *.beta / "prod hosts" placeholders with concrete per-app origins Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
## What Removes the last stale `staging` references now that the ladder is `dev → beta → main` and staging is being deleted everywhere. ## Changes - **ci.yml** / **prisma-migrate.yml** — drop `staging` from branch triggers → `[dev, beta, main]` - **prisma-migrate.yml** — remove the `staging → 'staging'` GitHub Environment mapping - **promotion-guard.yml** — fix the illustrative fork-guard example (`'staging <- dev'` → `'beta <- dev'`); the *logic* was already de-staged in #670 - **apps/backend/.env.example**, **apps/web/.env.example** — payment-key guidance: TEST keys now cover **local/dev/beta** (beta is a disposable rehearsal on sandbox payments); **LIVE keys are production-only** (previously mislabelled beta as LIVE) ## Note The only remaining `staging` mention is the intentional "Staging was dropped —" historical note in the guard header, which documents the decision. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Chores** - Updated deployment workflows to use the `dev → beta → main` promotion path. - Removed `staging` from automated pull request and migration triggers. - Updated environment selection for development, beta, and production deployments. - **Documentation** - Clarified CORS configuration guidance. - Updated Paystack key instructions for local, development, beta, and production environments. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
What
Retires staging and moves the promotion ladder to
dev → beta → main, and reframes the self-host runbook around the agreed rollout: beta = disposable rehearsal on a VPS, prod on its own dedicated box later, early-access via allowlist on prod (no beta→prod data migration).Why
For a small, fast team, four always-on tiers (dev/staging/beta/main) is overhead.
dev+ per-PR ephemeral preview envs already cover pre-beta testing, so staging's job folds intodev. Beta becomes a throwaway proving ground for the self-hosted Openship stack; real early-access users live on prod behind an allowlist from day one, so nothing ever migrates between environments (they're separate Neon DBs and beta uses sandbox payments).Changes
.github/workflows/promotion-guard.ymlALLOWEDmap →[main]=beta,[beta]=dev(staging removed)branches: [main, beta]dev → beta → mainladderTWIZRR_SELF_HOST_DEPLOYMENT.mddevits own host at cutoverstagingbranch + Neon are retired/dormantFollow-ups (not in this PR)
guardstatus check required in thebetaandmainrulesetsstaginggit branch + Neonep-mute-glitter(leave dormant or delete)🤖 Generated with Claude Code
Summary by CodeRabbit