Skip to Content
SDK (Deep Dive)Environment & Secrets

Environment & Secrets

The ctx.vars and ctx.secrets objects provide access to environment variables and secure secrets during test execution.

Purpose

To separate configuration (URLs, regions, flags) from sensitive credentials (API keys, OAuth tokens) and provide a type-safe, strict way to access them.

Design Rationale

  • Strict by Default: Both objects provide a require() method. Missing configuration is the #1 cause of confusing test failures. require() guarantees that if a necessary variable is missing or invalid, the test fails immediately with a clear error message, rather than failing 30 lines later with a cryptic “Cannot read property of undefined”.
  • Separation of Secrets: Secrets are handled via a separate ctx.secrets object. This distinct boundary ensures that the runner knows exactly which values are sensitive. The runner automatically redacts these values from logs, traces, and assertions before they are stored or displayed in the Glubean dashboard.

Scenarios

Required vs. Optional Configuration

When your test cannot proceed without a specific environment variable, use require(). When you have a sensible fallback, use get().

export const healthCheck = test("health", async (ctx) => { // Fails immediately if BASE_URL is not set in the environment const baseUrl = ctx.vars.require("BASE_URL"); // Falls back to "us-east-1" if REGION is not set const region = ctx.vars.get("REGION") ?? "us-east-1"; });

Accessing Secrets

Secrets should always be accessed via ctx.secrets. Never place API keys in ctx.vars.

export const testAuth = test("auth", async (ctx) => { // Fails immediately if API_KEY is missing const apiKey = ctx.secrets.require("API_KEY"); const res = await ctx.http.get("...", { headers: { Authorization: `Bearer ${apiKey}` } }); });

Validation Functions

You can pass a validator function to require() to ensure the variable or secret is not just present, but structurally valid. This prevents sending malformed requests to your API.

export const validateConfig = test("validate", async (ctx) => { // Validates that the port is a number const port = ctx.vars.require("PORT", (v) => !isNaN(Number(v))); // Validates that a JWT token has exactly 3 parts const jwt = ctx.secrets.require("JWT_TOKEN", (v) => { const parts = v.split("."); if (parts.length !== 3) { return "must be a valid JWT containing 3 parts separated by dots"; } return true; }); });
Last updated on