[PR #9] fix: resolve ${VAR} templates against environment variables #9

Open
opened 2026-02-15 18:15:39 -05:00 by yindo · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/openclaw/lobster/pull/9
Author: @JoshuaLelon
Created: 2/8/2026
Status: 🔄 Open

Base: mainHead: feat/env-var-inheritance


📝 Commits (1)

  • 37083f2 fix: resolve ${VAR} templates against environment variables

📊 Changes

3 files changed (+184 additions, -9 deletions)

View changed files

📝 src/workflows/file.ts (+25 -9)
test/fixtures/env-test.lobster (+6 -0)
test/workflow_env.test.ts (+153 -0)

📄 Description

Summary

resolveArgsTemplate() only looked up ${VAR} from workflow args (passed via --args-json), so env: { MY_VAR: "${MY_VAR}" } in workflow YAML produced the literal string "${MY_VAR}" instead of the actual value from process.env. This also affected ${VAR} in command, stdin, and cwd fields.

The fix threads the accumulated environment through resolveTemplate, resolveStdin, and resolveCwd so ${VAR} falls back to the process/workflow environment when not found in args. Args still take precedence over env vars.

Also adds relative cwd resolution — cwd: ./scripts now resolves relative to the workflow file's directory instead of being passed as-is to spawn().

lobster-biscuit

Repro Steps

  1. Create a workflow file with env: { TEST_VAR: "${TEST_VAR}" }
  2. Run TEST_VAR=hello lobster run --file workflow.lobster
  3. The step's process.env.TEST_VAR is the literal "${TEST_VAR}" instead of "hello"

Root Cause

resolveArgsTemplate only checked args (workflow-defined args from --args-json). It had no fallback to the environment, so any ${VAR} not defined in args was returned verbatim.

Behavior Changes

  • ${VAR} in env, command, stdin, and cwd values now resolves from the environment when not found in workflow args
  • Precedence: args > env > literal (unchanged match kept as-is)
  • Relative cwd values (e.g. ./scripts) now resolve relative to the workflow file directory
  • No breaking changes to existing behavior — unresolved ${VAR} still pass through as before

Tests

6 new tests in test/workflow_env.test.ts:

Test Result
env var substitution resolves from process.env
workflow-level env overrides parent env
step-level env overrides workflow-level env
args take precedence over env in template substitution
env vars resolve in command templates
relative cwd resolves from workflow file directory

All 53 tests pass (47 existing + 6 new).

pnpm build && pnpm test — clean.

Manual Testing

$ TEST_VAR=hello node bin/lobster.js run --file test/fixtures/env-test.lobster
["hello"]

Sign-Off

  • Models used: Claude Opus 4.6
  • Submitter effort: planned + reviewed
  • Agent notes: ~25 lines of source changes; all optional env params preserve backward compatibility

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/openclaw/lobster/pull/9 **Author:** [@JoshuaLelon](https://github.com/JoshuaLelon) **Created:** 2/8/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/env-var-inheritance` --- ### 📝 Commits (1) - [`37083f2`](https://github.com/openclaw/lobster/commit/37083f23ba2d77d47d54958779613060f7f04a1c) fix: resolve ${VAR} templates against environment variables ### 📊 Changes **3 files changed** (+184 additions, -9 deletions) <details> <summary>View changed files</summary> 📝 `src/workflows/file.ts` (+25 -9) ➕ `test/fixtures/env-test.lobster` (+6 -0) ➕ `test/workflow_env.test.ts` (+153 -0) </details> ### 📄 Description #### Summary `resolveArgsTemplate()` only looked up `${VAR}` from workflow args (passed via `--args-json`), so `env: { MY_VAR: "${MY_VAR}" }` in workflow YAML produced the literal string `"${MY_VAR}"` instead of the actual value from `process.env`. This also affected `${VAR}` in `command`, `stdin`, and `cwd` fields. The fix threads the accumulated environment through `resolveTemplate`, `resolveStdin`, and `resolveCwd` so `${VAR}` falls back to the process/workflow environment when not found in args. Args still take precedence over env vars. Also adds relative `cwd` resolution — `cwd: ./scripts` now resolves relative to the workflow file's directory instead of being passed as-is to `spawn()`. lobster-biscuit #### Repro Steps 1. Create a workflow file with `env: { TEST_VAR: "${TEST_VAR}" }` 2. Run `TEST_VAR=hello lobster run --file workflow.lobster` 3. The step's `process.env.TEST_VAR` is the literal `"${TEST_VAR}"` instead of `"hello"` #### Root Cause `resolveArgsTemplate` only checked `args` (workflow-defined args from `--args-json`). It had no fallback to the environment, so any `${VAR}` not defined in `args` was returned verbatim. #### Behavior Changes - `${VAR}` in `env`, `command`, `stdin`, and `cwd` values now resolves from the environment when not found in workflow args - Precedence: args > env > literal (unchanged match kept as-is) - Relative `cwd` values (e.g. `./scripts`) now resolve relative to the workflow file directory - No breaking changes to existing behavior — unresolved `${VAR}` still pass through as before #### Tests 6 new tests in `test/workflow_env.test.ts`: | Test | Result | |---|---| | env var substitution resolves from process.env | ✅ | | workflow-level env overrides parent env | ✅ | | step-level env overrides workflow-level env | ✅ | | args take precedence over env in template substitution | ✅ | | env vars resolve in command templates | ✅ | | relative cwd resolves from workflow file directory | ✅ | All 53 tests pass (47 existing + 6 new). `pnpm build && pnpm test` — clean. #### Manual Testing ``` $ TEST_VAR=hello node bin/lobster.js run --file test/fixtures/env-test.lobster ["hello"] ``` **Sign-Off** - Models used: Claude Opus 4.6 - Submitter effort: planned + reviewed - Agent notes: ~25 lines of source changes; all optional `env` params preserve backward compatibility --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
yindo added the pull-request label 2026-02-15 18:15:39 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: openclaw/lobster#9