From 67fcd6d27b3cb05667a21f53718b7aa654ac9754 Mon Sep 17 00:00:00 2001 From: wesship <37167955+wesship@users.noreply.github.com> Date: Sat, 7 Feb 2026 17:31:07 -0700 Subject: [PATCH 1/2] Add Vercel caller workflow example and go-live checklist --- .github/workflows/supreme-ai-deploy.yml | 175 ++++++++++++++++++ .../workflows/vercel-app-deploy-example.yml | 28 +++ .github/workflows/vercel-deploy.yml | 111 +++++++++++ profile/README.md | 59 ++++++ 4 files changed, 373 insertions(+) create mode 100644 .github/workflows/supreme-ai-deploy.yml create mode 100644 .github/workflows/vercel-app-deploy-example.yml create mode 100644 .github/workflows/vercel-deploy.yml diff --git a/.github/workflows/supreme-ai-deploy.yml b/.github/workflows/supreme-ai-deploy.yml new file mode 100644 index 0000000..3891c4b --- /dev/null +++ b/.github/workflows/supreme-ai-deploy.yml @@ -0,0 +1,175 @@ +name: Supreme AI Deployment Hub CI/CD + +on: + push: + branches: + - main + - master + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: deploy-${{ github.ref }} + cancel-in-progress: true + +env: + REGISTRY: ghcr.io + CONTAINER_NAME: supreme-ai-hub + APP_PORT: 3000 + HOST_PORT: 80 + BIND_IP: 127.0.0.1 + +jobs: + validate: + name: Validate, test, and build + runs-on: ubuntu-latest + timeout-minutes: 20 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Lint + run: npm run lint --if-present + + - name: Unit tests + run: npm test --if-present -- --ci + + - name: Build + run: npm run build --if-present + + containerize: + name: Build and push image + runs-on: ubuntu-latest + needs: validate + if: github.event_name != 'pull_request' + timeout-minutes: 30 + permissions: + contents: read + packages: write + outputs: + image_tag: ${{ steps.vars.outputs.image_tag }} + image_repo: ${{ steps.vars.outputs.image_repo }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set image variables + id: vars + run: | + IMAGE_REPO=$(echo "${GITHUB_REPOSITORY}" | tr '[:upper:]' '[:lower:]') + echo "image_repo=${IMAGE_REPO}" >> "$GITHUB_OUTPUT" + echo "image_tag=sha-${GITHUB_SHA}" >> "$GITHUB_OUTPUT" + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ steps.vars.outputs.image_repo }} + tags: | + type=raw,value=${{ steps.vars.outputs.image_tag }} + type=raw,value=latest + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + deploy: + name: Deploy to server + runs-on: ubuntu-latest + needs: containerize + if: github.event_name != 'pull_request' + timeout-minutes: 20 + environment: + name: production + + steps: + - name: Validate required secrets are present + env: + DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} + DEPLOY_USER: ${{ secrets.DEPLOY_USER }} + DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} + GHCR_USERNAME: ${{ secrets.GHCR_USERNAME }} + GHCR_TOKEN: ${{ secrets.GHCR_TOKEN }} + run: | + missing=0 + for name in DEPLOY_HOST DEPLOY_USER DEPLOY_SSH_KEY GHCR_USERNAME GHCR_TOKEN; do + if [ -z "${!name}" ]; then + echo "Missing required secret: ${name}" >&2 + missing=1 + fi + done + if [ "$missing" -ne 0 ]; then + exit 1 + fi + + - name: Deploy and verify + uses: appleboy/ssh-action@v1.0.3 + env: + IMAGE_REPO: ${{ needs.containerize.outputs.image_repo }} + IMAGE_TAG: ${{ needs.containerize.outputs.image_tag }} + GHCR_USER: ${{ secrets.GHCR_USERNAME }} + GHCR_TOKEN: ${{ secrets.GHCR_TOKEN }} + HEALTHCHECK_URL: ${{ secrets.HEALTHCHECK_URL }} + DEPLOY_BIND_IP: ${{ secrets.DEPLOY_BIND_IP }} + with: + host: ${{ secrets.DEPLOY_HOST }} + username: ${{ secrets.DEPLOY_USER }} + key: ${{ secrets.DEPLOY_SSH_KEY }} + script_stop: true + envs: IMAGE_REPO,IMAGE_TAG,GHCR_USER,GHCR_TOKEN,HEALTHCHECK_URL,DEPLOY_BIND_IP + script: | + set -euxo pipefail + IMAGE="${{ env.REGISTRY }}/${IMAGE_REPO}:${IMAGE_TAG}" + HEALTH_URL="${HEALTHCHECK_URL:-http://localhost/health}" + BIND_IP="${DEPLOY_BIND_IP:-${{ env.BIND_IP }}}" + + printf '%s' "$GHCR_TOKEN" | docker login ${{ env.REGISTRY }} -u "$GHCR_USER" --password-stdin + docker pull "$IMAGE" + + docker stop "${{ env.CONTAINER_NAME }}" || true + docker rm "${{ env.CONTAINER_NAME }}" || true + + docker run -d --name "${{ env.CONTAINER_NAME }}" --restart unless-stopped \ + -p ${BIND_IP}:${{ env.HOST_PORT }}:${{ env.APP_PORT }} \ + "$IMAGE" + + for attempt in {1..12}; do + if curl -fsS "$HEALTH_URL" > /dev/null; then + echo "Health check passed on attempt ${attempt}" + docker image prune -f || true + exit 0 + fi + sleep 5 + done + + echo "Health check failed for ${HEALTH_URL}" >&2 + docker logs --tail 100 "${{ env.CONTAINER_NAME }}" || true + exit 1 diff --git a/.github/workflows/vercel-app-deploy-example.yml b/.github/workflows/vercel-app-deploy-example.yml new file mode 100644 index 0000000..3e07269 --- /dev/null +++ b/.github/workflows/vercel-app-deploy-example.yml @@ -0,0 +1,28 @@ +name: Vercel Deploy (Example Caller) + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + deploy: + uses: wesship/.github/.github/workflows/vercel-deploy.yml@main + with: + environment: production + production: true + working-directory: . + node-version: '20' + vercel-version: 'latest' + secrets: + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + + announce: + runs-on: ubuntu-latest + needs: deploy + steps: + - name: Print deployed URL + run: echo "Deployed URL -> ${{ needs.deploy.outputs.deployment_url }}" diff --git a/.github/workflows/vercel-deploy.yml b/.github/workflows/vercel-deploy.yml new file mode 100644 index 0000000..d48ce2c --- /dev/null +++ b/.github/workflows/vercel-deploy.yml @@ -0,0 +1,111 @@ +name: Reusable Vercel Deploy + +on: + workflow_call: + inputs: + environment: + description: Vercel target environment + required: false + default: production + type: string + working-directory: + description: Directory of app source in caller repository + required: false + default: . + type: string + production: + description: Deploy to production (`--prod`) + required: false + default: true + type: boolean + node-version: + description: Node.js version used for CLI execution + required: false + default: '20' + type: string + vercel-version: + description: Vercel CLI version + required: false + default: 'latest' + type: string + secrets: + VERCEL_TOKEN: + required: true + VERCEL_ORG_ID: + required: true + VERCEL_PROJECT_ID: + required: true + outputs: + deployment_url: + description: URL returned by Vercel deploy + value: ${{ jobs.deploy.outputs.deployment_url }} + +permissions: + contents: read + +jobs: + deploy: + runs-on: ubuntu-latest + timeout-minutes: 20 + outputs: + deployment_url: ${{ steps.deploy.outputs.deployment_url }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + + - name: Install Vercel CLI + run: npm install --global "vercel@${{ inputs.vercel-version }}" + + - name: Validate working directory + working-directory: ${{ inputs.working-directory }} + run: | + test -f package.json || { + echo "package.json not found in $PWD" >&2 + exit 1 + } + + - name: Pull Vercel environment + working-directory: ${{ inputs.working-directory }} + env: + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + run: | + vercel pull --yes --environment=${{ inputs.environment }} --token="$VERCEL_TOKEN" + + - name: Build with Vercel + working-directory: ${{ inputs.working-directory }} + env: + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + run: | + vercel build --token="$VERCEL_TOKEN" + + - name: Deploy prebuilt output + id: deploy + working-directory: ${{ inputs.working-directory }} + env: + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + run: | + set -euo pipefail + DEPLOY_ARGS="--prebuilt --yes --token=$VERCEL_TOKEN" + if [ "${{ inputs.production }}" = "true" ]; then + DEPLOY_ARGS="$DEPLOY_ARGS --prod" + fi + + DEPLOY_OUTPUT=$(vercel deploy $DEPLOY_ARGS 2>&1) + echo "$DEPLOY_OUTPUT" + + DEPLOYMENT_URL=$(printf '%s\n' "$DEPLOY_OUTPUT" | grep -Eo "https://[A-Za-z0-9.-]+\.vercel\.app" | tail -n 1) + if [ -z "$DEPLOYMENT_URL" ]; then + echo "Could not detect deployment URL from Vercel output" >&2 + exit 1 + fi + + echo "deployment_url=$DEPLOYMENT_URL" >> "$GITHUB_OUTPUT" + echo "### Vercel Deployment\n- URL: $DEPLOYMENT_URL" >> "$GITHUB_STEP_SUMMARY" diff --git a/profile/README.md b/profile/README.md index 103e942..8287d05 100644 --- a/profile/README.md +++ b/profile/README.md @@ -19,3 +19,62 @@ n8n is a low-code automation tool. With over 220 pre-built integrations and a ge - 🌱 We were Sequoia's first seed investment in Germany, and recently raised a $12m Series A round, led by Felicis Ventures We're on a mission to give technical superpowers to everyone with a computer. Join us! + +## Supreme AI Deployment Hub: debug + deploy workflow + +If your `wesship/supreme-ai-deployment-hub` app is failing in production, this repo now includes a hardened GitHub Actions workflow at `.github/workflows/supreme-ai-deploy.yml`. + +It performs: +- dependency installation and app validation (`npm ci`, lint, tests, build), +- container image publishing to GHCR, +- remote deployment via SSH, +- immediate health check retries with failure logs for faster debugging. + +Required repository secrets: +- `DEPLOY_HOST` +- `DEPLOY_USER` +- `DEPLOY_SSH_KEY` +- `GHCR_USERNAME` +- `GHCR_TOKEN` (PAT with `read:packages`) + +Optional repository secrets: +- `HEALTHCHECK_URL` (defaults to `http://localhost/health`) +- `DEPLOY_BIND_IP` (defaults to `127.0.0.1`; set to `0.0.0.0` only if you explicitly want public exposure) + +Deployability checklist: +- Ensure your app image exposes port `3000` (or update `APP_PORT` in workflow). +- Ensure target VM has Docker + curl installed and SSH key access configured. +- Ensure GHCR package visibility and token permissions allow pull from deploy host. + +Security hardening included: +- Deployment now binds service to `127.0.0.1` by default to reduce accidental public exposure (addresses common n8n exposure mistakes). +- GHCR login on the server uses `--password-stdin` to avoid leaking tokens in process args. + +Vercel note: +- This repo only contains GitHub profile/workflow files and no Vercel project config, so Vercel-specific runtime errors must be fixed in the actual app repo (`wesship/supreme-ai-deployment-hub`). + +Recommendations: +- Use environment protection rules for `production` (required reviewers + wait timer). +- Rotate deploy and GHCR credentials regularly and scope them minimally. +- Pin your app runtime with a tested Docker image base and keep lockfiles committed. +- Add smoke tests for your critical API routes after deploy. + +This gives you a repeatable pipeline to debug failures earlier (in CI) and deploy only after checks pass. + +Vercel deployment (for `https://vercel.com/wesships-projects`): +- A reusable workflow is available at `.github/workflows/vercel-deploy.yml` for app repos to call. +- Required repo secrets in the app repo: `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_PROJECT_ID`. +- Supports Lovable-generated apps too (example project: `https://lovable.dev/projects/b5eb8a4d-3709-4e3f-930c-ab5ab4b96560`) by deploying from a configurable `working-directory`. +- Typical usage in the app repo: + - `uses: wesship/.github/.github/workflows/vercel-deploy.yml@main` + - `with.environment: production` + - `with.production: true` +- The reusable workflow exports `deployment_url` so callers can post the deployed URL to PR comments/check summaries. +- If Vercel still errors, verify project linkage (`vercel pull`), build output (`vercel build`), and runtime env vars in the Vercel dashboard. + +Go-live quick start: +- 1) Add the three Vercel secrets in your app repo: `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_PROJECT_ID`. +- 2) Copy `.github/workflows/vercel-app-deploy-example.yml` into your app repo and adjust `working-directory` (for Lovable monorepos/subfolders). +- 3) Push to `main` and verify the workflow summary includes the `deployment_url` output. +- 4) In Vercel dashboard, set Production domain + environment variables, then run one manual `workflow_dispatch` smoke deploy. + From 79459300888e85a678a0a9212fcffc25826be6e9 Mon Sep 17 00:00:00 2001 From: wesship <37167955+wesship@users.noreply.github.com> Date: Mon, 9 Feb 2026 02:20:21 -0700 Subject: [PATCH 2/2] Refine reusable deploy workflows for go-live readiness --- .github/workflows/supreme-ai-deploy.yml | 90 ++++++++++--------- .../workflows/vercel-app-deploy-example.yml | 3 - profile/README.md | 50 ++++------- 3 files changed, 66 insertions(+), 77 deletions(-) diff --git a/.github/workflows/supreme-ai-deploy.yml b/.github/workflows/supreme-ai-deploy.yml index 3891c4b..3214c05 100644 --- a/.github/workflows/supreme-ai-deploy.yml +++ b/.github/workflows/supreme-ai-deploy.yml @@ -1,26 +1,57 @@ -name: Supreme AI Deployment Hub CI/CD +name: Reusable Supreme AI Deploy on: - push: - branches: - - main - - master - pull_request: + workflow_call: + inputs: + node-version: + description: Node.js version used during validation + required: false + default: '20' + type: string + app-port: + description: Container application port + required: false + default: 3000 + type: number + host-port: + description: Host port exposed on the deploy server + required: false + default: 80 + type: number + bind-ip: + description: Bind address on deploy host (127.0.0.1 recommended) + required: false + default: '127.0.0.1' + type: string + healthcheck-url: + description: Health endpoint URL checked from deploy host + required: false + default: 'http://localhost/health' + type: string + secrets: + DEPLOY_HOST: + required: true + DEPLOY_USER: + required: true + DEPLOY_SSH_KEY: + required: true + GHCR_USERNAME: + required: true + GHCR_TOKEN: + required: true + workflow_dispatch: permissions: contents: read concurrency: - group: deploy-${{ github.ref }} + group: supreme-ai-deploy-${{ github.ref }} cancel-in-progress: true env: REGISTRY: ghcr.io CONTAINER_NAME: supreme-ai-hub - APP_PORT: 3000 - HOST_PORT: 80 - BIND_IP: 127.0.0.1 jobs: validate: @@ -35,7 +66,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: ${{ inputs.node-version || '20' }} cache: npm - name: Install dependencies @@ -54,7 +85,6 @@ jobs: name: Build and push image runs-on: ubuntu-latest needs: validate - if: github.event_name != 'pull_request' timeout-minutes: 30 permissions: contents: read @@ -105,31 +135,11 @@ jobs: name: Deploy to server runs-on: ubuntu-latest needs: containerize - if: github.event_name != 'pull_request' timeout-minutes: 20 environment: name: production steps: - - name: Validate required secrets are present - env: - DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} - DEPLOY_USER: ${{ secrets.DEPLOY_USER }} - DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} - GHCR_USERNAME: ${{ secrets.GHCR_USERNAME }} - GHCR_TOKEN: ${{ secrets.GHCR_TOKEN }} - run: | - missing=0 - for name in DEPLOY_HOST DEPLOY_USER DEPLOY_SSH_KEY GHCR_USERNAME GHCR_TOKEN; do - if [ -z "${!name}" ]; then - echo "Missing required secret: ${name}" >&2 - missing=1 - fi - done - if [ "$missing" -ne 0 ]; then - exit 1 - fi - - name: Deploy and verify uses: appleboy/ssh-action@v1.0.3 env: @@ -137,19 +147,19 @@ jobs: IMAGE_TAG: ${{ needs.containerize.outputs.image_tag }} GHCR_USER: ${{ secrets.GHCR_USERNAME }} GHCR_TOKEN: ${{ secrets.GHCR_TOKEN }} - HEALTHCHECK_URL: ${{ secrets.HEALTHCHECK_URL }} - DEPLOY_BIND_IP: ${{ secrets.DEPLOY_BIND_IP }} + HEALTHCHECK_URL: ${{ inputs.healthcheck-url || 'http://localhost/health' }} + DEPLOY_BIND_IP: ${{ inputs.bind-ip || '127.0.0.1' }} + APP_PORT: ${{ inputs.app-port || 3000 }} + HOST_PORT: ${{ inputs.host-port || 80 }} with: host: ${{ secrets.DEPLOY_HOST }} username: ${{ secrets.DEPLOY_USER }} key: ${{ secrets.DEPLOY_SSH_KEY }} script_stop: true - envs: IMAGE_REPO,IMAGE_TAG,GHCR_USER,GHCR_TOKEN,HEALTHCHECK_URL,DEPLOY_BIND_IP + envs: IMAGE_REPO,IMAGE_TAG,GHCR_USER,GHCR_TOKEN,HEALTHCHECK_URL,DEPLOY_BIND_IP,APP_PORT,HOST_PORT script: | set -euxo pipefail IMAGE="${{ env.REGISTRY }}/${IMAGE_REPO}:${IMAGE_TAG}" - HEALTH_URL="${HEALTHCHECK_URL:-http://localhost/health}" - BIND_IP="${DEPLOY_BIND_IP:-${{ env.BIND_IP }}}" printf '%s' "$GHCR_TOKEN" | docker login ${{ env.REGISTRY }} -u "$GHCR_USER" --password-stdin docker pull "$IMAGE" @@ -158,11 +168,11 @@ jobs: docker rm "${{ env.CONTAINER_NAME }}" || true docker run -d --name "${{ env.CONTAINER_NAME }}" --restart unless-stopped \ - -p ${BIND_IP}:${{ env.HOST_PORT }}:${{ env.APP_PORT }} \ + -p ${DEPLOY_BIND_IP}:${HOST_PORT}:${APP_PORT} \ "$IMAGE" for attempt in {1..12}; do - if curl -fsS "$HEALTH_URL" > /dev/null; then + if curl -fsS "$HEALTHCHECK_URL" > /dev/null; then echo "Health check passed on attempt ${attempt}" docker image prune -f || true exit 0 @@ -170,6 +180,6 @@ jobs: sleep 5 done - echo "Health check failed for ${HEALTH_URL}" >&2 + echo "Health check failed for ${HEALTHCHECK_URL}" >&2 docker logs --tail 100 "${{ env.CONTAINER_NAME }}" || true exit 1 diff --git a/.github/workflows/vercel-app-deploy-example.yml b/.github/workflows/vercel-app-deploy-example.yml index 3e07269..5644a0d 100644 --- a/.github/workflows/vercel-app-deploy-example.yml +++ b/.github/workflows/vercel-app-deploy-example.yml @@ -1,9 +1,6 @@ name: Vercel Deploy (Example Caller) on: - push: - branches: - - main workflow_dispatch: jobs: diff --git a/profile/README.md b/profile/README.md index 8287d05..11b2ff5 100644 --- a/profile/README.md +++ b/profile/README.md @@ -22,59 +22,41 @@ We're on a mission to give technical superpowers to everyone with a computer. containerize -> SSH deploy. +- `.github/workflows/vercel-deploy.yml`: reusable Vercel workflow for `vercel pull`, `vercel build`, and `vercel deploy --prebuilt`. -Required repository secrets: +For Supreme AI server deploy callers, provide these required secrets from the app repo: - `DEPLOY_HOST` - `DEPLOY_USER` - `DEPLOY_SSH_KEY` - `GHCR_USERNAME` - `GHCR_TOKEN` (PAT with `read:packages`) -Optional repository secrets: -- `HEALTHCHECK_URL` (defaults to `http://localhost/health`) -- `DEPLOY_BIND_IP` (defaults to `127.0.0.1`; set to `0.0.0.0` only if you explicitly want public exposure) +Recommended inputs when calling `supreme-ai-deploy.yml`: +- `healthcheck-url` (default: `http://localhost/health`) +- `bind-ip` (default: `127.0.0.1`; set `0.0.0.0` only when you intentionally expose publicly) +- `app-port` / `host-port` (defaults: `3000` / `80`) Deployability checklist: -- Ensure your app image exposes port `3000` (or update `APP_PORT` in workflow). +- Ensure your app repo includes a valid `package.json`, lockfile, and `Dockerfile`. - Ensure target VM has Docker + curl installed and SSH key access configured. - Ensure GHCR package visibility and token permissions allow pull from deploy host. Security hardening included: -- Deployment now binds service to `127.0.0.1` by default to reduce accidental public exposure (addresses common n8n exposure mistakes). +- Deployment binds service to `127.0.0.1` by default to reduce accidental public exposure. - GHCR login on the server uses `--password-stdin` to avoid leaking tokens in process args. -Vercel note: -- This repo only contains GitHub profile/workflow files and no Vercel project config, so Vercel-specific runtime errors must be fixed in the actual app repo (`wesship/supreme-ai-deployment-hub`). - -Recommendations: -- Use environment protection rules for `production` (required reviewers + wait timer). -- Rotate deploy and GHCR credentials regularly and scope them minimally. -- Pin your app runtime with a tested Docker image base and keep lockfiles committed. -- Add smoke tests for your critical API routes after deploy. - -This gives you a repeatable pipeline to debug failures earlier (in CI) and deploy only after checks pass. - Vercel deployment (for `https://vercel.com/wesships-projects`): -- A reusable workflow is available at `.github/workflows/vercel-deploy.yml` for app repos to call. -- Required repo secrets in the app repo: `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_PROJECT_ID`. +- Required app-repo secrets: `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_PROJECT_ID`. - Supports Lovable-generated apps too (example project: `https://lovable.dev/projects/b5eb8a4d-3709-4e3f-930c-ab5ab4b96560`) by deploying from a configurable `working-directory`. -- Typical usage in the app repo: - - `uses: wesship/.github/.github/workflows/vercel-deploy.yml@main` - - `with.environment: production` - - `with.production: true` - The reusable workflow exports `deployment_url` so callers can post the deployed URL to PR comments/check summaries. -- If Vercel still errors, verify project linkage (`vercel pull`), build output (`vercel build`), and runtime env vars in the Vercel dashboard. Go-live quick start: -- 1) Add the three Vercel secrets in your app repo: `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_PROJECT_ID`. -- 2) Copy `.github/workflows/vercel-app-deploy-example.yml` into your app repo and adjust `working-directory` (for Lovable monorepos/subfolders). -- 3) Push to `main` and verify the workflow summary includes the `deployment_url` output. -- 4) In Vercel dashboard, set Production domain + environment variables, then run one manual `workflow_dispatch` smoke deploy. +- 1) Add required secrets in your app repo. +- 2) Copy `.github/workflows/vercel-app-deploy-example.yml` into your app repo. +- 3) Add a second caller workflow in the app repo for `wesship/.github/.github/workflows/supreme-ai-deploy.yml@main`. +- 4) Run one manual `workflow_dispatch` in each workflow and confirm health checks / deployment URL output.