Deployment and lifecycle management for Nix
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cleanup: make subscription name required in client schema

name was added in 0.8.0 as optional; now that all gardens send it,
make it required in SowerClient.Orchestration.Subscription. The
server-side create_subscription retains its seed_name fallback for
web UI and fixture use.

Updates contract baseline and all test fixtures to include name.

sow-122

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+46 -34
+26 -10
apps/garden/test/garden/socket/lifecycle_test.exs
··· 59 59 describe "merge_subscriptions/2" do 60 60 test "merges server-assigned sids into config subscriptions" do 61 61 config_subs = [ 62 - Subscription.cast!(%{seed_name: "host", seed_type: "nixos", poll_on_connect: true}), 63 - Subscription.cast!(%{seed_name: "user", seed_type: "home-manager"}) 62 + Subscription.cast!(%{ 63 + name: "host", 64 + seed_name: "host", 65 + seed_type: "nixos", 66 + poll_on_connect: true 67 + }), 68 + Subscription.cast!(%{name: "user", seed_name: "user", seed_type: "home-manager"}) 64 69 ] 65 70 66 71 registered = [ 67 - %{"seed_name" => "host", "seed_type" => "nixos", "sid" => "sub_abc"}, 68 - %{"seed_name" => "user", "seed_type" => "home-manager", "sid" => "sub_def"} 72 + %{"name" => "host", "seed_name" => "host", "seed_type" => "nixos", "sid" => "sub_abc"}, 73 + %{ 74 + "name" => "user", 75 + "seed_name" => "user", 76 + "seed_type" => "home-manager", 77 + "sid" => "sub_def" 78 + } 69 79 ] 70 80 71 81 result = Lifecycle.merge_subscriptions(config_subs, registered) ··· 78 88 79 89 test "drops config subscriptions not registered on server" do 80 90 config_subs = [ 81 - Subscription.cast!(%{seed_name: "host", seed_type: "nixos"}), 82 - Subscription.cast!(%{seed_name: "orphan", seed_type: "nixos"}) 91 + Subscription.cast!(%{name: "host", seed_name: "host", seed_type: "nixos"}), 92 + Subscription.cast!(%{name: "orphan", seed_name: "orphan", seed_type: "nixos"}) 83 93 ] 84 94 85 95 registered = [ 86 - %{"seed_name" => "host", "seed_type" => "nixos", "sid" => "sub_abc"} 96 + %{"name" => "host", "seed_name" => "host", "seed_type" => "nixos", "sid" => "sub_abc"} 87 97 ] 88 98 89 99 result = Lifecycle.merge_subscriptions(config_subs, registered) ··· 94 104 95 105 test "returns empty list for empty registered" do 96 106 config_subs = [ 97 - Subscription.cast!(%{seed_name: "host", seed_type: "nixos"}) 107 + Subscription.cast!(%{name: "host", seed_name: "host", seed_type: "nixos"}) 98 108 ] 99 109 100 110 assert Lifecycle.merge_subscriptions(config_subs, []) == [] ··· 105 115 test "filters to subscriptions with poll_on_connect true" do 106 116 subs = [ 107 117 Subscription.cast!(%{ 118 + name: "host", 108 119 seed_name: "host", 109 120 seed_type: "nixos", 110 121 poll_on_connect: true, 111 122 sid: "sub_1" 112 123 }), 113 - Subscription.cast!(%{seed_name: "user", seed_type: "home-manager", sid: "sub_2"}) 124 + Subscription.cast!(%{ 125 + name: "user", 126 + seed_name: "user", 127 + seed_type: "home-manager", 128 + sid: "sub_2" 129 + }) 114 130 ] 115 131 116 132 result = Lifecycle.poll_on_connect_subscriptions(subs) ··· 121 137 122 138 test "returns empty list when none have poll_on_connect" do 123 139 subs = [ 124 - Subscription.cast!(%{seed_name: "host", seed_type: "nixos", sid: "sub_1"}) 140 + Subscription.cast!(%{name: "host", seed_name: "host", seed_type: "nixos", sid: "sub_1"}) 125 141 ] 126 142 127 143 assert Lifecycle.poll_on_connect_subscriptions(subs) == []
+13 -15
apps/sower/lib/sower/orchestration/subscription.ex
··· 201 201 end 202 202 203 203 def register_subscription(%SowerClient.Orchestration.Subscription{} = sub, garden_id) do 204 - attrs = 205 - %{ 206 - garden_id: garden_id, 207 - seed_name: sub.seed_name, 208 - seed_type: sub.seed_type, 209 - rules: sub.rules, 210 - schedule: sub.schedule, 211 - timezone: sub.timezone, 212 - activation_args: sub.activation_args, 213 - reboot_policy: sub.reboot_policy, 214 - allow_realtime: sub.allow_realtime, 215 - window: sub.window 216 - } 217 - 218 - attrs = if sub.name, do: Map.put(attrs, :name, sub.name), else: attrs 204 + attrs = %{ 205 + garden_id: garden_id, 206 + name: sub.name, 207 + seed_name: sub.seed_name, 208 + seed_type: sub.seed_type, 209 + rules: sub.rules, 210 + schedule: sub.schedule, 211 + timezone: sub.timezone, 212 + activation_args: sub.activation_args, 213 + reboot_policy: sub.reboot_policy, 214 + allow_realtime: sub.allow_realtime, 215 + window: sub.window 216 + } 219 217 220 218 case create_subscription(attrs) do 221 219 {:ok, subscription} ->
+3 -3
apps/sower/test/sower_web/channels/garden_channel_handle_in_test.exs
··· 328 328 ref = 329 329 push(socket, "subscriptions:sync", %{ 330 330 "subscriptions" => [ 331 - %{"seed_name" => "sync-host-1", "seed_type" => "nixos"}, 332 - %{"seed_name" => "sync-host-2", "seed_type" => "nixos"} 331 + %{"name" => "sync-host-1", "seed_name" => "sync-host-1", "seed_type" => "nixos"}, 332 + %{"name" => "sync-host-2", "seed_name" => "sync-host-2", "seed_type" => "nixos"} 333 333 ] 334 334 }) 335 335 ··· 352 352 ref = 353 353 push(socket, "subscriptions:sync", %{ 354 354 "subscriptions" => [ 355 - %{"seed_name" => "to-keep", "seed_type" => "nixos"} 355 + %{"name" => "to-keep", "seed_name" => "to-keep", "seed_type" => "nixos"} 356 356 ] 357 357 }) 358 358
+2 -4
apps/sower_client/lib/sower_client/orchestration/subscription.ex
··· 12 12 readOnly: true, 13 13 nullable: true 14 14 }, 15 - # TODO: make required in 0.9.0 once all gardens send name 16 15 name: %Schema{ 17 16 type: :string, 18 - description: "Human-readable subscription name", 19 - nullable: true 17 + description: "Human-readable subscription name" 20 18 }, 21 19 seed_name: %Schema{ 22 20 type: :string, ··· 72 70 }, 73 71 window: __MODULE__.Window 74 72 }, 75 - required: [:seed_name, :seed_type], 73 + required: [:name, :seed_name, :seed_type], 76 74 example: %{ 77 75 seed_name: "myhost", 78 76 seed_type: "nixos",
+2 -2
config/runtime.exs
··· 19 19 state_directory: 20 20 Path.join(System.tmp_dir!(), "sower_test_#{System.system_time(:millisecond)}"), 21 21 subscriptions: [ 22 - %{seed_name: "test1", seed_type: "nixos"}, 23 - %{seed_name: "test1", seed_type: "home-manager"} 22 + %{name: "test1", seed_name: "test1", seed_type: "nixos"}, 23 + %{name: "test1", seed_name: "test1", seed_type: "home-manager"} 24 24 ] 25 25 }, 26 26 skip_config_file: true,