4.2 KiB · text 5af55d9
defmodule GitGudWeb.ActionsEndpointsTest do
use GitGudWeb.ConnCase, async: false
alias GitGud.Storage
alias GitGud.Workflows.RunnerJwt
alias GitGud.Workflows.WorkflowJob
alias GitGud.Workflows.WorkflowRun
import GitGud.ForgeFixtures
@moduletag :git_required
setup do
if System.find_executable("git") == nil do
{:skip, "git not on PATH"}
else
{_user, repo} = repository_fixture()
run =
%WorkflowRun{repository_id: repo.id}
|> WorkflowRun.create_changeset(%{
number: 1,
workflow_path: ".github/workflows/ci.yml",
trigger: "push",
head_sha: :crypto.strong_rand_bytes(20)
})
|> GitGud.Repo.insert!()
job =
%WorkflowJob{workflow_run_id: run.id}
|> WorkflowJob.create_changeset(%{job_id: "build", definition: %{}})
|> GitGud.Repo.insert!()
token = RunnerJwt.mint(job, run)
# In-memory test storage so we don't need a real Garage instance.
original = Application.get_env(:git_gud, Storage, [])
Application.put_env(:git_gud, Storage, impl: GitGudWeb.ActionsEndpointsTest.MemStorage)
on_exit(fn -> Application.put_env(:git_gud, Storage, original) end)
:ets.new(:test_blobs, [:public, :named_table])
{:ok, run: run, job: job, token: token}
end
end
defmodule MemStorage do
@behaviour GitGud.Storage
@impl true
def put(bucket, key, body, _opts) do
:ets.insert(:test_blobs, {{bucket, key}, IO.iodata_to_binary(body)})
:ok
end
@impl true
def get(bucket, key) do
case :ets.lookup(:test_blobs, {bucket, key}) do
[{_, body}] -> {:ok, body}
[] -> {:error, :not_found}
end
end
@impl true
def delete(bucket, key) do
:ets.delete(:test_blobs, {bucket, key})
:ok
end
@impl true
def presign_url(_b, _k, _m, _o), do: {:ok, ""}
end
test "cache endpoint requires a token", %{conn: conn} do
resp = get(conn, "/api/actions/_apis/artifactcache/cache?keys=foo&version=1")
assert resp.status == 401
end
test "cache GET returns 204 (always miss for now)", %{conn: conn, token: token} do
resp =
conn
|> put_req_header("authorization", "Bearer " <> token)
|> get("/api/actions/_apis/artifactcache/cache?keys=foo&version=1")
assert resp.status == 204
end
test "artifact upload + download round-trip via storage", %{
conn: conn,
run: run,
token: token
} do
create =
conn
|> put_req_header("authorization", "Bearer " <> token)
|> put_req_header("content-type", "application/json")
|> post(
"/api/actions/_apis/pipelines/workflows/#{run.id}/artifacts",
Jason.encode!(%{"name" => "logs.txt"})
)
assert create.status == 201
%{"containerId" => artifact_id} = Jason.decode!(create.resp_body)
body = "hello artifact"
upload =
conn
|> put_req_header("authorization", "Bearer " <> token)
|> put_req_header("content-type", "application/octet-stream")
|> post(
"/api/actions/_apis/pipelines/workflows/#{run.id}/artifacts/#{artifact_id}/upload",
body
)
assert upload.status == 200
download =
conn
|> put_req_header("authorization", "Bearer " <> token)
|> get("/api/actions/_apis/pipelines/workflows/#{run.id}/artifacts/#{artifact_id}/download")
assert download.status == 200
assert download.resp_body == body
end
test "list artifacts returns the persisted set", %{conn: conn, run: run, token: token} do
auth = fn c -> put_req_header(c, "authorization", "Bearer " <> token) end
for name <- ["a", "b"] do
resp =
conn
|> auth.()
|> put_req_header("content-type", "application/json")
|> post(
"/api/actions/_apis/pipelines/workflows/#{run.id}/artifacts",
Jason.encode!(%{"name" => name})
)
assert resp.status == 201
end
list =
conn
|> auth.()
|> get("/api/actions/_apis/pipelines/workflows/#{run.id}/artifacts")
body = Jason.decode!(list.resp_body)
assert body["count"] >= 2
names = body["value"] |> Enum.map(& &1["name"]) |> Enum.sort()
assert "a" in names and "b" in names
end
end