Skip to content

feat: cascade parent issue status to sub-issues on close#9433

Open
kimnamwook1 wants to merge 2 commits into
makeplane:previewfrom
kimnamwook1:feat/status-cascade
Open

feat: cascade parent issue status to sub-issues on close#9433
kimnamwook1 wants to merge 2 commits into
makeplane:previewfrom
kimnamwook1:feat/status-cascade

Conversation

@kimnamwook1

@kimnamwook1 kimnamwook1 commented Jul 18, 2026

Copy link
Copy Markdown

Description

Adds an opt-in, per-project automation that cascades a parent issue's closing state to its sub-issues. When a parent enters a Completed or Cancelled state and the project has the toggle enabled, all non-terminal descendants (recursively) are moved to the parent's new state.

Backend

  • Project.cascade_state_on_close flag (+ migration 0122).
  • cascade_state_to_sub_issues Celery task: BFS over the sub-issue tree with a visited set + depth cap, bulk_update, and one issue_activity per changed child — modeled on the existing close_old_issues automation.
  • Hook in IssueViewSet.partial_update: fires only when the parent enters a completed/cancelled group (never on reopen or terminal→terminal) and the project opted in.

Frontend

  • New "Auto-close sub-issues" toggle under Project Settings → Automations.
  • IProject.cascade_state_on_close + English i18n strings.

Behavior: Completed parent → sub-issues completed; Cancelled parent → sub-issues cancelled. Already-closed sub-issues are skipped (idempotent). Traversal is bounded (depth cap + visited set) since Issue.parent has no cycle guard.

Note: the sub-issue widget reflects cascaded states on the next fetch; a live in-place UI refresh can be a small follow-up.

Type of Change

  • Feature (non-breaking change which adds functionality)

Screenshots and Media (if any)

The change adds a toggle under Project Settings → Automations ("Auto-close sub-issues"), following the existing Auto-archive / Auto-close pattern.

Test Scenarios

  • Enable the toggle; move a parent with open sub-issues to a Completed state → all non-terminal sub-issues become Completed (recursively). Cancelled behaves symmetrically.
  • Already Completed/Cancelled sub-issues are left untouched (idempotent).
  • Reopening a parent does not change sub-issues.
  • Toggle off → no cascade.
  • Automated: unit tests (plane/tests/unit/bg_tasks/test_issue_cascade_task.py) + a contract test for the view gate; passing locally against the docker-compose-test stack.

References

Closes #9432

Summary by CodeRabbit

  • New Features
    • Added an optional project automation to cascade completed/cancelled states from a parent issue to descendant sub-issues that are not yet closed.
    • Added a project setting toggle to enable/disable this behavior (off by default).
  • UI / Localization
    • Added “Auto-close sub-issues” automation controls to the project automations page.
    • Added translated project-settings text for the new automation.
  • Tests
    • Added contract and unit test coverage for cascading, terminal-to-terminal behavior, descendant recursion, cycle safety, and safety caps.

Note on locale values: the 18 non-English locales carry English placeholders pending translation. This repo's translations appear to be managed in bulk rather than per-PR, so I did not machine-translate them. Happy to fill them in if you'd prefer.

Add an opt-in, per-project automation that mirrors a parent issue's
completed/cancelled state onto its non-terminal sub-issues, recursively.

- Project.cascade_state_on_close flag (+ migration 0122)
- cascade_state_to_sub_issues Celery task: BFS over the sub-issue tree
  with a visited set and depth cap, bulk_update, one activity per child
  (modeled on the existing close_old_issues automation)
- Hook in IssueViewSet.partial_update: fires only when the parent enters
  a completed/cancelled group and the project has opted in; never on reopen
- Project Automations settings toggle (web) + IProject type + en i18n
- Unit and contract tests

Ref makeplane#9432
@CLAassistant

CLAassistant commented Jul 18, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds an opt-in project automation for cascading completed or cancelled parent issue states to non-terminal descendants. The backend enqueues a bounded traversal task, the frontend exposes the setting, and tests cover gating, traversal, terminal states, timestamps, and cycles.

Changes

Issue close-state cascade

Layer / File(s) Summary
Project setting and automation control
apps/api/plane/db/..., packages/types/src/project/projects.ts, apps/web/core/components/automation/..., apps/web/app/.../automations/page.tsx, packages/i18n/src/locales/*/project-settings.json
Adds the cascade_state_on_close project field, API type, migration, translated settings toggle, page wiring, and automation layout styling.
Terminal transition enqueue
apps/api/plane/app/views/issue/base.py
Detects enabled transitions into completed or cancelled states and enqueues the cascade task.
Bounded descendant cascade
apps/api/plane/bgtasks/issue_cascade_task.py
Traverses descendants, updates non-terminal issues, bulk-persists changes, enforces traversal limits, and records issue activity.
Cascade behavior validation
apps/api/plane/tests/contract/app/test_issue_cascade_app.py, apps/api/plane/tests/unit/bg_tasks/test_issue_cascade_task.py
Tests project opt-in gating, terminal-state mirroring, timestamps, recursive traversal, closed intermediates, project scope, cycle handling, and fan-out limits.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: dheeru0198, sriramveeraghanta

Sequence Diagram(s)

sequenceDiagram
  participant IssueViewSet
  participant cascade_state_to_sub_issues
  participant Issue
  participant issue_activity
  IssueViewSet->>Issue: save parent terminal state
  IssueViewSet->>cascade_state_to_sub_issues: enqueue cascade task
  cascade_state_to_sub_issues->>Issue: traverse descendants and bulk update
  cascade_state_to_sub_issues->>issue_activity: enqueue activity events
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The border styling change in auto-close-automation appears unrelated to the cascade feature and is outside the linked issue scope. Move the visual-only auto-close-automation style tweak to a separate PR or remove it from this change.
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The implementation matches #9432: opt-in per-project parent→child cascading, recursive closure, idempotent skips, and no reverse propagation.
Title check ✅ Passed The title clearly summarizes the main feature: cascading parent issue status to sub-issues on close.
Description check ✅ Passed The description follows the template with sections for description, change type, screenshots, tests, and references, and includes concrete implementation details.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/plane/app/views/issue/base.py`:
- Around line 718-739: Update the terminal-state cascade condition in the issue
state transition logic to trigger whenever the new state group is completed or
cancelled, regardless of previous_group. Preserve the existing state-change
check, project opt-in check, and cascade_state_to_sub_issues.delay invocation so
transitions between terminal groups also cascade.

In `@apps/api/plane/bgtasks/issue_cascade_task.py`:
- Around line 85-104: Replace the broad catch-and-return in the cascade task
containing Issue.objects.bulk_update and issue_activity.delay with a retryable,
resumable workflow. Ensure descendant state updates and their activity records
are committed transactionally or through a durable outbox, and propagate
database or broker failures so Celery retries instead of reporting a partial
cascade as successful.
- Around line 45-85: Update the breadth-first traversal in the task’s main
function around frontier/children handling to enforce a fixed maximum total
descendant count, not just MAX_DEPTH. Process each queryset level in bounded
chunks and stop or schedule continuation work once the cap is reached, while
keeping visited tracking and bulk updates bounded; ensure activity generation
cannot enqueue an unbounded number of descendant updates.
- Around line 37-43: Update the target-state lookup in the issue cascade task
around State.all_state_objects and new_state to restrict the query to the
affected issue’s project and active, non-deleted state records before validating
terminal membership. Preserve the existing early return for missing or
non-terminal states and the completed_at assignment behavior.

In `@packages/i18n/src/locales/en/project-settings.json`:
- Around line 194-197: Add the new "cascade-state.title" and
"cascade-state.description" keys to the corresponding project-settings object in
every locale file, using the English values as placeholders where translations
are unavailable. Preserve the existing locale structure and key names
consistently across all locale files.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 77039738-175e-4011-8bb9-6fccc37ba0f2

📥 Commits

Reviewing files that changed from the base of the PR and between 7cef741 and 3f951b9.

📒 Files selected for processing (12)
  • apps/api/plane/app/views/issue/base.py
  • apps/api/plane/bgtasks/issue_cascade_task.py
  • apps/api/plane/db/migrations/0122_project_cascade_state_on_close.py
  • apps/api/plane/db/models/project.py
  • apps/api/plane/tests/contract/app/test_issue_cascade_app.py
  • apps/api/plane/tests/unit/bg_tasks/test_issue_cascade_task.py
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/automations/page.tsx
  • apps/web/core/components/automation/auto-close-automation.tsx
  • apps/web/core/components/automation/cascade-state-automation.tsx
  • apps/web/core/components/automation/index.ts
  • packages/i18n/src/locales/en/project-settings.json
  • packages/types/src/project/projects.ts

Comment thread apps/api/plane/app/views/issue/base.py
Comment thread apps/api/plane/bgtasks/issue_cascade_task.py
Comment thread apps/api/plane/bgtasks/issue_cascade_task.py
Comment thread apps/api/plane/bgtasks/issue_cascade_task.py
Comment on lines +194 to +197
"cascade-state": {
"title": "Auto-close sub-issues",
"description": "When a parent work item is completed or cancelled, its sub-issues are moved to the same state."
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add these keys to every locale file.

New locale keys must exist in all locales; use the English strings as placeholders where translations are unavailable.

Based on learnings, every new Plane i18n key must be added to every locale immediately, with English placeholders allowed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/i18n/src/locales/en/project-settings.json` around lines 194 - 197,
Add the new "cascade-state.title" and "cascade-state.description" keys to the
corresponding project-settings object in every locale file, using the English
values as placeholders where translations are unavailable. Preserve the existing
locale structure and key names consistently across all locale files.

Source: Learnings

- i18n: add the two cascade-state keys to the remaining 18 locales so the
  sync check passes. Values are the English source as a placeholder; they
  still need real translations (this repo translates every locale).
- Scope the cascade's target state lookup to the project and drop the
  all_state_objects manager, so a soft-deleted or cross-project state can
  no longer drive the cascade.
- Cascade on terminal -> terminal moves too (e.g. completed -> cancelled).
  The previous_group guard suppressed the cascade whenever the parent was
  already closed, stranding still-open descendants. Re-entry is not a
  concern: the task writes via bulk_update and bypasses save().
- Bound total traversal with MAX_DESCENDANTS. MAX_DEPTH only capped the
  tree's height, so a wide tree could fan out one activity task per
  descendant. Hitting the cap logs a warning instead of failing silently.

Adds regression coverage for the terminal -> terminal cascade, the project
scoping of the target state, and the new traversal cap.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🚀 Feature: Auto-cascade status from a parent issue to its sub-issues on close

2 participants