deploy: make Phoenix redeploys archive-safe
Some checks failed
Deploy to Phoenix / deploy (push) Failing after 5s
phoenix-deploy Deploy failed: Command failed: bash scripts/deployment/phoenix-deploy-currencicombo-from-workspace.sh
[currencicombo-phoenix] packing s
Some checks failed
Deploy to Phoenix / deploy (push) Failing after 5s
phoenix-deploy Deploy failed: Command failed: bash scripts/deployment/phoenix-deploy-currencicombo-from-workspace.sh
[currencicombo-phoenix] packing s
This commit is contained in:
@@ -1,27 +1,42 @@
|
||||
import { z } from "zod";
|
||||
|
||||
const emptyToUndefined = (value: unknown) => {
|
||||
if (typeof value !== "string") return value;
|
||||
const trimmed = value.trim();
|
||||
return trimmed === "" ? undefined : trimmed;
|
||||
};
|
||||
|
||||
const optionalString = () => z.preprocess(emptyToUndefined, z.string().optional());
|
||||
const optionalUrl = () => z.preprocess(emptyToUndefined, z.string().url().optional());
|
||||
|
||||
/**
|
||||
* Environment variable validation schema
|
||||
*/
|
||||
const envSchema = z.object({
|
||||
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
|
||||
PORT: z.string().transform(Number).pipe(z.number().int().positive()),
|
||||
DATABASE_URL: z.string().url().optional(),
|
||||
API_KEYS: z.string().optional(),
|
||||
REDIS_URL: z.string().url().optional(),
|
||||
DATABASE_URL: optionalUrl(),
|
||||
API_KEYS: optionalString(),
|
||||
REDIS_URL: optionalUrl(),
|
||||
LOG_LEVEL: z.enum(["error", "warn", "info", "debug"]).default("info"),
|
||||
ALLOWED_IPS: z.string().optional(),
|
||||
ALLOWED_IPS: optionalString(),
|
||||
SESSION_SECRET: z.string().min(32),
|
||||
JWT_SECRET: z.string().min(32).optional(),
|
||||
AZURE_KEY_VAULT_URL: z.string().url().optional(),
|
||||
AWS_SECRETS_MANAGER_REGION: z.string().optional(),
|
||||
SENTRY_DSN: z.string().url().optional(),
|
||||
JWT_SECRET: z.preprocess(emptyToUndefined, z.string().min(32).optional()),
|
||||
AZURE_KEY_VAULT_URL: optionalUrl(),
|
||||
AWS_SECRETS_MANAGER_REGION: optionalString(),
|
||||
SENTRY_DSN: optionalUrl(),
|
||||
// Chain-138 + NotaryRegistry wiring (arch §4.5). All optional; when
|
||||
// absent the notary adapter falls back to its deterministic mock.
|
||||
CHAIN_138_RPC_URL: z.string().url().optional(),
|
||||
CHAIN_138_CHAIN_ID: z.string().regex(/^\d+$/).optional(),
|
||||
NOTARY_REGISTRY_ADDRESS: z.string().regex(/^0x[0-9a-fA-F]{40}$/).optional(),
|
||||
ORCHESTRATOR_PRIVATE_KEY: z.string().regex(/^0x[0-9a-fA-F]{64}$/).optional(),
|
||||
CHAIN_138_RPC_URL: optionalUrl(),
|
||||
CHAIN_138_CHAIN_ID: z.preprocess(emptyToUndefined, z.string().regex(/^\d+$/).optional()),
|
||||
NOTARY_REGISTRY_ADDRESS: z.preprocess(
|
||||
emptyToUndefined,
|
||||
z.string().regex(/^0x[0-9a-fA-F]{40}$/).optional(),
|
||||
),
|
||||
ORCHESTRATOR_PRIVATE_KEY: z.preprocess(
|
||||
emptyToUndefined,
|
||||
z.string().regex(/^0x[0-9a-fA-F]{64}$/).optional(),
|
||||
),
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -31,7 +46,7 @@ export const env = envSchema.parse({
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
PORT: process.env.PORT || "8080",
|
||||
DATABASE_URL: process.env.DATABASE_URL,
|
||||
API_KEYS: process.env.API_KEYS,
|
||||
API_KEYS: process.env.API_KEYS || process.env.ORCHESTRATOR_API_KEYS,
|
||||
REDIS_URL: process.env.REDIS_URL,
|
||||
LOG_LEVEL: process.env.LOG_LEVEL,
|
||||
ALLOWED_IPS: process.env.ALLOWED_IPS,
|
||||
@@ -56,7 +71,7 @@ export function validateEnv() {
|
||||
NODE_ENV: process.env.NODE_ENV || "development",
|
||||
PORT: process.env.PORT || "8080",
|
||||
DATABASE_URL: process.env.DATABASE_URL,
|
||||
API_KEYS: process.env.API_KEYS,
|
||||
API_KEYS: process.env.API_KEYS || process.env.ORCHESTRATOR_API_KEYS,
|
||||
REDIS_URL: process.env.REDIS_URL,
|
||||
LOG_LEVEL: process.env.LOG_LEVEL || "info",
|
||||
ALLOWED_IPS: process.env.ALLOWED_IPS,
|
||||
@@ -65,6 +80,10 @@ export function validateEnv() {
|
||||
AZURE_KEY_VAULT_URL: process.env.AZURE_KEY_VAULT_URL,
|
||||
AWS_SECRETS_MANAGER_REGION: process.env.AWS_SECRETS_MANAGER_REGION,
|
||||
SENTRY_DSN: process.env.SENTRY_DSN,
|
||||
CHAIN_138_RPC_URL: process.env.CHAIN_138_RPC_URL,
|
||||
CHAIN_138_CHAIN_ID: process.env.CHAIN_138_CHAIN_ID,
|
||||
NOTARY_REGISTRY_ADDRESS: process.env.NOTARY_REGISTRY_ADDRESS,
|
||||
ORCHESTRATOR_PRIVATE_KEY: process.env.ORCHESTRATOR_PRIVATE_KEY,
|
||||
};
|
||||
envSchema.parse(envWithDefaults);
|
||||
console.log("✅ Environment variables validated");
|
||||
@@ -79,4 +98,3 @@ export function validateEnv() {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,16 +70,28 @@ app.get("/health", async (req, res) => {
|
||||
const health = await healthCheck();
|
||||
res.status(health.status === "healthy" ? 200 : 503).json(health);
|
||||
});
|
||||
app.get("/api/health", async (req, res) => {
|
||||
const health = await healthCheck();
|
||||
res.status(health.status === "healthy" ? 200 : 503).json(health);
|
||||
});
|
||||
|
||||
app.get("/ready", async (req, res) => {
|
||||
const ready = await readinessCheck();
|
||||
res.status(ready ? 200 : 503).json({ ready });
|
||||
});
|
||||
app.get("/api/ready", async (req, res) => {
|
||||
const ready = await readinessCheck();
|
||||
res.status(ready ? 200 : 503).json({ ready });
|
||||
});
|
||||
|
||||
app.get("/live", async (req, res) => {
|
||||
const alive = await livenessCheck();
|
||||
res.status(alive ? 200 : 503).json({ alive });
|
||||
});
|
||||
app.get("/api/live", async (req, res) => {
|
||||
const alive = await livenessCheck();
|
||||
res.status(alive ? 200 : 503).json({ alive });
|
||||
});
|
||||
|
||||
// Metrics endpoint
|
||||
app.get("/metrics", async (req, res) => {
|
||||
@@ -87,6 +99,11 @@ app.get("/metrics", async (req, res) => {
|
||||
const metrics = await getMetrics();
|
||||
res.send(metrics);
|
||||
});
|
||||
app.get("/api/metrics", async (req, res) => {
|
||||
res.setHeader("Content-Type", register.contentType);
|
||||
const metrics = await getMetrics();
|
||||
res.send(metrics);
|
||||
});
|
||||
|
||||
// API routes with rate limiting
|
||||
app.use("/api", apiLimiter);
|
||||
@@ -173,4 +190,3 @@ async function start() {
|
||||
}
|
||||
|
||||
start();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user