Skip to content

feat: secret support — hm.secrets["…"], local .env resolution, hm cloud secret CLI#152

Open
markovejnovic wants to merge 7 commits into
mainfrom
cli-41-secrets
Open

feat: secret support — hm.secrets["…"], local .env resolution, hm cloud secret CLI#152
markovejnovic wants to merge 7 commits into
mainfrom
cli-41-secrets

Conversation

@markovejnovic

Copy link
Copy Markdown
Contributor

Implements the CLI/DSL/IR side of GHA-style secrets (CLI-41 / #112).

Secrets are referenced in pipelines via hm.secrets["NAME"] and resolved at run time — never embedded in the IR. The DSLs split each step's env into a literal env map and a secrets map (env-var-name → secret-name) that rides through the v0 IR JSON; the backend (separate simci PR) and local hm run both resolve those references to values, with the backend additionally driving log masking.

What's here (7 commits)

  • IR (hm-pipeline-ir): secrets map on CommandStep (per-step) and Transition (merged node), serde round-tripped, snapshots updated.
  • Python DSL: hm.secrets["NAME"] returns a SecretRef; env values accept refs; lowering splits literals vs refs into env/secrets. Name-validated (^[A-Za-z_][A-Za-z0-9_]*$).
  • TypeScript DSL: secrets["NAME"] (Symbol-branded SecretRef, symbol-access-safe Proxy); same lowering split.
  • hm init templates: commented hm.secrets usage in the Python + TS starters.
  • Local resolution (hm-exec): SecretResolver reads a project .env overlaid by the process env (process wins) and resolves each step's refs into the container env; fails fast with a precise, actionable error when a referenced secret is missing. Tracing span skips the env map so resolved values never reach local logs.
  • hm cloud secret set | list | rm: org-scoped by default, --pipeline <slug> for pipeline scope; value via arg, --from-file, or - (stdin); list shows names only (values are write-only).

Contract

secrets map direction = env-var-name → secret-name, on both step and merged node, mirroring env. Merge semantics: pipeline secrets under per-step secrets (step wins). Matches the Elixir IR + DSL emit byte-for-byte (verified via regenerated e2e fixtures, additive only).

Test plan

  • cargo test (workspace) + cargo clippy --all-targets -- -D warnings
  • harmont-py: ruff check + pytest (new test_secrets.py; e2e fixtures regenerated, additive)
  • harmont-ts: vitest + tsc --noEmit (new secret.test.ts)
  • hm-exec resolver + fail-fast unit tests; hm-plugin-cloud path/value-source unit tests + cmd_cloud_gate
  • hm init template round-trip render tests

Pairs with the simci backend PR (encrypted org/pipeline storage, resolve-at-materialize, REST CRUD, agent log masking, dashboard UI). Ref #112.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant