Skip to content

Check destination before eager loading sub-configs#1912

Open
ThomasSevestre wants to merge 4 commits into
basecamp:mainfrom
ThomasSevestre:fix-destination-check-precedes-subconfig-validation
Open

Check destination before eager loading sub-configs#1912
ThomasSevestre wants to merge 4 commits into
basecamp:mainfrom
ThomasSevestre:fix-destination-check-precedes-subconfig-validation

Conversation

@ThomasSevestre

Copy link
Copy Markdown

Check destination before eager loading sub-configs

Problem

When a project sets require_destination: true and the user runs a command without -d <destination>, Kamal raises a confusing, unrelated error instead of telling the user the destination is missing.

This happens whenever a required sub-config key lives only in the per-destination file. Because Kamal eager-loads and validates every sub-config during Configuration#initialize before checking the destination, the first incomplete sub-config raises and masks the real cause. Depending on your layout the masking error varies (builder arch, servers, registry, …).

Example — misleading config

deploy.yml (base, no builder.arch — it lives in the destination files):

service: app
image: dhh/app
registry:
  server: registry.digitalocean.com
  username: <%= ENV["REGISTRY_USER"] %>
  password: <%= ENV["REGISTRY_PASSWORD"] %>
require_destination: true

deploy.production.yml:

builder:
  arch: amd64
servers:
  - 1.1.1.1

Misleading message — running any command without -d:

$ kamal lock release
  ERROR (Kamal::ConfigurationError): builder: Builder arch not set

The user has no idea this actually means "you forgot -d production".

After this change:

$ kamal lock release
  ERROR (ArgumentError): You must specify a destination

Root cause

In Kamal::Configuration#initialize, the eager-loaded sub-configs (Servers, Registry, Builder, …) validate themselves during construction, and one of them raises before ensure_destination_if_required runs at the end of the method.

ensure_destination_if_required only depends on @destination and raw_config.require_destination, both available right after the top-level validate! — so the guard can safely run much earlier.

Fix

Move ensure_destination_if_required to run immediately after the top-level validate!, before the sub-configs are eager-loaded. The missing-destination error now surfaces first, regardless of which destination-only sub-config happens to be incomplete. The generic top-level validate! stays where it is.

Tests

  • Added a regression test (test/configuration_test.rb): base config missing a destination-only key (builder.arch) + require_destination: true + no destination → raises ArgumentError, "You must specify a destination". Confirmed it fails on main with the old Kamal::ConfigurationError: builder: Builder arch not set and passes with the fix.
  • Full suite green: 855 runs, 3116 assertions, 0 failures, 0 errors, 0 skips.

When require_destination: true and no destination is given, a sub-config
validation error (e.g. "Builder arch not set") could mask the real cause,
because the eager-loaded sub-configs validated themselves before the
destination guard ran.

Move ensure_destination_if_required to run right after the top-level
validate!, so the missing-destination error surfaces first regardless of
which destination-only sub-config happens to be incomplete.
Copilot AI review requested due to automatic review settings July 10, 2026 19:28

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.

Pull request overview

This PR fixes a confusing error path when require_destination: true is set but no destination is provided, by ensuring the missing-destination check runs before eager-loaded sub-configs are constructed/validated.

Changes:

  • Move ensure_destination_if_required to run immediately after top-level config validation in Kamal::Configuration#initialize.
  • Add a regression test ensuring the destination guard raises ArgumentError, "You must specify a destination" before sub-config validation can mask it.

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.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
lib/kamal/configuration.rb Runs the destination-required guard earlier to prevent sub-config validation from masking the real error.
test/configuration_test.rb Adds regression coverage asserting destination validation precedes sub-config validation failures.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/configuration_test.rb
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 10, 2026 19:47

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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread test/configuration_test.rb Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 11, 2026 07:49

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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread test/configuration_test.rb Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 11, 2026 11:39

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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

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.

2 participants