Repository navigation
Collapse :add and :install into one verb (0.2.0) - #1
Merged
Merged
Conversation
Whether a package ships an Igniter installer is upstream's business and
changes over time, but the two-verb API made every workflow file encode
it: a package gaining an installer meant hand-editing {:add, :x} to
{:install, :x} in every workflow naming it.
That distinction only existed because installs had to be queued into a
subprocess, which in turn rested on the belief that installers cannot be
composed mid-run. They can — Igniter's own run_installers/5 composes them
into the same igniter; igniter.install just ends with do_or_dry_run
because it is a top-level task.
So installs now happen in-run, using public Igniter API: collect the
install packages up front, add and fetch them once via
apply_and_fetch_dependencies/2 (which writes only the deps change,
leaving the rest of the diff pending), then compose each <pkg>.install at
its position in the step list.
With installs composable, the verbs collapse: {:add, name} runs Starter's
step when it has one and otherwise installs the package and runs its own
installer. {:install, name} survives as the explicit override.
Consequences:
- One diff, one confirmation. No queued subprocess for installs, so the
--yes-into-subprocess workaround (0.1.1) and the argv-leak bug (0.1.2)
are structurally impossible for installs.
- Ordering is list position. A step after one that installs a package
sees its effects, so sort_deps is an in-run step again and oban_pro
just follows oban. This supersedes 0.1.2's queued sort_deps.
- Runs print a plan naming what each step resolved to, which is where
the built-in-vs-installer distinction lives now that the step list no
longer draws it.
The fall-through means a typo'd step name would become a doomed Hex
lookup, so names closely resembling a built-in step raise a suggestion
instead.
Dependencies remain the one thing that reaches disk before the main
diff — an installer has to be on disk to compose at all. That change is
shown and confirmed on its own.
Verified against a real project: oban.install runs in-run, and sort_deps
placed last sorts the deps the installers added.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e210091. Configure here.
jamilabreu
added a commit
that referenced
this pull request
Aug 6, 2026
0.2.0 added every package a workflow installs to mix.exs before any step
runs, which quietly broke the oban_pro step's guard. has_dep?(:oban) used
to mean "Oban is already set up" — reliable when installs were queued to
run after the workflow — but now answers "will oban be a dep?", which is
true from the start whenever oban appears anywhere in the list.
So {:add, :oban_pro} placed before {:add, :oban} passed the guard and
wrote Oban config that oban.install then clobbers, where the old queued
behavior warned and skipped.
Guard on Oban's config instead. Since oban.install now composes into the
same run, a later step can see what it wrote, so this is both correct and
order-sensitive in the way the dep check no longer was.
The warning also still pointed at {:install, :oban} and
{:queue, "starter.add", ["oban_pro"]} — the API 0.2.0 removed.
CI missed this because the golden test runs `mix starter.run --yes` with
no flags, so oban_pro (behind --oban-pro) never executed. It now passes
the flags CI can run. --oban-pro is not among them: oban_pro is licensed
and lives in a private Hex repo, so it stays unit-tested only.
Reported by Cursor Bugbot on #1. Its second finding — that private-repo
deps break — is not a regression: igniter.install resolves string deps
through the same determine_dep_type_and_version!/2, so bare names have
always resolved against public Hex. Documented the qualified form
instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Whether a package ships an Igniter installer is upstream's business and
changes over time, but the two-verb API made every workflow file encode
it: a package gaining an installer meant hand-editing {:add, :x} to
{:install, :x} in every workflow naming it.
That distinction only existed because installs had to be queued into a
subprocess, which in turn rested on the belief that installers cannot be
composed mid-run. They can — Igniter's own run_installers/5 composes them
into the same igniter; igniter.install just ends with do_or_dry_run
because it is a top-level task.
So installs now happen in-run, using public Igniter API: collect the
install packages up front, add and fetch them once via
apply_and_fetch_dependencies/2 (which writes only the deps change,
leaving the rest of the diff pending), then compose each .install at
its position in the step list.
With installs composable, the verbs collapse: {:add, name} runs Starter's
step when it has one and otherwise installs the package and runs its own
installer. {:install, name} survives as the explicit override.
Consequences:
--yes-into-subprocess workaround (0.1.1) and the argv-leak bug (0.1.2)
are structurally impossible for installs.
sees its effects, so sort_deps is an in-run step again and oban_pro
just follows oban. This supersedes 0.1.2's queued sort_deps.
the built-in-vs-installer distinction lives now that the step list no
longer draws it.
The fall-through means a typo'd step name would become a doomed Hex
lookup, so names closely resembling a built-in step raise a suggestion
instead.
Dependencies remain the one thing that reaches disk before the main
diff — an installer has to be on disk to compose at all. That change is
shown and confirmed on its own.
Verified against a real project: oban.install runs in-run, and sort_deps
placed last sorts the deps the installers added.
Note
High Risk
This rewrites core workflow execution (dep prefetch timing, single diff vs subprocess installs) and changes the public step semantics users encode in workflow files, though
{:install}is preserved.Overview
0.2.0 collapses package setup into
{:add, name}: built-in Starter steps when they exist, otherwise add the dep and compose the package’s<name>.installinside the same Igniter run.{:install, name}remains as an explicit “always use upstream’s installer” override.Starter.Runnerno longer queuesmix igniter.installafter apply. Install packages are collected up front, written tomix.exs, and fetched viaIgniter.apply_and_fetch_dependencies/2(separate confirm), then each installer runs at its list position in one combined diff. Runs print a Starter plan of how each step resolved, andStarter.Runner.installs/2exposes the prefetch package set.mix starter.new’s catalog now uses{:add, :oban}(etc.) withoban_proafteroban, andsort_depsas an in-run{:gen}step instead of a post-install queue.{:add}typos near built-in names raise “Did you mean?” instead of Hex lookups.Reviewed by Cursor Bugbot for commit e210091. Bugbot is set up for automated code reviews on this repo. Configure here.