Deployment and lifecycle management for Nix
0
fork

Configure Feed

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

test: add seed deployment handle_in tests (seed_status, seed_result)

Test deployment:seed_status updating seed deployment state,
deployment:seed_result recording results (with and without result
field for log-only updates), and error cases for unknown deployments
and seeds not in the deployment.

SOW-73

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

+160
+160
apps/sower/test/sower_web/channels/garden_channel_handle_in_test.exs
··· 194 194 assert_reply ref, :error, :deployment_not_found 195 195 end 196 196 end 197 + 198 + describe "deployment:seed_status" do 199 + test "updates seed deployment state" do 200 + %{socket: socket, garden: garden} = connect_and_join_garden() 201 + 202 + seed = seed_fixture(%{name: "seed-status-seed", seed_type: "nixos"}) 203 + 204 + subscription = 205 + subscription_fixture(%{ 206 + garden_id: garden.id, 207 + seed_name: seed.name, 208 + seed_type: seed.seed_type 209 + }) 210 + 211 + deployment = 212 + deployment_fixture(%{ 213 + garden_id: garden.id, 214 + seeds: [seed], 215 + subscriptions: [subscription] 216 + }) 217 + 218 + ref = 219 + push(socket, "deployment:seed_status", %{ 220 + "deployment_sid" => deployment.sid, 221 + "seed_sid" => seed.sid, 222 + "status" => "downloading" 223 + }) 224 + 225 + assert_reply ref, :ok, %{} 226 + end 227 + 228 + test "returns error for unknown deployment" do 229 + %{socket: socket} = connect_and_join_garden() 230 + 231 + ref = 232 + push(socket, "deployment:seed_status", %{ 233 + "deployment_sid" => "nonexistent_sid", 234 + "seed_sid" => "nonexistent_seed", 235 + "status" => "downloading" 236 + }) 237 + 238 + assert_reply ref, :error, :deployment_not_found 239 + end 240 + 241 + test "returns error for seed not in deployment" do 242 + %{socket: socket, garden: garden} = connect_and_join_garden() 243 + 244 + seed = seed_fixture(%{name: "seed-status-miss", seed_type: "nixos"}) 245 + other_seed = seed_fixture(%{name: "seed-status-other", seed_type: "nixos"}) 246 + 247 + subscription = 248 + subscription_fixture(%{ 249 + garden_id: garden.id, 250 + seed_name: seed.name, 251 + seed_type: seed.seed_type 252 + }) 253 + 254 + deployment = 255 + deployment_fixture(%{ 256 + garden_id: garden.id, 257 + seeds: [seed], 258 + subscriptions: [subscription] 259 + }) 260 + 261 + ref = 262 + push(socket, "deployment:seed_status", %{ 263 + "deployment_sid" => deployment.sid, 264 + "seed_sid" => other_seed.sid, 265 + "status" => "downloading" 266 + }) 267 + 268 + assert_reply ref, :error, :seed_not_in_deployment 269 + end 270 + end 271 + 272 + describe "deployment:seed_result" do 273 + test "records seed deployment result and updates DB" do 274 + %{socket: socket, garden: garden} = connect_and_join_garden() 275 + 276 + seed = seed_fixture(%{name: "seed-result-seed", seed_type: "nixos"}) 277 + 278 + subscription = 279 + subscription_fixture(%{ 280 + garden_id: garden.id, 281 + seed_name: seed.name, 282 + seed_type: seed.seed_type 283 + }) 284 + 285 + deployment = 286 + deployment_fixture(%{ 287 + garden_id: garden.id, 288 + seeds: [seed], 289 + subscriptions: [subscription] 290 + }) 291 + 292 + ref = 293 + push(socket, "deployment:seed_result", %{ 294 + "deployment_sid" => deployment.sid, 295 + "seed_sid" => seed.sid, 296 + "result" => "success", 297 + "log" => "deployment completed successfully" 298 + }) 299 + 300 + assert_reply ref, :ok, %{} 301 + 302 + [seed_deployment] = 303 + Sower.Repo.preload(deployment, :seed_deployments, force: true).seed_deployments 304 + 305 + assert seed_deployment.result == :success 306 + assert seed_deployment.log == "deployment completed successfully" 307 + end 308 + 309 + test "appends log without setting result (log-only update)" do 310 + %{socket: socket, garden: garden} = connect_and_join_garden() 311 + 312 + seed = seed_fixture(%{name: "seed-result-logonly", seed_type: "nixos"}) 313 + 314 + subscription = 315 + subscription_fixture(%{ 316 + garden_id: garden.id, 317 + seed_name: seed.name, 318 + seed_type: seed.seed_type 319 + }) 320 + 321 + deployment = 322 + deployment_fixture(%{ 323 + garden_id: garden.id, 324 + seeds: [seed], 325 + subscriptions: [subscription] 326 + }) 327 + 328 + ref = 329 + push(socket, "deployment:seed_result", %{ 330 + "deployment_sid" => deployment.sid, 331 + "seed_sid" => seed.sid, 332 + "log" => "partial output" 333 + }) 334 + 335 + assert_reply ref, :ok, %{} 336 + 337 + [seed_deployment] = 338 + Sower.Repo.preload(deployment, :seed_deployments, force: true).seed_deployments 339 + 340 + assert seed_deployment.result == nil 341 + assert seed_deployment.log == "partial output" 342 + end 343 + 344 + test "returns error for unknown deployment" do 345 + %{socket: socket} = connect_and_join_garden() 346 + 347 + ref = 348 + push(socket, "deployment:seed_result", %{ 349 + "deployment_sid" => "nonexistent_sid", 350 + "seed_sid" => "nonexistent_seed", 351 + "result" => "success" 352 + }) 353 + 354 + assert_reply ref, :error, :deployment_not_found 355 + end 356 + end 197 357 end