🤖 This issue has been generated by Claude Code.
Summary
When an engine.env value in workflow frontmatter is a non-string YAML scalar (a number or a boolean), gh aw compile silently drops it from the generated *.lock.yml. No warning, no error — the variable simply never appears in the Execute ... CLI step's env: block. Only string-typed values survive.
This is surprising because GitHub Actions workflow syntax does allow numbers and booleans as env values (it coerces them to strings at runtime), so the input looks perfectly valid to the author.
Version: v0.79.1.
Reproduction
Minimal workflow:
---
engine:
id: claude
env:
# string values — kept
OTEL_TRACES_EXPORTER: console,otlp
# numeric values — silently dropped
CLAUDE_CODE_ENABLE_TELEMETRY: 1
OTEL_TRACES_EXPORT_INTERVAL: 1000
OTEL_LOG_USER_PROMPTS: 1
# boolean values — also dropped
SOME_FLAG: true
---
# Test
hello
Run gh aw compile and inspect the env: of the Execute ... step in the generated *.lock.yml.
Expected
All five variables present (numbers/booleans rendered as strings), matching how GitHub Actions itself treats them.
Actual
Only OTEL_TRACES_EXPORTER is emitted. CLAUDE_CODE_ENABLE_TELEMETRY, OTEL_TRACES_EXPORT_INTERVAL, OTEL_LOG_USER_PROMPTS, and SOME_FLAG are gone — with no diagnostic output.
Quoting the values (CLAUDE_CODE_ENABLE_TELEMETRY: "1", SOME_FLAG: "true") makes them reappear, which is the only hint that anything was wrong.
Root cause
pkg/workflow/engine.go, in ExtractEngineConfig (the env extraction block, ~lines 375–385 in v0.79.1):
// Extract optional 'env' field (object/map of strings)
if env, hasEnv := engineObj["env"]; hasEnv {
if envMap, ok := env.(map[string]any); ok {
config.Env = make(map[string]string)
for key, value := range envMap {
if valueStr, ok := value.(string); ok { // non-string → skipped, silently
config.Env[key] = valueStr
}
}
}
}
The value.(string) type assertion fails for YAML-parsed integers (int/float64) and booleans (bool), and the else branch does nothing — so those entries are discarded with no record that they existed.
Why the input is valid
The official GitHub Actions workflow JSON schema (SchemaStore github-workflow.json, used by GitHub's own validation) defines env values as:
"additionalProperties": { "oneOf": [ {"type": "string"}, {"type": "number"}, {"type": "boolean"} ] }
So FOO: 1 and FOO: true are legal workflow input; GitHub coerces them to "1" / "true". gh-aw rejecting them — and doing so silently — is the mismatch.
Request
Either of the following would resolve the trap; the first is preferable:
- Support non-string scalars — coerce numbers and booleans to their string form during extraction (e.g.
fmt.Sprintf("%v", value) for string/int/int64/float64/bool), matching GitHub Actions semantics.
- Fail at compile time — if non-string coercion isn't desired, emit a clear compile error (or at minimum a warning) naming the offending key, instead of silently dropping it.
The current silent-drop behavior is the worst of both: valid-looking input produces a compiled workflow that's missing configuration, with nothing pointing at the cause.
Happy to send a PR for option 1 if that's the preferred direction.
🤖 This issue has been generated by Claude Code.
Summary
When an
engine.envvalue in workflow frontmatter is a non-string YAML scalar (a number or a boolean),gh aw compilesilently drops it from the generated*.lock.yml. No warning, no error — the variable simply never appears in theExecute ... CLIstep'senv:block. Only string-typed values survive.This is surprising because GitHub Actions workflow syntax does allow numbers and booleans as
envvalues (it coerces them to strings at runtime), so the input looks perfectly valid to the author.Version:
v0.79.1.Reproduction
Minimal workflow:
Run
gh aw compileand inspect theenv:of theExecute ...step in the generated*.lock.yml.Expected
All five variables present (numbers/booleans rendered as strings), matching how GitHub Actions itself treats them.
Actual
Only
OTEL_TRACES_EXPORTERis emitted.CLAUDE_CODE_ENABLE_TELEMETRY,OTEL_TRACES_EXPORT_INTERVAL,OTEL_LOG_USER_PROMPTS, andSOME_FLAGare gone — with no diagnostic output.Quoting the values (
CLAUDE_CODE_ENABLE_TELEMETRY: "1",SOME_FLAG: "true") makes them reappear, which is the only hint that anything was wrong.Root cause
pkg/workflow/engine.go, inExtractEngineConfig(theenvextraction block, ~lines 375–385 in v0.79.1):The
value.(string)type assertion fails for YAML-parsed integers (int/float64) and booleans (bool), and theelsebranch does nothing — so those entries are discarded with no record that they existed.Why the input is valid
The official GitHub Actions workflow JSON schema (SchemaStore
github-workflow.json, used by GitHub's own validation) definesenvvalues as:So
FOO: 1andFOO: trueare legal workflow input; GitHub coerces them to"1"/"true". gh-aw rejecting them — and doing so silently — is the mismatch.Request
Either of the following would resolve the trap; the first is preferable:
fmt.Sprintf("%v", value)forstring/int/int64/float64/bool), matching GitHub Actions semantics.The current silent-drop behavior is the worst of both: valid-looking input produces a compiled workflow that's missing configuration, with nothing pointing at the cause.
Happy to send a PR for option 1 if that's the preferred direction.