Problem/Motivation

The action task offers two targets: the entity a process variable names, and the process's attached entity. The second belongs to Orchestra Content, so the task holds AttachmentManagerInterface as a nullable service, asks the container whether that service exists, and resolves nothing from the attached branch when it does not. The dependency is real but undeclared.

It is the only one of its kind here. Every other relationship between submodules, eighteen of them, is declared in info.yml. This is not a pattern the project uses; it is one place that grew a guarded reference instead.

What it costs is a target that can be configured and can never work. The settings form offers the attached entity whatever is installed, an author picks it, and the run finds out at the step, with a message about an entity that could not be resolved.

Proposed resolution

Extract the attachment-agnostic machinery of ActionTask into an abstract ActionTaskBase in orchestra_action: instantiating the action, the settings subform and its JSON round-trip, the context-aware interface, and the success and failure contract, leaving one abstract method to resolve the entity the action needs. ActionTask is final today, which is what makes extracting the base the enabling step.

ActionTask then resolves an entity a process variable names, and nothing else. A new bridge submodule, orchestra_content_action, depends on orchestra_content and orchestra_action and ships ContentActionTask, which resolves the attached entity under an attachment key. The target setting goes with them: each task type does one thing rather than switching between two, which is what put a nullable service and a form offering an unusable option into the action module in the first place. A bridge rather than a dependency on orchestra_content itself keeps the action module off everyone who only wants the entity-form interaction.

Models are rewritten rather than supported in both shapes: an action node targeting the attached entity becomes a content_action node, and one targeting a variable keeps its variable and loses a setting that only ever had one useful value. No workflow shipped with the project uses the attached target, so nothing in config/install or config/optional changes.

Letting ECA start a workflow with variables

Binding the entity a run is about is two collaborators: the engine starts the run and hands the new instance to start()'s on_started callable, and the attachment manager binds from inside it. That is the ordering the binding needs, but it leaves every caller of a content-bound workflow writing the same closure. The Tugboat demo seeding the preview is four lines of it.

The attach_entity task makes a better answer possible: the example_content_review workflow could bind itself, with an attach step reading the entity type and id from two process variables, and every caller would then start it like any other workflow, naming the article in a variable and composing nothing.

What stops that today is that no ECA start action can seed process variables. Both orchestra_start_process and orchestra_start_process_for_entity take only a definition id and a token name, and neither passes anything to start()'s variables, so a workflow that binds itself would find them unset on the ECA path and dead-letter that run.

So orchestra_start_process takes them: one per line as name: value, split on the first colon with both sides trimmed, values token-replaced, an empty value for a line without one. That is the same shape the subprocess task already uses for its variable map, and it is useful on its own, since a model knows what fired it and can now say so.

orchestra_start_process_for_entity then has nothing of its own left, and goes. Its job was handing an event's entity to the run as a type and an id, and a model can name those itself: [entity:entity_type] and [entity:id] resolve for any content entity an event puts in scope, including entity types with no token support of their own, so the coverage argument that would have kept it does not hold. Pre-1.0, so it is deleted rather than deprecated, and a model using it moves to orchestra_start_process with two lines of variables. orchestra_content_eca is left with the one action that genuinely needs the attachment manager, which is what that module is for.

The example workflow gets its attach step, and the Tugboat seed, the tests and the shipped ECA model all start it the same way: name the content in two variables and let the model bind it. The closure stays for what it is actually for: a caller that needs the binding in place before the first node runs, rather than at the first node.

AI-Generated: Yes (Claude Code was used to help draft this issue summary and to write the code and its tests on the merge request. I reviewed the work, and each new test was confirmed to fail without the change it covers and to pass with it.)

Issue fork orchestra-3622824

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mably created an issue. See original summary.

mably’s picture

Title: Extract ActionTaskBase and move the attached-entity target to a content bridge » Follow-ups from the attach task: a content bridge for the attached action target, and ECA starting a workflow with variables
Issue summary: View changes

mably’s picture

Issue summary: View changes
mably’s picture

Status: Active » Needs review
mably’s picture

Title: Follow-ups from the attach task: a content bridge for the attached action target, and ECA starting a workflow with variables » Split the action task on its base, and let ECA start a workflow with variables
mably’s picture

Issue summary: View changes

  • mably committed f056b227 on 1.x
    task: #3622824 Split the action task on its base, and let ECA start a...
mably’s picture

Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.