Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ config :bob,
master_schedule: [],
agent_schedule: []

config :ex_aws,
access_key_id: "test",
secret_access_key: "test",
http_client: Bob.FakeHttpClient

config :logger, level: :warning
15 changes: 11 additions & 4 deletions lib/bob/repo.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@ defmodule Bob.Repo do

# TODO: Use S3 object metadata
def fetch_built_refs(build_path) do
Path.join(build_path, "builds.txt")
|> fetch_file()
|> String.split("\n", trim: true)
|> Map.new(&line_to_ref/1)
path = Path.join(build_path, "builds.txt")

case ExAws.S3.get_object(@bucket, path, []) |> ExAws.request() do
{:ok, %{body: body}} ->
body
|> String.split("\n", trim: true)
|> Map.new(&line_to_ref/1)

{:error, {:http_error, 404, _}} ->
%{}
end
end

def fetch_file(path) do
Expand Down
4 changes: 4 additions & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ defmodule Bob.Mixfile do
version: "0.0.1",
elixir: "~> 1.18",
start_permanent: Mix.env() == :prod,
elixirc_paths: elixirc_paths(Mix.env()),
releases: releases(),
deps: deps()
]
end

defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]

def application() do
[
mod: {Bob.Application, []},
Expand Down
46 changes: 46 additions & 0 deletions test/bob/repo_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
defmodule Bob.RepoTest do
use ExUnit.Case

alias Bob.Repo

setup do
Bob.FakeHttpClient.reset()
:ok
end

describe "fetch_built_refs/1" do
test "parses lines into a ref_name => ref map" do
body = """
OTP-26.2 abc123 2026-01-01T00:00:00Z hash1
OTP-27.0 def456 2026-02-01T00:00:00Z hash2
"""

Bob.FakeHttpClient.stub(
:get,
"https://s3.amazonaws.com/s3.hex.pm/builds/otp/amd64/ubuntu-24.04/builds.txt",
200,
body
)

assert Repo.fetch_built_refs("builds/otp/amd64/ubuntu-24.04") == %{
"OTP-26.2" => "abc123",
"OTP-27.0" => "def456"
}
end

test "returns an empty map when builds.txt does not exist yet" do
assert Repo.fetch_built_refs("builds/otp/amd64/ubuntu-26.04") == %{}
end

test "returns an empty map when builds.txt is empty" do
Bob.FakeHttpClient.stub(
:get,
"https://s3.amazonaws.com/s3.hex.pm/builds/otp/amd64/ubuntu-24.04/builds.txt",
200,
""
)

assert Repo.fetch_built_refs("builds/otp/amd64/ubuntu-24.04") == %{}
end
end
end
33 changes: 33 additions & 0 deletions test/support/fake_http_client.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
defmodule Bob.FakeHttpClient do
@behaviour ExAws.Request.HttpClient

@impl true
def request(method, url, _body, _headers, _http_opts) do
case :persistent_term.get({__MODULE__, {method, url}}, :not_found) do
:not_found -> {:ok, %{status_code: 404, headers: [], body: not_found_body(url)}}
response -> {:ok, response}
end
end

def stub(method, url, status_code, body) do
:persistent_term.put(
{__MODULE__, {method, url}},
%{status_code: status_code, headers: [], body: body}
)
end

def reset() do
for {{__MODULE__, _key} = key, _value} <- :persistent_term.get() do
:persistent_term.erase(key)
end
end

defp not_found_body(url) do
key = URI.parse(url).path |> String.trim_leading("/")

"""
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>#{key}</Key></Error>
"""
end
end
Loading