@kjanat/gha-env-validator

Type-safe GitHub Actions environment variable validation with IntelliSense support using Zod.
Features
- ✅ Type-Safe: Full TypeScript support with inferred types from Zod schemas
- ✅ IntelliSense: Auto-complete for all GitHub Actions environment variables in your IDE
- ✅ Runtime Validation: Catch missing or invalid environment variables early with Zod
- ✅ Pre-built Schemas: All GitHub Actions default variables included out-of-the-box
- ✅ Extensible: Easily add custom environment variables to the default schema
- ✅ Zero-Config: Works immediately with GitHub Actions workflows
- ✅ Bun-Native: Built and tested with Bun for optimal performance
Installation
npm install @kjanat/gha-env-validator zod
Other package managers
bun add @kjanat/gha-env-validator zod
pnpm add @kjanat/gha-env-validator zod
yarn add @kjanat/gha-env-validator zod
Quick Start
Basic Usage (Default GitHub Actions Variables)
import { validateEnv } from "@kjanat/gha-env-validator";
const env = validateEnv();
console.log(env.GITHUB_SHA);
console.log(env.GITHUB_RUN_ID);
console.log(env.GITHUB_REPOSITORY);
console.log(env.RUNNER_OS);
Adding Custom Environment Variables
import {
createEnvSchema,
validateCustomEnv,
z
} from "@kjanat/gha-env-validator";
const schema = createEnvSchema({
API_KEY: z.string().min(1),
API_URL: z.string().url(),
NODE_ENV: z.enum(["development", "production", "test"]),
MAX_RETRIES: z.string().transform(Number),
DRY_RUN: z.string().transform((s) => s === "true")
});
const env = validateCustomEnv(schema);
console.log(env.API_KEY);
console.log(env.GITHUB_SHA);
console.log(env.MAX_RETRIES);
console.log(env.DRY_RUN);
Safe Validation (No Throwing)
import { safeValidateEnv } from "@kjanat/gha-env-validator";
const result = safeValidateEnv();
if (result.success) {
console.log("Valid environment:", result.data.GITHUB_SHA);
} else {
console.error("Validation failed:", result.error.format());
process.exit(1);
}
IntelliSense Support
Simply importing the package augments process.env with types:
import "@kjanat/gha-env-validator";
const sha = process.env.GITHUB_SHA;
const runId = process.env.GITHUB_RUN_ID;
const os = process.env.RUNNER_OS;
GitHub Context & Events
Access github context properties and typed event payloads:
import {
getEventPayload,
getGitHubToken,
getPullRequestEvent,
getPushEvent,
getReleaseEvent,
getRepositoryUrl,
isEventType,
isPushEvent
} from "@kjanat/gha-env-validator";
if (isPushEvent()) {
const event = getPushEvent();
console.log(event.commits.length);
console.log(event.head_commit?.message);
}
const token = getGitHubToken();
const response = await fetch(api, {
headers: { Authorization: `Bearer ${token}` }
});
const url = getRepositoryUrl();
Context Utilities
Convenient helpers for accessing GitHub Actions context:
import {
getActor,
getCommitSha,
getCurrentBranch,
getRepoInfo,
getRunnerInfo,
isPullRequest,
isTag
} from "@kjanat/gha-env-validator";
const branch = getCurrentBranch();
const repo = getRepoInfo();
const sha = getCommitSha("short");
if (isPullRequest()) {
const pr = getPullRequestInfo();
}
const runner = getRunnerInfo();
const actor = getActor();
Action Input Validation
Type-safe input validation for GitHub Actions:
import {
getBooleanInput,
getInput,
validateInputs,
z
} from "@kjanat/gha-env-validator";
const token = getInput("github-token", { required: true });
const dryRun = getBooleanInput("dry-run");
const inputs = validateInputs({
version: z.string().regex(/^\d+\.\d+\.\d+$/),
environment: z.enum(["dev", "staging", "prod"]),
"dry-run": z.boolean().default(false),
targets: z.array(z.string()).default([])
});
Workflow Command Helpers
Type-safe utilities for GitHub Actions workflow commands:
Setting Environment Variables
import { setEnvVar, setMultilineEnvVar } from "@kjanat/gha-env-validator";
setEnvVar("NODE_ENV", "production");
setMultilineEnvVar("API_RESPONSE", JSON.stringify(data, null, 2));
Setting Step Outputs
import { setOutput, setOutputs } from "@kjanat/gha-env-validator";
setOutput("version", "1.2.3");
setOutputs({
version: "1.2.3",
commit_sha: "abc123",
build_time: new Date().toISOString()
});
Job Summaries
import {
addJobSummary,
addSummary,
addSummaryTable
} from "@kjanat/gha-env-validator";
addJobSummary("## Build Results\n\n✅ All tests passed!");
addSummary("Deployment", "🚀 Deployed to production");
addSummaryTable(
["Metric", "Value"],
[
["Tests", "42 passed"],
["Coverage", "95%"]
]
);
Log Annotations
import { debug, error, notice, warning } from "@kjanat/gha-env-validator";
debug("Processing item 5 of 10");
notice("Deployment successful");
warning("Deprecated API usage", { file: "app.ts", line: 42 });
error("Build failed", { file: "main.ts", line: 10, title: "Type Error" });
Log Organization
import { endGroup, group, startGroup } from "@kjanat/gha-env-validator";
await group("Install Dependencies", async () => {
console.log("Installing...");
await installPackages();
});
startGroup("Build Process");
console.log("Building...");
endGroup();
Utilities
import {
addPath,
isGitHubActions,
maskValue,
setFailed
} from "@kjanat/gha-env-validator";
maskValue(apiKey);
addPath("/usr/local/custom-tools");
if (isGitHubActions()) {
setEnvVar("CI", "true");
}
if (buildFailed) {
setFailed("Build encountered errors");
}
GitHub Actions Workflow Example
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- name: Install dependencies
run: bun install
- name: Run validation script
env:
API_KEY: ${{ secrets.API_KEY }}
NODE_ENV: production
run: bun run validate-env.ts
validate-env.ts:
import {
createEnvSchema,
validateCustomEnv,
z
} from "@kjanat/gha-env-validator";
const schema = createEnvSchema({
API_KEY: z.string().min(1),
NODE_ENV: z.enum(["development", "production", "test"])
});
try {
const env = validateCustomEnv(schema);
console.log("✅ Environment validation passed!");
console.log("Running on:", env.RUNNER_OS);
console.log("Repository:", env.GITHUB_REPOSITORY);
console.log("Commit SHA:", env.GITHUB_SHA);
} catch (error) {
console.error("❌ Environment validation failed:", error);
process.exit(1);
}
API Reference
validateEnv(options?)
Validates environment variables against the default GitHub Actions schema.
Parameters:
options.env - Custom environment object (defaults to process.env)
options.strict - Strip unknown variables (defaults to false)
Returns: Validated GitHubActionsEnv object
Throws: ZodError if validation fails
validateCustomEnv(schema, options?)
Validates environment variables against a custom schema.
Parameters:
schema - Zod schema to validate against
options.env - Custom environment object (defaults to process.env)
options.strict - Strip unknown variables (defaults to false)
Returns: Validated environment object inferred from schema
Throws: ZodError if validation fails
safeValidateEnv(options?)
Safely validates environment variables, returning a result object instead of throwing.
Parameters:
options.env - Custom environment object (defaults to process.env)
options.strict - Strip unknown variables (defaults to false)
Returns: SafeParseReturnType<unknown, GitHubActionsEnv>
safeValidateCustomEnv(schema, options?)
Safely validates environment variables against a custom schema.
Parameters:
schema - Zod schema to validate against
options.env - Custom environment object (defaults to process.env)
options.strict - Strip unknown variables (defaults to false)
Returns: SafeParseReturnType<unknown, T> where T is inferred from schema
createEnvSchema(customSchema)
Creates a combined schema with GitHub Actions defaults + custom variables.
Parameters:
customSchema - Object defining custom environment variables with Zod validators
Returns: Extended Zod schema
createCustomEnvSchema(customSchema)
Creates a schema with ONLY custom variables (no GitHub Actions defaults).
Parameters:
customSchema - Object defining environment variables with Zod validators
Returns: Zod schema
githubActionsSchema
Pre-built Zod schema for all GitHub Actions default environment variables.
Type: GitHubActionsEnv
TypeScript type representing all GitHub Actions default environment variables with proper types (string, number, boolean, enums).
Included GitHub Actions Variables
All GitHub Actions default environment variables are included with rich metadata:
CI, GITHUB_ACTIONS (boolean)
GITHUB_ACTOR, GITHUB_REPOSITORY, GITHUB_SHA, etc. (string)
GITHUB_RUN_ID, GITHUB_RUN_NUMBER, etc. (number)
RUNNER_OS (enum: "Linux" | "Windows" | "macOS")
RUNNER_ARCH (enum: "X86" | "X64" | "ARM" | "ARM64")
- And many more...
See GitHub Actions documentation for complete list.
Metadata Support (Zod v4)
Each environment variable includes rich metadata using Zod v4's .meta() API:
import { githubActionsSchema } from "@kjanat/gha-env-validator";
const shaField = githubActionsSchema.shape.GITHUB_SHA;
Categories:
environment: CI flags
action: Action context
actor: User/app information
api: GitHub API endpoints
git: Git refs and branches
paths: File system paths
event: Trigger events
job: Job information
repository: Repository details
workflow: Workflow execution
runner: Runner environment
Metadata Use Cases
The rich metadata enables powerful tooling and automation:
1. Auto-Generated Documentation
for (const [name, schema] of Object.entries(githubActionsSchema.shape)) {
const meta = schema._zod.meta;
console.log(`### ${name}`);
console.log(`**${meta.title}** - ${meta.description}`);
console.log(`Example: \`${meta.example}\``);
}
2. Form/UI Builders
const fields = Object.entries(deploymentSchema.shape).map(([name, schema]) => {
const meta = schema._zod.meta;
return {
name,
label: meta.title,
description: meta.description,
placeholder: meta.example,
type: meta.category === "secrets" ? "password" : "text"
};
});
3. CLI Tools & Helpers
function searchVars(keyword: string) {
return Object.entries(schema.shape)
.filter(([_, s]) => s._zod.meta.description.includes(keyword))
.map(([name, s]) => ({ name, ...s._zod.meta }));
}
4. Enhanced Error Messages
if (!result.success) {
for (const issue of result.error.issues) {
const fieldMeta = schema.shape[issue.path[0]]._zod.meta;
console.error(`${fieldMeta.title}: ${issue.message}`);
console.error(`Expected: ${fieldMeta.example}`);
}
}
5. Schema Exports
const jsonSchema = {
properties: Object
.fromEntries(Object.entries(schema.shape).map(([name, s]) => [
name,
{
type: "string",
title: s._zod.meta.title,
description: s._zod.meta.description,
examples: [s._zod.meta.example]
}
]))
};
See examples/ directory for complete implementations:
metadata-documentation-generator.ts - Auto-generate markdown docs
metadata-form-builder.ts - Build configuration UIs
metadata-cli-helper.ts - Interactive CLI tools
metadata-validation-reporter.ts - Rich error messages
metadata-schema-explorer.ts - Schema introspection
Development
bun install
bun test
bun run typecheck
bun run lint
bun run format
bun run build
Build System
This package uses tsdown for building:
- Dual format: Ships both ESM (
.mjs) and CJS (.cjs) outputs
- Type declarations: Separate
.d.mts and .d.cts for module systems
- Node 18+: Target platform with tree-shaking enabled
- Clean builds: Automatic cleanup before each build
Code Quality
- Biome: Fast linting and formatting
- Dprint: Markdown and JSON formatting
- Lefthook: Pre-commit hooks for automated quality checks
- 100% test coverage: All modules fully tested
License
MIT