v2.9.0
Release notes for orun v2.9.0.
Highlights
- Dependency include policy (
dependsOn[].include). Dependencies now separate two orthogonal questions: ordering (existingdependsOn/dependencyModebehavior) and plan inclusion. The newincludefield controls whether a dependency should be pulled into a--changedplan when only the dependent component changed. - Behavior change for
--changedplanning. The default is nowinclude: if-selected, which means change-detected plans only contain components that actually changed (plus their order edges when both ends are already in the plan). Components that were silently pulled in by transitivedependsOnin v2.8.0 and earlier are no longer included unless authors explicitly opt in withinclude: always.
New: dependsOn[].include
| Value | Selection behavior | Best for |
|---|---|---|
if-selected | Add an ordering edge only when both components are already selected | Default for most component dependencies |
always | Pull the dependency into the plan and add the ordering edge | Migrations, codegen, shared infra, parent package build |
if-selected is the built-in default and is applied during
normalization.
Default: order-only
metadata:
name: web-console
spec:
type: cloudflare-pages-turbo
dependsOn:
- component: ui-package
# include: if-selected (default)
Change-detection behavior:
changed: web-console -> plan: web-console
changed: ui-package -> plan: ui-package
changed: web-console + ui-pkg -> plan: ui-package -> web-console
full plan -> plan: ui-package -> web-console
Opt-in: always pull the dependency in
metadata:
name: api-edge-worker
spec:
type: cloudflare-worker-turbo
dependsOn:
- component: identity-schema
include: always
reason: api requires latest generated identity contract before deploy
changed: api-edge-worker -> plan: identity-schema -> api-edge-worker
Use include: always for schema generation, database migrations,
codegen, artifact publishing, or any dependency whose output must be
refreshed before the dependent runs.
Planner algorithm
The planner now thinks in three sets:
ChangedSet = components directly changed (files / trigger scope)
SelectedSet = components included in this plan
DependencyEdges = ordering edges between selected jobs
- Seed
SelectedSetfrom changed / full / explicit scope. - Walk
SelectedSetalong each component'sdependsOn. - For each edge:
include: if-selected— do NOT add the dependency; add the edge only if the dependency is already selected.include: always— add the dependency toSelectedSet, then add the edge.
- Repeat until
SelectedSetstops growing. - Compile, validate the DAG, render the plan.
This keeps the planner deterministic and keeps the compiled plan as the visible truth — the runner consumes the plan rather than reinterpreting intent.
Orthogonal semantics
dependsOn = ordering relationship
include = plan selection behavior (new in v2.9.0)
condition = success/failure gating behavior
dependencyMode = enforced / advisory / disabled (v2.8.0)
These can be combined. For example, a PR plan can use
dependencyMode: advisory (parallel feedback) together with the
default include: if-selected (don't drag unchanged components in).
Migration
If a v2.8.0 intent file relied on --changed plans transitively
pulling in dependencies, add include: always to those edges:
dependsOn:
- component: database-migration
+ include: always
+ reason: api cannot deploy without fresh schema
The CWD context scope (orun plan from inside a component
directory) intentionally keeps the old "give me this component and
everything it needs" behavior so you still see the full footprint of
a fresh plan when working locally on a single component.
Validation
Invalid include values are rejected at plan time:
component api: dependsOn[0].include "sometimes" is invalid
(expected "if-selected" or "always")
Missing-dependency errors are now scoped to include: always:
dependency not found: api.pr depends on db.pr (include: always)
Previously a missing dep was always an error. Under the new default
this is just an order-only edge that drops silently when the other
end isn't part of the plan — which is exactly what --changed wants.