Pulse: expand ${VAR} across all PULSE.toml string values, not just job.command#1544
Open
m8ryx wants to merge 1 commit into
Open
Pulse: expand ${VAR} across all PULSE.toml string values, not just job.command#1544m8ryx wants to merge 1 commit into
m8ryx wants to merge 1 commit into
Conversation
…b.command
resolveEnvVars() existed but was applied to exactly one field — a job's
`command`. Every other ${VAR} in the config was a dead literal, producing two
silent failures:
- `[notifications.discord] webhook = "${DISCORD_WEBHOOK}"` ships upstream and
nothing ever expanded it.
- Any module reading a secret off the config would hand the literal string
"${TOKEN}" to a remote API and fail auth with no local error.
Add parseConfigToml(), which parses a Pulse TOML document and recursively
expands env vars in every string value. Both readers of PULSE.toml — the job
loader in lib.ts and loadPulseConfig() in pulse.ts — now go through it, making
expansion a property of the config layer rather than of one consumer.
Substitution semantics are unchanged from the original single-field behaviour:
both $VAR and ${VAR} are recognised, and an undefined variable resolves to the
empty string. Because the regex only matches `$` followed by an uppercase
identifier, plain literal values are returned byte-identical, so existing
installs are unaffected by the upgrade.
Covered by lib.test.ts (added here): nested-section expansion, the
[notifications.discord] webhook stub, literal pass-through, non-string scalars,
job.command still expanding, undefined-var semantics, and keys never being
rewritten.
$ cd LIFEOS/PULSE && bun install && bun test lib.test.ts
7 pass, 0 fail, 10 expect() calls
Note: this is the repo's first tracked test file — there is no existing test
convention or runner config, so it is colocated and run directly with
`bun test`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PULSE.tomldeclares environment references in three places —${NTFY_TOPIC},${DISCORD_WEBHOOK},${TWILIO_TO_NUMBER}— butresolveEnvVars()is only applied to a job'scommand, so none of them are expanded. Consumers currently work around this by readingprocess.envdirectly indispatchSingle(), so nothing is broken at runtime today; the config simply doesn't behave the way it reads.Any module that trusts the config instead receives the literal string
"${VAR}". For a credential that means an authentication failure with no local error.This moves expansion into the config layer via a new
parseConfigToml(), so both readers ofPULSE.toml— the job loader inlib.tsandloadPulseConfig()inpulse.ts— go through it, and the declared convention becomes real.Substitution semantics are deliberately unchanged from the existing single-field behaviour: both
$VARand${VAR}are recognised, and an undefined variable resolves to the empty string. The pattern only matches$followed by an uppercase identifier, so a plain literal value (a hostname, a cron expression, a prose prompt) is returned byte-identical and existing installs are unaffected.Includes tests covering nested-section expansion, literal pass-through, non-string scalars,
job.commandstill expanding, undefined-variable semantics, and keys never being rewritten.Note this is the repo's first tracked test file — there's no existing test convention or runner config, so it's colocated and run with
bun test. Happy to move it if you'd prefer a different location or setup.