Starter.Workflow behaviour (starter v0.2.0)

Copy Markdown View Source

Defines a setup workflow: an ordered list of steps applied to a project.

use Starter.Workflow turns a module into a full Igniter.Mix.Task. Name it under Mix.Tasks (for example Mix.Tasks.MyApp.Workflow) and it becomes runnable as mix my_app.workflow — or via mix starter.run, which finds it — with a --flag option for every optional step.

Step forms

  • {:add, :credo} — get a package into the app: Starter's own step when it has one, otherwise the package is installed and its own installer runs. Which of the two applies is upstream's business, not something a workflow file should encode.
  • {:remove, :topbar} — run the built-in remove step topbar
  • {:gen, :gitignore} — run the built-in gen step gitignore
  • {:add, :oban, if: :oban} — only when the --oban flag is passed
  • {:install, :ash} — force the package's own installer, skipping any built-in step of the same name. Rarely needed; {:add, :ash} already resolves this way when Starter ships no step.
  • {:task, "some.igniter.task"} — compose any Igniter-aware Mix task, with optional argv and an if: option as a fourth element; non-Igniter tasks are skipped with a warning
  • {:queue, "starter.add", ["oban_pro"]} — queue any Mix task to run after the workflow's changes apply; use this only for work that must see the applied project on disk
  • {:workflow, OtherWorkflow} — include another workflow's steps
  • MyApp.Steps.Custom — any module implementing Igniter.Mix.Task, optionally as {MyApp.Steps.Custom, if: :flag}

Queued tasks run non-interactively with --yes appended — their subprocesses have no stdin, so a prompt there could never be answered. Confirming the workflow's diff is the approval for everything it queues; queued tasks must tolerate the --yes flag (every Igniter task does).

Ordering

Steps apply in list order, installers included, and every change lands in one diff you confirm once. A step placed after one that installs a package sees its effects, so ordering is just list position — e.g. {:gen, :sort_deps} at the end sorts the deps the installers added.

The one exception is dependencies. Packages that resolve to an install are added to mix.exs and fetched before any step runs, because their installers have to be on disk to compose. That dependency change is written and confirmed on its own, ahead of the run's main diff.

Queued steps still run last, in list order, after everything applies.

Each run prints a plan showing what every step resolved to — a built-in step, a package's installer, a plain dependency, or queued work.

Example

defmodule Mix.Tasks.MyApp.Workflow do
  use Starter.Workflow

  @impl Starter.Workflow
  def steps do
    [
      {:remove, :daisy_ui},
      {:gen, :gitignore},
      {:add, :credo},
      {:add, :oban, if: :oban}
    ]
  end
end

Running mix my_app.workflow applies every unconditional step; mix my_app.workflow --oban also applies the Oban step.

Summary

Types

A single entry in a workflow's steps/0 list.

Callbacks

Returns the workflow's steps, in the order they should run.

Functions

Returns every flag referenced by if: options in the given steps, including flags of nested workflows.

Returns every flag used by the given workflow module.

Types

step()

@type step() ::
  {:add | :remove | :gen, atom()}
  | {:add | :remove | :gen, atom(), keyword()}
  | {:install, atom()}
  | {:install, atom(), keyword()}
  | {:queue, String.t()}
  | {:queue, String.t(), [String.t()]}
  | {:queue, String.t(), [String.t()], keyword()}
  | {:task, String.t()}
  | {:task, String.t(), [String.t()]}
  | {:task, String.t(), [String.t()], keyword()}
  | {:workflow, module()}
  | {:workflow, module(), keyword()}
  | module()
  | {module(), keyword()}

A single entry in a workflow's steps/0 list.

Callbacks

steps()

@callback steps() :: [step()]

Returns the workflow's steps, in the order they should run.

Functions

flags(steps)

@spec flags([step()]) :: [atom()]

Returns every flag referenced by if: options in the given steps, including flags of nested workflows.

flags_of(workflow)

@spec flags_of(module()) :: [atom()]

Returns every flag used by the given workflow module.