Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 40 additions & 27 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ jobs:
set -euo pipefail

base_url=$(node -e 'const u = new URL(process.env.WEBHOOK_URL); console.log(`${u.protocol}//${u.host}`)')
health_url="${base_url}/api/health/auth-config"
auth_health_url="${base_url}/api/health/auth-config"
generic_health_url="${base_url}/api/health"
health_url="$auth_health_url"

echo "==> Running deploy smoke check: $health_url"

Expand All @@ -127,41 +129,52 @@ jobs:
http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | sed '$d')

if [ "$http_code" = "404" ] && [ "$health_url" = "$auth_health_url" ]; then
echo "Auth-config health endpoint not available. Falling back to generic health check."
health_url="$generic_health_url"
continue
fi

if [ "$http_code" = "200" ]; then
HEALTH_BODY="$body" node - <<'NODE'
const body = process.env.HEALTH_BODY ?? '';
let parsed;
try {
parsed = JSON.parse(body);
} catch {
console.error('::error::auth-config returned invalid JSON');
process.exit(1);
}

const status = parsed?.status ?? 'unknown';
const hasLegacyDomain = Boolean(parsed?.auth?.hasLegacyDomain);
const warnings = Array.isArray(parsed?.warnings) ? parsed.warnings : [];

if (status !== 'ok' || hasLegacyDomain || warnings.length > 0) {
console.error(
`::error::OAuth auth-config smoke check failed (status=${status}, hasLegacyDomain=${hasLegacyDomain}, warnings=${warnings.length})`,
);
if (warnings.length > 0) {
console.error(`::error::Warnings: ${warnings.join(' | ')}`);
if [ "$health_url" = "$generic_health_url" ]; then
echo "==> Generic health check passed"
exit 0
fi

HEALTH_BODY="$body" node -e '
const body = process.env.HEALTH_BODY ?? "";
let parsed;
try {
parsed = JSON.parse(body);
} catch {
console.error("::error::auth-config returned invalid JSON");
process.exit(1);
}

const status = parsed?.status ?? "unknown";
const hasLegacyDomain = Boolean(parsed?.auth?.hasLegacyDomain);
const warnings = Array.isArray(parsed?.warnings) ? parsed.warnings : [];

if (status !== "ok" || hasLegacyDomain || warnings.length > 0) {
console.error(
`::error::OAuth auth-config smoke check failed (status=${status}, hasLegacyDomain=${hasLegacyDomain}, warnings=${warnings.length})`,
);
if (warnings.length > 0) {
console.error(`::error::Warnings: ${warnings.join(" | ")}`);
}
process.exit(1);
}
process.exit(1);
}

console.log('==> OAuth auth-config smoke check passed');
NODE
console.log("==> OAuth auth-config smoke check passed");
'
exit 0
fi

echo "Service not ready yet (HTTP $http_code). Waiting 10s..."
echo "Service not ready yet at $health_url (HTTP $http_code). Waiting 10s..."
sleep 10
done

echo "::error::Timed out waiting for /api/health/auth-config to become available"
echo "::error::Timed out waiting for health endpoint to become available"
exit 1

- name: Notify failure
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

- Backend CORS now accepts configured origins plus `*.lucassantana.tech` and `*.luk-homeserver.com.br` hosts for dashboard/API split-domain setups
- Frontend API client now auto-resolves hosted API base to `api.lucassantana.tech` or `api.luk-homeserver.com.br` when `VITE_API_BASE_URL` is not set
- Frontend API client now auto-resolves hosted API base to `lucky-api.lucassantana.tech` or `api.luk-homeserver.com.br` when `VITE_API_BASE_URL` is not set
- Deploy smoke check now falls back to `/api/health` when `/api/health/auth-config` is unavailable
- Vercel routing no longer rewrites `/api/*` back to the same Lucky host, preventing `508 INFINITE_LOOP` on OAuth login
- Frontend API base URL now supports `VITE_API_BASE_URL` for hosted deployments that use a separate backend origin
- Deploy webhook trigger now uses strict curl connect/request timeouts to avoid long hangs in CI deploy jobs
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ Triggers the GitHub `Deploy to Homelab` workflow, waits for completion, and show
Vercel note: `vercel.json` runs `npm run db:generate` before `build:shared` and `build:frontend` to ensure Prisma generated client files are present during cloud builds.
For hosted frontend deployments, set `VITE_API_BASE_URL` to your backend API origin
(example: `https://api.yourdomain.com/api`) to avoid auth/API loop misrouting.
Without `VITE_API_BASE_URL`, frontend now auto-targets `api.lucassantana.tech` for
Without `VITE_API_BASE_URL`, frontend now auto-targets `lucky-api.lucassantana.tech` for
`*.lucassantana.tech` hosts and `api.luk-homeserver.com.br` for `*.luk-homeserver.com.br`.

## Environment Variables
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/services/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const inferApiBase = (): string => {
hostname === 'lucassantana.tech' ||
hostname.endsWith('.lucassantana.tech')
) {
return `${protocol}//api.lucassantana.tech/api`
return `${protocol}//lucky-api.lucassantana.tech/api`
}

if (
Expand Down