dotCMS / dotCMS/core

Push Publishing receiver bypasses workflow on ingest — optionally fire default workflow actions when receiving content

Open
#35,837 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

dotCMS : Push Publishing dotCMS : Workflow stale Team : Maintenance Type : Defect
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Summary

When content is ingested on a Push Publishing receiver (delivery environment), the system calls setLive() / setWorking() directly, bypassing the workflow engine entirely. This leaves the content's workflow step out of sync with its actual content state on the receiver — content can be live but still showing a "Draft" workflow step.

This is a systemic instance of the broader State vs. Step problem and was explicitly called out as one of the highest-impact sources of state/step divergence:

"Push Publishing or Push Removing Content (this is a biggie)" — Will Ezell, #eng March 2026

This issue proposes an opt-in configuration to allow the receiver to fire the content type's default workflow action during ingest, keeping state and step in sync.


Current behavior
  1. User publishes content on authoring → workflow fires → step = Published, state = live
  2. Content is push-published to receiver
  3. Receiver ingests the bundle → setLive() called directly, no workflow fired
  4. On receiver: state = live ✗ step = Draft (unchanged from authoring draft state)

Content is correctly live on the front end of the delivery environment, but the workflow step display is wrong. Any workflow-triggered side effects (notifications, indexing actionlets, integrations) are also silently skipped.

The same problem occurs in reverse when push-removing content: the receiver calls the equivalent of setWorking() / setDeleted() without firing an UNPUBLISH or ARCHIVE workflow action.


Expected behavior

An opt-in flag (suggested: PUSH_PUBLISH_USE_DEFAULT_WORKFLOW_ON_RECEIVER) that, when enabled, causes the receiver to:

  1. Look up the workflow scheme assigned to the incoming content type on the receiver
  2. Resolve the default action for the applicable system action (PUBLISH, UNPUBLISH, ARCHIVE) — same logic already used by /api/v1/workflow/fire/DEFAULT/PUBLISH
  3. Fire that action on the received content via WorkflowAPI (skipping actionlets flagged as sender-side only, to avoid side-effect duplication)
  4. If no default action is configured → fall back to current behavior (direct setLive()) and log a warning

"Optionally" is critical — unconditionally firing actionlets on receivers would cause double-notifications, push-publish loops, and hits to external APIs that customers have designed for authoring-side use only.


Reproduction steps
  1. Set up two dotCMS environments with Push Publishing configured (sender + receiver)
  2. On sender: create a content item and leave it in "Draft" workflow step
  3. On sender: run the Publish workflow action → content becomes live, step = "Published"
  4. Push-publish the content to the receiver
  5. On receiver: verify content is live on the front end ✓
  6. On receiver: open the content item in the UI → workflow step still shows "Draft"

Also reproducible in a single-environment setup via page cascade-publish (same root cause, same bypass).


Code references
  • PublishContentActionlet.java:75 — sets WORKFLOW_IN_PROGRESS = true on related content before cascade-publish, bypassing workflow
  • ESContentletAPIImpl.java:1200–1212 — workflow skipped entirely when WORKFLOW_IN_PROGRESS = true; only setLive() is called
  • WorkflowAPIImpl — default action resolution logic to reuse on the receiver side

Impact
  • Severity: High — affects all push-publishing customers; workflow step UI is permanently wrong for received content unless manually corrected
  • Workaround: On the receiver, manually open each affected content item and run the Publish workflow action to resync the step. Not feasible at scale.
  • Customer report: Freshdesk ticket #37387 — customer reports content appearing live on front end while UI shows "Draft"; also observes inconsistent behavior when removing content from pages in remote-publishing setups

Related

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with PublishContentActionlet.java:75 and ESContentletAPIImpl.java:1200–1212 to trace how WORKFLOW_IN_PROGRESS bypasses workflow during publishing. Then inspect WorkflowAPIImpl for the existing default-action resolution used by /api/v1/workflow/fire/DEFAULT/PUBLISH. Done means an opt-in receiver path handles publish, unpublish, and archive actions, preserves the current fallback with a warning, and avoids sender-only side effects.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend, content
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.