# `Gamend.Hooks.PluginBuilder`
[🔗](https://github.com/appsinacup/gamend/blob/v1.0.7/lib/gamend/hooks/plugin_builder.ex#L1)

Builds an OTP plugin bundle from plugin source code on disk.

This is intended for admin-only workflows in development/self-hosted setups.
It runs `mix` commands on the server host/container.

# `build_result`

```elixir
@type build_result() :: %{
  ok?: boolean(),
  plugin: String.t(),
  source_dir: String.t(),
  started_at: DateTime.t(),
  finished_at: DateTime.t(),
  steps: [step_result()]
}
```

# `step_result`

```elixir
@type step_result() :: %{
  cmd: String.t(),
  status: non_neg_integer(),
  output: String.t()
}
```

# `available?`

```elixir
@spec available?() :: boolean()
```

Whether this image can build plugin bundles at all.

The build shells out to `mix`, which a release image built from
`Dockerfile.release` does not ship: it carries compiled `.beam` files and no
build toolchain. Callers check this so an image without Mix presents a
disabled control with a reason, instead of three `System.cmd/3` calls that
fail on :enoent and surface as a build error.

# `build`

```elixir
@spec build(String.t()) :: {:ok, build_result()} | {:error, term()}
```

# `list_buildable_plugins`

```elixir
@spec list_buildable_plugins() :: [String.t()]
```

# `sources_dir`

```elixir
@spec sources_dir() :: String.t()
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
