Skip to content
This repository has been archived by the owner on Mar 25, 2023. It is now read-only.

Create org #8

Merged
merged 8 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from 6 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
27 changes: 27 additions & 0 deletions lib/gitea.ex
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,33 @@ defmodule Gitea do
Gitea.Http.post(url, params)
end

@doc """
Create an organisation on Gitea
"""
@spec remote_org_create(String.t(), list()) :: {:ok, map} | {:error, any}
def remote_org_create(org_name, opts \\ []) do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason we don't just pass in a Map of params instead of the org_name and opts ? 💭

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw the remote_org_create function having only one required argument (the org_name) and the other values (description, full_name and visibility) as optional similar to the gitea api and the UI. In this case I think it makes sense to use a keyword list as it is used for this type of optional argument
see: https://elixir-lang.org/getting-started/keywords-and-maps.html#keyword-lists

Keyword lists are a data-structure used to pass options to functions

However if you consider that all the values are required we can pass a Map (or even define a struct).

Let me know if you prefer the "map" version of the function

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, sadly, remote_org_create/1 in Gogs didn't work dwyl/gogs#8 (comment) so I didn't pursue it ...
I find keyword lists cumbersome.
in this case having a single params argument with all the necessary fields (only params.username is required) will make it immediately clear to the person using the app that their params are passed in directly.

url = api_base_url() <> "orgs"

params = %{
descriptions: opts[:description] || "org description",
full_name: opts[:full_name] || org_name,
username: org_name,
visibility: opts[:visibility] || "private"
}

Gitea.Http.post(url, params)
end

@doc """
Create an organisation on Gitea
"""
@spec remote_org_delete(String.t()) :: {:ok, map} | {:error, any}
def remote_org_delete(org_name) do
url = api_base_url() <> "orgs/#{org_name}"

Gitea.Http.delete(url)
end

@doc """
`remote_repo_delete/2` accepts two arguments: `org_name` and `repo_name`.
It deletes the repo on the remote `Gitea` instance as defined
Expand Down
9 changes: 7 additions & 2 deletions lib/http.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ defmodule Gitea.Http do
"""
@spec parse_body_response({atom, String.t()} | {:error, any}) :: {:ok, map} | {:error, any}
def parse_body_response({:error, err}), do: {:error, err}
def parse_body_response({:ok, response = %{status_code: 204}}), do: {:ok, response}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for status code here instead of checking if the body exists as a 204 status code response has an empty body.
see https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204 and https://gitea-server.fly.dev/api/swagger#/organization/orgDelete

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth including this comment in-line (in the code) as it will be lost here in the PR ...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I've added this definition is to avoid changing the code below:

 if body == nil || byte_size(body) == 0 do

My first thought was to remove the byte_size(body) == 0 condition as I don't think parse_body_response should return {:error, :no_body} when the body is an empty string (it is defined like this when deleting orgs or repos). However I didn't want to break existing tests in case I missed something.

I'll add a comment in the code

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I didn't know what to return. Please use your judgement. 👍


def parse_body_response({:ok, response}) do
# Logger.debug(response) # very noisy!
body = Map.get(response, :body)

if body == nil || byte_size(body) == 0 do
Logger.warning("GiteaHttp.parse_body_response: response body is nil!")
{:error, :no_body}
Expand All @@ -63,6 +64,7 @@ defmodule Gitea.Http do
@spec get(String.t()) :: {:ok, map} | {:error, any}
def get(url) do
Logger.debug("GiteaHttp.get #{url}")

inject_poison().get(url, json_headers())
|> parse_body_response()
end
Expand Down Expand Up @@ -94,8 +96,9 @@ defmodule Gitea.Http do
# Logger.debug("raw_markdown: #{raw_markdown}")
headers = [
{"Accept", "text/html"},
auth_header(),
auth_header()
]

inject_poison().post(url, raw_markdown, headers)
end

Expand All @@ -109,6 +112,7 @@ defmodule Gitea.Http do
def post(url, params \\ %{}) do
Logger.debug("GiteaHttp.post #{url}")
body = Jason.encode!(params)

inject_poison().post(url, body, json_headers())
|> parse_body_response()
end
Expand All @@ -120,6 +124,7 @@ defmodule Gitea.Http do
@spec delete(String.t()) :: {:ok, map} | {:error, any}
def delete(url) do
Logger.debug("GiteaHttp.delete #{url}")

inject_poison().delete(url <> "?token=#{access_token()}")
|> parse_body_response()
end
Expand Down
45 changes: 32 additions & 13 deletions lib/httpoison_mock.ex
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,24 @@ defmodule Gitea.HTTPoisonMock do
def post(url, body, headers) do
Logger.debug("Gitea.HTTPoisonMock.post/3 #{url}")

if String.contains?(url, "markdown/raw") do
post_raw_html(url, body, headers)
else
body_map = Jason.decode!(body) |> Useful.atomize_map_keys()
cond do
url =~ "markdown/raw" ->
post_raw_html(url, body, headers)

response_body =
make_repo_create_post_response_body(body_map.name)
|> Jason.encode!()
url =~ "/repo" ->
body_map = Jason.decode!(body) |> Useful.atomize_map_keys()

{:ok, %HTTPoison.Response{body: response_body, status_code: 200}}
response_body =
make_repo_create_post_response_body(body_map.name)
|> Jason.encode!()

{:ok, %HTTPoison.Response{body: response_body, status_code: 200}}

url =~ "/orgs" ->
{:ok, %HTTPoison.Response{body: Jason.encode!(%{username: "new_org"}), status_code: 200}}

true ->
{:ok, %HTTPoison.Response{body: Jason.encode!(""), status_code: 404}}
end
end

Expand All @@ -135,11 +143,22 @@ defmodule Gitea.HTTPoisonMock do
"""
def delete(url) do
Logger.debug("Gitea.HTTPoisonMock.delete/1 #{url}")
# check delete request endpooints
cond do
# match delete org
url =~ "/orgs" ->
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check what is the delete request (delete org or delete repo at the moment) and returns response accordingly

{:ok,
%HTTPoison.Response{
body: "",
status_code: 204
}}

{:ok,
%HTTPoison.Response{
body: Jason.encode!(%{deleted: List.first(String.split(url, "?"))}),
status_code: 200
}}
true ->
{:ok,
%HTTPoison.Response{
body: Jason.encode!(%{deleted: List.first(String.split(url, "?"))}),
status_code: 200
}}
end
end
end
10 changes: 10 additions & 0 deletions test/gitea_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ defmodule GiteaTest do
Gitea.remote_repo_delete(org_name, repo_name)
end

test "remote_org_create\2 create a new organistaion" do
org_name = "new_org"
{:ok, response} = Gitea.remote_org_create(org_name)

assert response.username
# delete organisation to allow test to run again
{:ok, response_delete} = Gitea.remote_org_delete(org_name)
assert response_delete.status_code == 204
end

test "remote_repo_create/3 creates a new repo on the gitea server" do
org_name = "myorg"
repo_name = test_repo()
Expand Down
12 changes: 10 additions & 2 deletions test/httpoison_mock_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ defmodule HttPoisonMockTest do
assert status == 200
end

test "Gitea.HTTPoisonMock.post any url should return status 200" do
test "Gitea.HTTPoisonMock.post /repos/org_name should return status 200" do
{:ok, %HTTPoison.Response{status_code: status, body: resp_body}} =
Gitea.HTTPoisonMock.post("hi", Jason.encode!(%{name: "simon"}), "any-header")
Gitea.HTTPoisonMock.post("/repos/myorg", Jason.encode!(%{name: "simon"}), "any-header")

assert status == 200
body_map = Jason.decode!(resp_body) |> Useful.atomize_map_keys()
Expand All @@ -33,7 +33,15 @@ defmodule HttPoisonMockTest do
test "Gitea.HTTPoisonMock.post when url is markdown/raw should return status 200" do
{:ok, %HTTPoison.Response{status_code: status, body: body}} =
Gitea.HTTPoisonMock.post("markdown/raw", "any", "any")

assert status == 200
assert body == Gitea.HTTPoisonMock.raw_html()
end

test "Gitea.HTTPoisonMock.post when url is not supported should return status 404" do
{:ok, %HTTPoison.Response{status_code: status}} =
Gitea.HTTPoisonMock.post("/not-defined", "any", "any")

assert status == 404
end
end