lib/openagents/deployments/approval.ex

main at 58e6347eeb72 · 1 KB

defmodule OpenAgents.Deployments.Approval do
  @moduledoc """
  One approver's decision on one run.

  The decision records the request digest it was made against, so an approval
  can never be carried onto different bytes: if the input changes, the run
  changes, and the old approval no longer applies to anything.
  """

  use Ecto.Schema

  import Ecto.Changeset

  @decisions ~w(approved rejected)

  @type t :: %__MODULE__{}

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id
  @timestamps_opts [type: :utc_datetime_usec]

  schema "deployment_approvals" do
    field :decision, :string
    field :rule, :string
    field :request_digest, :string
    field :comment, :string
    field :decided_at, :utc_datetime_usec

    belongs_to :repository, OpenAgents.Repositories.Repository
    belongs_to :deployment_run, OpenAgents.Deployments.Run
    belongs_to :approver_user, OpenAgents.Accounts.User

    timestamps()
  end

  @doc false
  def changeset(approval, attrs) do
    approval
    |> cast(attrs, [:decision, :comment])
    |> validate_required([:decision, :rule, :request_digest, :decided_at])
    |> validate_inclusion(:decision, @decisions)
    |> validate_length(:comment, max: 500)
    |> unique_constraint(:approver_user_id,
      name: :deployment_approvals_deployment_run_id_approver_user_id_index
    )
  end

  @doc "The decisions an approver can record."
  @spec decisions() :: [String.t()]
  def decisions, do: @decisions
end