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.