···11+defmodule Sower.Repo.Migrations.AddLogAndResultToSeedDeployment do
22+ use Ecto.Migration
33+44+ def change do
55+ alter table(:seed_deployment) do
66+ add :log, :text
77+ add :result, :string
88+ end
99+ end
1010+end
-107
apps/sower/test/sower/storage_test.exs
···11-defmodule Sower.StorageTest do
22- use Sower.DataCase
33-44- alias Sower.Storage
55- alias SowerClient.Storage.DeploymentLogUploadRequest
66- alias SowerClient.Storage.PresignedUploadReply
77-88- import Sower.AccountsFixtures
99- import Sower.OrchestrationFixtures
1010- import Sower.SeedFixtures
1111-1212- setup do
1313- org = organization_fixture()
1414- Sower.Repo.put_org_id(org.org_id)
1515-1616- %{organization: org}
1717- end
1818-1919- describe "presign_deployment_log_upload/2" do
2020- setup %{organization: org} do
2121- agent = agent_fixture(%{org_id: org.org_id})
2222- other_agent = agent_fixture(%{org_id: org.org_id, name: "other agent"})
2323-2424- seed = seed_fixture(%{org_id: org.org_id})
2525-2626- deployment =
2727- deployment_fixture(%{
2828- org_id: org.org_id,
2929- agent_id: agent.id,
3030- seeds: [seed],
3131- subscriptions: []
3232- })
3333-3434- deployment = Sower.Repo.preload(deployment, :seeds)
3535-3636- %{agent: agent, other_agent: other_agent, deployment: deployment, seed: seed}
3737- end
3838-3939- test "returns presigned upload URL for valid request", %{
4040- agent: agent,
4141- deployment: deployment,
4242- seed: seed
4343- } do
4444- request = %DeploymentLogUploadRequest{
4545- deployment_sid: deployment.sid,
4646- seed_sid: seed.sid,
4747- checksum_sha256: nil
4848- }
4949-5050- # Mock the presign_upload function to avoid S3 dependency
5151- mock_presign = fn path, _opts ->
5252- {:ok, "https://mock-s3.example.com/#{path}?signed=true"}
5353- end
5454-5555- assert {:ok, %PresignedUploadReply{} = reply} =
5656- Storage.presign_deployment_log_upload(agent, request, mock_presign)
5757-5858- assert reply.url ==
5959- "https://mock-s3.example.com/logs/deployments/#{deployment.sid}/seeds/#{seed.sid}.log?signed=true"
6060-6161- assert reply.method == "PUT"
6262- assert reply.headers == %{}
6363- end
6464-6565- test "returns error for non-existent deployment", %{agent: agent} do
6666- request = %DeploymentLogUploadRequest{
6767- deployment_sid: "nonexistent_deploy",
6868- seed_sid: "some_seed",
6969- checksum_sha256: nil
7070- }
7171-7272- assert {:error, :unauthorized} =
7373- Storage.presign_deployment_log_upload(agent, request)
7474- end
7575-7676- test "returns unauthorized error for deployment owned by different agent", %{
7777- other_agent: other_agent,
7878- deployment: deployment,
7979- seed: seed
8080- } do
8181- request = %DeploymentLogUploadRequest{
8282- deployment_sid: deployment.sid,
8383- seed_sid: seed.sid,
8484- checksum_sha256: nil
8585- }
8686-8787- assert {:error, :unauthorized} =
8888- Storage.presign_deployment_log_upload(other_agent, request)
8989- end
9090-9191- test "returns error when seed is not associated with deployment", %{
9292- agent: agent,
9393- deployment: deployment
9494- } do
9595- other_seed = seed_fixture(%{org_id: agent.org_id, name: "other_seed"})
9696-9797- request = %DeploymentLogUploadRequest{
9898- deployment_sid: deployment.sid,
9999- seed_sid: other_seed.sid,
100100- checksum_sha256: nil
101101- }
102102-103103- assert {:error, :seed_not_in_deployment} =
104104- Storage.presign_deployment_log_upload(agent, request)
105105- end
106106- end
107107-end