Make Secrets#key? existence-based so empty values count as present by Harsh23Kashyap · Pull Request #1972 · basecamp/kamal · GitHub
Skip to content

Make Secrets#key? existence-based so empty values count as present - #1972

Open
Harsh23Kashyap wants to merge 1 commit into
basecamp:mainfrom
Harsh23Kashyap:fix-secrets-key-empty-value
Open

Harsh23Kashyap wants to merge 1 commit into
basecamp:mainfrom
Harsh23Kashyap:fix-secrets-key-empty-value

Conversation

@Harsh23Kashyap

Copy link
Copy Markdown

Problem

Kamal::Secrets#key? fetches the value and calls .present? on it, so a secret that is set but empty (EMPTY= in .kamal/secrets) reports as missing, while Secrets#[] happily returns its empty string. The two methods disagree about the same key.

One place this bites is Kamal::Configuration::Ssh, which checks secrets.key?("KAMAL_SSH_PRIVATE_KEY")-style lookups via the key_data secret: with an intentionally empty value it falls back to treating the secret name as an inline key (plus a deprecation warning), instead of seeing the key as set.

Fixes #1966.

Fix

Fetch the key and translate only KeyError into false, matching Hash semantics: a key that exists counts as present even when its value is empty. #[] keeps raising for genuinely missing keys and still returns empty strings, so legitimately empty values keep working.

Verification

Repro with a .kamal/secrets file containing EMPTY=:

Before:

key?("EMPTY") => false
secrets["EMPTY"] => ""
key?("SET") => true
key?("MISSING") => false

After:

key?("EMPTY") => true
secrets["EMPTY"] => ""
key?("SET") => true
key?("MISSING") => false

Added a regression test covering the empty-value case. bin/test test/secrets_test.rb passes: 15 runs, 29 assertions, 0 failures (ran twice). The full bin/test run shows the same 4 failures and 23 errors before and after this change; they are pre-existing on unmodified main in my environment (docker-dependent CLI tests) and are untouched by this patch.

Secrets#key? used .present? on the fetched value, so a secret that is
set but empty (EMPTY=) reported as missing while Secrets#[] returns
its empty string. That made the two methods disagree, and broke the
ssh key_data check in Kamal::Configuration::Ssh, which falls back to
treating the secret name as an inline key when key? is false.

Fetch the key and only translate KeyError into false, matching Hash
semantics: a key that exists counts as present even when its value
is empty.

Fixes basecamp#1966
Copilot AI balanced review requested due to automatic review settings October 18, 2026 13:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approved

The focused change preserves missing-key handling and includes regression coverage, with no unresolved findings.

No open issues 🎉

What changed in this PR

Fixes #1966 by making Kamal::Secrets#key? check existence rather than value presence, consistent with Secrets#[].

Changes:

  • Counts empty secrets as present while preserving missing-key behavior.
  • Adds regression coverage for empty-value lookups.

[!TIP]
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

File Description
test/​secrets_test.rb Verifies empty secrets exist and return an empty string.
lib/​kamal/​secrets.rb Returns true after a successful fetch, regardless of value.

Review effort: Balanced

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.

Secrets#key? treats an empty value as missing, Secrets#[] returns it

2 participants