Transform into GitLab Push Triggerer
Takes in GitLab push webhook events instead of normal triggers
This commit is contained in:
parent
ac1eb372a4
commit
04f0bbb05b
5 changed files with 64 additions and 31 deletions
30
README.md
30
README.md
|
@ -1,8 +1,8 @@
|
|||
# GitLabPushTriggerer
|
||||
|
||||
GitLabPushTriggerer is a small application that triggers execution of scripts when given endpoints are hit
|
||||
with GET requests. It contains no permissions handling, no authentication, no request limiting. So
|
||||
these must be handled in some other way, like with an Nginx reverse proxy.
|
||||
GitLabPushTriggerer is a small application that triggers execution of scripts when given endpoints
|
||||
are hit with GitLab push webhooks. It contains no permissions handling, no authentication, no
|
||||
request limiting. So these must be handled in some other way, like with an Nginx reverse proxy.
|
||||
|
||||
Should work on any \*nix system that has `sh`.
|
||||
|
||||
|
@ -21,12 +21,17 @@ Configuration of endpoints and scripts is done via environment variables. Enviro
|
|||
are set in the following format:
|
||||
|
||||
```
|
||||
TRIGGERER_FOO=/path/to/bar.sh
|
||||
GLPT_FOO='master;/path/to/bar.sh'
|
||||
```
|
||||
|
||||
The variable consists of `TRIGGERER_` prefix, after which is the name of the endpoint. The value is
|
||||
the path to the script to execute. The above variable would result in an endpoint `/foo`, which would
|
||||
execute `/path/to/bar.sh`.
|
||||
The variable consists of `GLPT_` prefix, after which is the name of the endpoint. The value is
|
||||
the branch to match and path to the script to execute. The above variable would result in
|
||||
an endpoint `/foo`, which would execute `/path/to/bar.sh` if a push to branch `master` was
|
||||
called on the endpoint.
|
||||
|
||||
**NOTE:** Add the single quotes `'` to encase the value to prevent the shell messing up.
|
||||
|
||||
**LIMITATION:** The branch name cannot contain `;`.
|
||||
|
||||
The endpoint path is transformed to lowercase and underscores are replaced with dashes. See the
|
||||
following examples:
|
||||
|
@ -36,10 +41,13 @@ following examples:
|
|||
* `TRIGGERER_AAA_` → `/aaa-`
|
||||
|
||||
The path to the script can be absolute or relative, as long as it can be reached from the current
|
||||
working dir.
|
||||
working dir (for releases that can be the release dir; it is easier to use absolute paths). Scripts
|
||||
are executed with `sh -c script`.
|
||||
|
||||
## Return value
|
||||
|
||||
If the script was triggered, 200 OK is returned. If the script is not found or the request path is
|
||||
wrong, 404 File not found is returned. If there is an error in script execution, 500 Internal server
|
||||
error is returned and the error is logged.
|
||||
* If the script was triggered, `200 OK` is returned.
|
||||
* If the script is not found or the request path is wrong, `404 File not found` is returned.
|
||||
* If the branch does not match, `400 Bad request` is returned.
|
||||
* If there is an error in script execution, `500 Internal server error` is returned and the error
|
||||
is logged.
|
||||
|
|
|
@ -9,6 +9,14 @@ defmodule GitLabPushTriggerer.Router do
|
|||
|
||||
plug(Plug.Logger)
|
||||
plug(:match)
|
||||
|
||||
plug(
|
||||
Plug.Parsers,
|
||||
parsers: [:urlencoded, :multipart, :json],
|
||||
pass: ["*/*"],
|
||||
json_decoder: Jason
|
||||
)
|
||||
|
||||
plug(:dispatch)
|
||||
|
||||
paths =
|
||||
|
@ -16,23 +24,25 @@ defmodule GitLabPushTriggerer.Router do
|
|||
GitLabPushTriggerer.get_envs()
|
||||
end
|
||||
|
||||
match "/:path" do
|
||||
case Map.get(unquote(paths), path) do
|
||||
post "/:path" do
|
||||
with {branch, script} <- Map.get(unquote(paths), path),
|
||||
:ok <- check_branch(branch, conn.body_params),
|
||||
:ok <- GitLabPushTriggerer.run(script) do
|
||||
send_resp(conn, 200, "OK")
|
||||
else
|
||||
# Nil returned by Map.get
|
||||
nil ->
|
||||
route_not_found(conn)
|
||||
|
||||
script ->
|
||||
case GitLabPushTriggerer.run(script) do
|
||||
:ok ->
|
||||
send_resp(conn, 200, "OK")
|
||||
{:error, :file_not_found} ->
|
||||
send_resp(conn, 404, "File not found.")
|
||||
|
||||
{:error, :file_not_found} ->
|
||||
send_resp(conn, 404, "File not found.")
|
||||
{:error, :wrong_branch} ->
|
||||
send_resp(conn, 400, "Branch not matching.")
|
||||
|
||||
error ->
|
||||
Logger.error("Unknown error: #{inspect(error)}")
|
||||
send_resp(conn, 500, "Unknown error.")
|
||||
end
|
||||
error ->
|
||||
Logger.error("Unknown error: #{inspect(error)}")
|
||||
send_resp(conn, 500, "Unknown error.")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -46,4 +56,14 @@ defmodule GitLabPushTriggerer.Router do
|
|||
Logger.error(inspect(data))
|
||||
send_resp(conn, conn.status, "Something went wrong.")
|
||||
end
|
||||
|
||||
# Check that branch in data matches branch in configuration
|
||||
defp check_branch(branch, data) when is_binary(branch) and is_map(data) do
|
||||
with "refs/heads/" <> data_branch <- Map.get(data, "ref"),
|
||||
^branch <- data_branch do
|
||||
:ok
|
||||
else
|
||||
_ -> {:error, :wrong_branch}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
defmodule GitLabPushTriggerer do
|
||||
require Logger
|
||||
|
||||
@split_char ";"
|
||||
|
||||
@doc """
|
||||
Get all matching environment variables and their values. Returns a map where keys are the transformed
|
||||
paths and values are the given script paths.
|
||||
|
@ -9,14 +11,14 @@ defmodule GitLabPushTriggerer do
|
|||
|
||||
In these examples, sample env is given as argument. If no argument is given, system env is used.
|
||||
|
||||
iex> GitLabPushTriggerer.get_envs(%{"TRIGGERER_FOO" => "./test.sh"})
|
||||
%{"foo" => "./test.sh"}
|
||||
iex> GitLabPushTriggerer.get_envs(%{"GLPT_FOO" => "master;./test.sh"})
|
||||
%{"foo" => {"master", "./test.sh"}}
|
||||
|
||||
iex> GitLabPushTriggerer.get_envs(%{})
|
||||
%{}
|
||||
|
||||
iex> GitLabPushTriggerer.get_envs(%{"WRONG_FORMAT" => "no", "TRIGGERER_BAR_" => "baz", "TRIGGERER_" => "no", "TRIGGERER_GO_WILD" => "/bin/true"})
|
||||
%{"bar-" => "baz", "go-wild" => "/bin/true"}
|
||||
iex> GitLabPushTriggerer.get_envs(%{"WRONG_FORMAT" => "no", "GLPT_BAR_" => "um;baz", "GLPT_" => "no", "GLPT_GO_WILD" => "jeffum;/bin/true"})
|
||||
%{"bar-" => {"um", "baz"}, "go-wild" => {"jeffum", "/bin/true"}}
|
||||
"""
|
||||
@spec get_envs(%{optional(String.t()) => String.t()}) :: map
|
||||
def get_envs(envs \\ nil) do
|
||||
|
@ -25,9 +27,10 @@ defmodule GitLabPushTriggerer do
|
|||
envs
|
||||
|> Map.keys()
|
||||
|> Enum.reduce(%{}, fn
|
||||
"TRIGGERER_" <> rest = key, acc when rest != "" ->
|
||||
"GLPT_" <> rest = key, acc when rest != "" ->
|
||||
path = transform_path(rest)
|
||||
Map.put(acc, path, envs[key])
|
||||
[branch | rest] = String.split(envs[key], @split_char)
|
||||
Map.put(acc, path, {branch, Enum.join(rest, @split_char)})
|
||||
|
||||
_, acc ->
|
||||
acc
|
||||
|
|
5
mix.exs
5
mix.exs
|
@ -3,7 +3,7 @@ defmodule GitLabPushTriggerer.MixProject do
|
|||
|
||||
def project do
|
||||
[
|
||||
app: :triggerer,
|
||||
app: :gitlab_push_triggerer,
|
||||
version: "1.0.0",
|
||||
elixir: "~> 1.6",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
|
@ -24,7 +24,8 @@ defmodule GitLabPushTriggerer.MixProject do
|
|||
[
|
||||
{:plug, "~> 1.4.5"},
|
||||
{:distillery, "~> 1.5"},
|
||||
{:cowboy, "~> 1.1"}
|
||||
{:cowboy, "~> 1.1"},
|
||||
{:jason, "~> 1.0.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
1
mix.lock
1
mix.lock
|
@ -2,6 +2,7 @@
|
|||
"cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm"},
|
||||
"distillery": {:hex, :distillery, "1.5.2", "eec18b2d37b55b0bcb670cf2bcf64228ed38ce8b046bb30a9b636a6f5a4c0080", [:mix], [], "hexpm"},
|
||||
"jason": {:hex, :jason, "1.0.0", "0f7cfa9bdb23fed721ec05419bcee2b2c21a77e926bce0deda029b5adc716fe2", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
|
||||
"mime": {:hex, :mime, "1.2.0", "78adaa84832b3680de06f88f0997e3ead3b451a440d183d688085be2d709b534", [:mix], [], "hexpm"},
|
||||
"plug": {:hex, :plug, "1.4.5", "7b13869283fff6b8b21b84b8735326cc012c5eef8607095dc6ee24bd0a273d8e", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"},
|
||||
|
|
Loading…
Reference in a new issue