Deploy checks run through provider adapters.
They catch env drift before a deploy starts and push schema-declared variables without shell quoting.
V1 targets:
- Vercel
- Railway
import { listDeployEnvVars } from "@howells/envy";
import { vercel } from "@howells/envy/adapters/vercel";
const keys = listDeployEnvVars(envSchema, {
environment: "production",
}).map((entry) => entry.key);
const result = await vercel({ project: "web" }).check({
environment: "production",
keys,
});Checks verify presence of deploy-relevant variables:
- include
server - include
public - include
optionalonly when explicitly marked deploy-required - exclude
systemby default
Provider APIs may not expose secret values. Presence checks still work. Value validation runs only when the provider returns readable values.
Example report:
Vercel production
✓ DATABASE_URL present
✓ OPENAI_API_KEY present
✕ NEXT_PUBLIC_APP_URL missing
- DATABASE_URL value is not readable, schema format not validated
- OPENAI_API_KEY value is not readable, schema format not validatedimport { loadDotenv } from "@howells/envy/dotenv";
import { railway } from "@howells/envy/adapters/railway";
const values: Record<string, string | undefined> = {};
loadDotenv([".env.production"], { processEnv: values });
await railway({
environmentId: "env_id",
projectId: "project_id",
serviceId: "service_id",
}).push({
dryRun: true,
values: Object.fromEntries(
Object.entries(values).filter((entry): entry is [string, string] =>
typeof entry[1] === "string"
),
),
});Pushes:
- parse
.envwith a real parser - use provider APIs directly
- push schema-declared keys only
- fail on undeclared keys by default
- exclude
systemkeys by default - push optional keys only when present
- never print secret values
- skip existing remote vars unless
--overwrite - refuse deletes in v1
Secrets are easy to corrupt with shell commands:
echo "$SECRET" | vercel env add SECRET productionThat can add trailing newlines or mishandle multiline values. Envy sends parsed values through provider APIs.
envy check local --from .env.productionBy default this validates the file alone and fails if:
- a required deploy key is missing
- a key is undeclared
- a readable value fails its Zod schema
Merging with the current process environment is explicit:
envy check local --from .env.production --with-process-envIn merged mode, process.env wins over file values.