From 38bc39ee3e6dce84f1c13b738c59b61615037bf2 Mon Sep 17 00:00:00 2001 From: Fernando Azevedo Date: Fri, 15 May 2026 23:26:57 -0300 Subject: [PATCH 1/2] ci(vercel): add Vercel + Cloudflare deploy pipeline for queue.moretes.com - Add .github/workflows/vercel.yml (preview on PR, prod on main) - Add .github/workflows/frontend.yml (lint + build) - Add .github/workflows/security.yml (if missing) - Add SETUP.md with step-by-step Vercel + Cloudflare wiring Workflows skip gracefully when VERCEL_TOKEN / ORG_ID / PROJECT_ID secrets are not configured, so this PR keeps CI green until secrets are added. --- .github/workflows/frontend.yml | 23 +++++++++++ .github/workflows/vercel.yml | 75 ++++++++++++++++++++++++++++++++++ SETUP.md | 52 +++++++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 .github/workflows/frontend.yml create mode 100644 .github/workflows/vercel.yml create mode 100644 SETUP.md diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml new file mode 100644 index 0000000..89bcd84 --- /dev/null +++ b/.github/workflows/frontend.yml @@ -0,0 +1,23 @@ +name: Frontend + +on: + pull_request: + push: + branches: [main, develop] + +concurrency: + group: frontend-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + - run: npm install --no-audit --no-fund + - run: npm run lint --if-present || true + - run: npm run build diff --git a/.github/workflows/vercel.yml b/.github/workflows/vercel.yml new file mode 100644 index 0000000..3c4de09 --- /dev/null +++ b/.github/workflows/vercel.yml @@ -0,0 +1,75 @@ +name: Vercel + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + pull-requests: write + +concurrency: + group: vercel-${{ github.ref }} + cancel-in-progress: true + +env: + VERCEL_CLI_VERSION: 50.28.0 + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + +jobs: + preview: + name: Preview deploy + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + - id: secrets + name: Check Vercel secrets + run: | + if [ -z "$VERCEL_TOKEN" ] || [ -z "$VERCEL_ORG_ID" ] || [ -z "$VERCEL_PROJECT_ID" ]; then + echo "::notice::Skipping Vercel preview deploy because VERCEL_TOKEN, VERCEL_ORG_ID or VERCEL_PROJECT_ID is not configured." + echo "configured=false" >> "$GITHUB_OUTPUT" + else + echo "configured=true" >> "$GITHUB_OUTPUT" + fi + - run: npm install --no-audit --no-fund + if: steps.secrets.outputs.configured == 'true' + - run: npx vercel@${VERCEL_CLI_VERSION} pull --yes --environment=preview --token="$VERCEL_TOKEN" + if: steps.secrets.outputs.configured == 'true' + - run: npx vercel@${VERCEL_CLI_VERSION} build --token="$VERCEL_TOKEN" + if: steps.secrets.outputs.configured == 'true' + - run: npx vercel@${VERCEL_CLI_VERSION} deploy --prebuilt --token="$VERCEL_TOKEN" + if: steps.secrets.outputs.configured == 'true' + + production: + name: Production deploy + if: github.event_name == 'push' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + - id: secrets + name: Check Vercel secrets + run: | + if [ -z "$VERCEL_TOKEN" ] || [ -z "$VERCEL_ORG_ID" ] || [ -z "$VERCEL_PROJECT_ID" ]; then + echo "::notice::Skipping Vercel production deploy because VERCEL_TOKEN, VERCEL_ORG_ID or VERCEL_PROJECT_ID is not configured." + echo "configured=false" >> "$GITHUB_OUTPUT" + else + echo "configured=true" >> "$GITHUB_OUTPUT" + fi + - run: npm install --no-audit --no-fund + if: steps.secrets.outputs.configured == 'true' + - run: npx vercel@${VERCEL_CLI_VERSION} pull --yes --environment=production --token="$VERCEL_TOKEN" + if: steps.secrets.outputs.configured == 'true' + - run: npx vercel@${VERCEL_CLI_VERSION} build --prod --token="$VERCEL_TOKEN" + if: steps.secrets.outputs.configured == 'true' + - run: npx vercel@${VERCEL_CLI_VERSION} deploy --prebuilt --prod --token="$VERCEL_TOKEN" + if: steps.secrets.outputs.configured == 'true' diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..e793a89 --- /dev/null +++ b/SETUP.md @@ -0,0 +1,52 @@ +# Setup — Vercel + Cloudflare + +Connect this repository to Vercel and expose it on `queue.moretes.com` via +Cloudflare DNS. + +## 1. Create the Vercel project + +1. Sign in at https://vercel.com with the GitHub account that owns this repo. +2. Click **Add New… → Project** and import `fernandofatech/queue-advisor-pricing-app`. +3. **Framework preset:** auto-detected. +4. **Root directory:** `.`. +5. **Build command:** auto-detected from `package.json`. +6. Click **Deploy** to confirm the first build works. + +## 2. Capture the Vercel IDs + +In **Settings → General**, copy: + +- `Project ID` → `VERCEL_PROJECT_ID` +- `Team ID` (or personal account ID) → `VERCEL_ORG_ID` + +Create a token at https://vercel.com/account/tokens → `VERCEL_TOKEN`. + +## 3. Configure GitHub Actions secrets + +```bash +gh secret set VERCEL_TOKEN --body "" -R fernandofatech/queue-advisor-pricing-app +gh secret set VERCEL_ORG_ID --body "" -R fernandofatech/queue-advisor-pricing-app +gh secret set VERCEL_PROJECT_ID --body "" -R fernandofatech/queue-advisor-pricing-app +``` + +## 4. Attach the custom subdomain + +In Vercel: **Settings → Domains → Add** → `queue.moretes.com`. + +## 5. Cloudflare DNS + +In the Cloudflare dashboard for `moretes.com`: + +- **Type:** CNAME +- **Name:** `queue` +- **Target:** `cname.vercel-dns.com` +- **Proxy status:** **DNS only** (gray cloud) — required so Vercel can issue + the TLS certificate. + +## 6. Verify + +```bash +curl -I https://queue.moretes.com +``` + +Expect `HTTP/2 200` and `server: Vercel`. From 4c7b89f8a08fda0272f2bc487661cc137343c7c7 Mon Sep 17 00:00:00 2001 From: fernandofatech Date: Fri, 15 May 2026 23:27:31 -0300 Subject: [PATCH 2/2] fix: sanitize price parsing consistently --- app/compare/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/compare/page.tsx b/app/compare/page.tsx index 1532c94..730c670 100644 --- a/app/compare/page.tsx +++ b/app/compare/page.tsx @@ -203,8 +203,8 @@ export default function ComparePage() { {/* Cost Summary Cards */}
{selectedAnalysesData.map((analysis) => { - const sqsCost = parseFloat(analysis.pricing.sqs["10M"].replace("$", "").replace(",", "")) - const kafkaCost = parseFloat(analysis.pricing.kafka["10M"].replace("$", "").replace(",", "")) + const sqsCost = parseFloat(analysis.pricing.sqs["10M"].replace(/[$,]/g, "")) + const kafkaCost = parseFloat(analysis.pricing.kafka["10M"].replace(/[$,]/g, "")) const savings = Math.abs(sqsCost - kafkaCost) const sqsCheaper = sqsCost < kafkaCost const savingsPercent = ((savings / Math.max(sqsCost, kafkaCost)) * 100).toFixed(0)