feat: cascade parent issue status to sub-issues on close#9433
feat: cascade parent issue status to sub-issues on close#9433kimnamwook1 wants to merge 2 commits into
Conversation
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
📝 WalkthroughWalkthroughAdds 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. ChangesIssue close-state cascade
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested reviewers: 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
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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
📒 Files selected for processing (12)
apps/api/plane/app/views/issue/base.pyapps/api/plane/bgtasks/issue_cascade_task.pyapps/api/plane/db/migrations/0122_project_cascade_state_on_close.pyapps/api/plane/db/models/project.pyapps/api/plane/tests/contract/app/test_issue_cascade_app.pyapps/api/plane/tests/unit/bg_tasks/test_issue_cascade_task.pyapps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/automations/page.tsxapps/web/core/components/automation/auto-close-automation.tsxapps/web/core/components/automation/cascade-state-automation.tsxapps/web/core/components/automation/index.tspackages/i18n/src/locales/en/project-settings.jsonpackages/types/src/project/projects.ts
| "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." | ||
| }, |
There was a problem hiding this comment.
🎯 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.
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_closeflag (+ migration0122).cascade_state_to_sub_issuesCelery task: BFS over the sub-issue tree with a visited set + depth cap,bulk_update, and oneissue_activityper changed child — modeled on the existingclose_old_issuesautomation.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
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.parenthas no cycle guard.Type of Change
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
plane/tests/unit/bg_tasks/test_issue_cascade_task.py) + a contract test for the view gate; passing locally against thedocker-compose-teststack.References
Closes #9432
Summary by CodeRabbit
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.