[GrandComicsDatabase/gcd-django] Validate persisted revisions before workflow transitions (PR #738)

5 views
Skip to first unread message

jhunterjActual

unread,
Aug 6, 2026, 3:24:41 PM (3 days ago) Aug 6
to GrandComicsDatabase/gcd-django, Subscribed

Summary

  • Validate persisted issue and story revisions before submission and immediately before approval.
  • Reuse the existing forms and formsets as the validation source of truth, including database-object Features values.
  • Keep invalid submissions in the indexer's workflow and block invalid approvals with guidance using the translated Send Back to Indexer action label.
  • Defer non-critical notification email until after the database transaction commits so an unavailable mail service cannot roll back a valid workflow action.

Root cause

Revision data can be changed through migrations or other non-form code paths and then submitted without passing through the normal edit-form validation. Submission and approval previously trusted that persisted data, allowing invalid mixed legacy-text/database-object Features data to reach a workflow transition. During UAT, synchronous notification failures also rolled back otherwise valid transitions.

User impact

Indexers receive linked validation errors and can correct the persisted data before submission. Editors cannot approve invalid data and are directed to use Send Back to Indexer with the required correction. Validation failures do not partially commit changes, and notification outages no longer prevent valid submit, send-back, or approval actions.

Validation

  • Focused tests: 10 passed
  • Flake8 passed for all changed Python files
  • Changed templates compiled successfully
  • Docker-configured manage.py check passed
  • git diff --check passed
  • Manual UAT passed for valid Features submission, invalid persisted data, send-back, correction, and approval

Closes #572


You can view, comment on, or merge this pull request online at:

  https://github.com/GrandComicsDatabase/gcd-django/pull/738

Commit Summary

  • f34e64b Validate persisted revisions before workflow transitions

File Changes

(8 files)

Patch Links:


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.Message ID: <GrandComicsDatabase/gcd-django/pull/738@github.com>

gemini-code-assist[bot]

unread,
Aug 6, 2026, 3:26:57 PM (3 days ago) Aug 6
to GrandComicsDatabase/gcd-django, Subscribed

@gemini-code-assist[bot] commented on this pull request.

Code Review

This pull request introduces a validation mechanism for persisted revisions before changeset workflow transitions, along with synchronized workflow action labels across buttons and instructions. It adds validation logic, corresponding unit tests, and updates views and templates to use the new labels and validate changesets before submission or approval. Feedback on these changes highlights three key areas for improvement: handling potential None values for min_num and max_num in formsets to avoid Django validation errors, adding a defensive guard in _send_notification to prevent AttributeError when user is None, and refactoring the formset validation loop to avoid relying on subtle non-short-circuiting behavior of the and operator.


In apps/oi/submission_validation.py:

> +    data['%s-MIN_NUM_FORMS' % prefix] = str(formset.min_num)
+    data['%s-MAX_NUM_FORMS' % prefix] = str(formset.max_num)

high

In Django, formset.min_num and formset.max_num can be None. If either is None, str(formset.min_num) or str(formset.max_num) will produce the string 'None'. When submitted to Django's ManagementForm, this will cause a validation error because 'None' is not a valid integer. It is safer to use an empty string '' when they are None so that Django's IntegerField cleans them correctly as None.

⬇️ Suggested change
-    data['%s-MIN_NUM_FORMS' % prefix] = str(formset.min_num)
-    data['%s-MAX_NUM_FORMS' % prefix] = str(formset.max_num)
+    data['%s-MIN_NUM_FORMS' % prefix] = '' if formset.min_num is None else str(formset.min_num)
+    data['%s-MAX_NUM_FORMS' % prefix] = '' if formset.max_num is None else str(formset.max_num)

In apps/oi/views.py:

> +def _send_notification(user, subject, body):
+    """Send non-critical email after commit and log delivery failures."""
+    def deliver():
+        try:
+            user.email_user(subject, body, settings.EMAIL_INDEXING)
+        except Exception:
+            # Email delivery must not turn a completed workflow action into a
+            # user-facing error, but operators still need the traceback.
+            logger.exception(
+              'Failed to send OI notification to user %s.', user.pk)
+
+    transaction.on_commit(deliver)

high

In the discuss workflow, if an indexer puts an OPEN changeset into discussion, changeset.approver can be None. This results in _send_notification being called with user=None, which triggers an AttributeError when attempting to call user.email_user(...). Although the exception is caught and logged, we should add a defensive guard to return early if user is None to avoid scheduling a failing on_commit callback and logging unnecessary tracebacks.

⬇️ Suggested change
-def _send_notification(user, subject, body):
-    """Send non-critical email after commit and log delivery failures."""
-    def deliver():
-        try:
-            user.email_user(subject, body, settings.EMAIL_INDEXING)
-        except Exception:
-            # Email delivery must not turn a completed workflow action into a
-            # user-facing error, but operators still need the traceback.
-            logger.exception(
-              'Failed to send OI notification to user %s.', user.pk)
-
-    transaction.on_commit(deliver)
+def _send_notification(user, subject, body):
+    """Send non-critical email after commit and log delivery failures."""
+    if user is None:
+        return
+
+    def deliver():
+        try:
+            user.email_user(subject, body, settings.EMAIL_INDEXING)
+        except Exception:
+            # Email delivery must not turn a completed workflow action into a
+            # user-facing error, but operators still need the traceback.
+            logger.exception(
+              'Failed to send OI notification to user %s.', user.pk)
+
+    transaction.on_commit(deliver)

In apps/oi/submission_validation.py:

> +    valid = form.is_valid()
+    for formset in extra_forms.values():
+        if formset is not None:
+            valid = formset.is_valid() and valid

medium

The loop uses valid = formset.is_valid() and valid to evaluate all formsets. Relying on the left-hand side of and to prevent short-circuiting is subtle and can easily be broken by future refactoring (e.g., if someone changes it to valid = valid and formset.is_valid()). It is safer and more readable to explicitly check the validity of each formset and update the flag.

⬇️ Suggested change
-    valid = form.is_valid()
-    for formset in extra_forms.values():
-        if formset is not None:
-            valid = formset.is_valid() and valid
+    valid = form.is_valid()
+    for formset in extra_forms.values():
+        if formset is not None:
+            if not formset.is_valid():
+                valid = False


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4877701767@github.com>

jhunterjActual

unread,
Aug 6, 2026, 3:35:34 PM (3 days ago) Aug 6
to GrandComicsDatabase/gcd-django, Push

@jhunterjActual pushed 1 commit.

  • c7fa6fd Update apps/oi/submission_validation.py


View it on GitHub or unsubscribe.


Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <GrandComicsDatabase/gcd-django/pull/738/before/f34e64be5fed1cd8d9255044511892666a143b7e/after/c7fa6fd4b2383370b5cc6fb44eb088eba498c272@github.com>

jhunterjActual

unread,
Aug 6, 2026, 3:41:46 PM (3 days ago) Aug 6
to GrandComicsDatabase/gcd-django, Subscribed

@jhunterjActual commented on this pull request.


In apps/oi/submission_validation.py:

> +    data['%s-MIN_NUM_FORMS' % prefix] = str(formset.min_num)
+    data['%s-MAX_NUM_FORMS' % prefix] = str(formset.max_num)

Django 5.2’s formset_factory() converts None to numeric defaults before constructing the formset class. All formsets used by this validation path come from Django’s formset factories, so _add_formset_data(data, formset): (on submission_validation.py line 58) receives integers.

Additionally, the suggested replacement creates two lines that would fail the project’s Flake8 line-length check.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4877777296@github.com>

jhunterjActual

unread,
Aug 6, 2026, 3:51:32 PM (3 days ago) Aug 6
to GrandComicsDatabase/gcd-django, Subscribed

@jhunterjActual commented on this pull request.


In apps/oi/views.py:

> +def _send_notification(user, subject, body):
+    """Send non-critical email after commit and log delivery failures."""
+    def deliver():
+        try:
+            user.email_user(subject, body, settings.EMAIL_INDEXING)
+        except Exception:
+            # Email delivery must not turn a completed workflow action into a
+            # user-facing error, but operators still need the traceback.
+            logger.exception(
+              'Failed to send OI notification to user %s.', user.pk)
+
+    transaction.on_commit(deliver)

The described path is unreachable. discuss(self, commenter, notes='') (from apps/oi/models.py line 823) explicitly rejects any changeset without an approver before _send_notification(changeset.approver, subject, email_body) (from apps/oi/views.py line 1253) is reached.

Silently accepting None in _send_notification() would also conceal future caller errors instead of preserving the existing invariant that a recipient is required.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4877826701@github.com>

jhunterjActual

unread,
Aug 6, 2026, 3:55:52 PM (3 days ago) Aug 6
to GrandComicsDatabase/gcd-django, Subscribed
jhunterjActual left a comment (GrandComicsDatabase/gcd-django#738)

Note that 2 of Gemini Code Assist's 3 feedback items were not implemented. Details in those comments.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <GrandComicsDatabase/gcd-django/pull/738/c5208722959@github.com>

JochenGCD

unread,
Aug 6, 2026, 9:02:05 PM (3 days ago) Aug 6
to GrandComicsDatabase/gcd-django, Subscribed

@jochengcd commented on this pull request.


In apps/oi/views.py:

> @@ -221,6 +229,20 @@
 ##############################################################################
 
 
+def _send_notification(user, subject, body):
+    """Send non-critical email after commit and log delivery failures."""
+    def deliver():
+        try:
+            user.email_user(subject, body, settings.EMAIL_INDEXING)
+        except Exception:
+            # Email delivery must not turn a completed workflow action into a
+            # user-facing error, but operators still need the traceback.
+            logger.exception(

What does this logging do ?

Generally this addresses a non-issue. Further, at least when a change is rejected, the indexer needs to get an email about it, which now might fail silently. Same for some other emails. Why the change ?


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4879107983@github.com>

jhunterjActual

unread,
Aug 7, 2026, 7:59:44 AM (3 days ago) Aug 7
to GrandComicsDatabase/gcd-django, gcd-github, Comment
jhunterjActual left a comment (GrandComicsDatabase/gcd-django#738)

I probably do not understand this, but would "...explicitly rejects any changeset without an approver..." result in a failure if someone commented on a changeset directly from the Pending list, that does not yet have an approver assigned?  We often have folks, some not editors, who make such comments. - Don Milne

Ordinary Add Comment activity isn't affected. It uses a separate path that leaves the changeset in its existing state and does not require an approver. On an unassigned pending changeset, it records the comment, notifies the indexer and prior commenters, and skips the approver notification because none exists.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/c5216785971@github.com>

jhunterjActual

unread,
Aug 7, 2026, 8:08:17 AM (3 days ago) Aug 7
to GrandComicsDatabase/gcd-django, gcd-github, Comment

@jhunterjActual commented on this pull request.


In apps/oi/views.py:

> @@ -221,6 +229,20 @@
 ##############################################################################
 
 
+def _send_notification(user, subject, body):
+    """Send non-critical email after commit and log delivery failures."""
+    def deliver():
+        try:
+            user.email_user(subject, body, settings.EMAIL_INDEXING)
+        except Exception:
+            # Email delivery must not turn a completed workflow action into a
+            # user-facing error, but operators still need the traceback.
+            logger.exception(

The change came from my UAT, where SMTP connection failures (I don't have an SMTP server running) caused valid workflow actions to return errors and, with ATOMIC_REQUESTS, risked rolling back the state transition. Not quite a non-issue, but not one that comes up in the happy path.

Yes, on the happy path, emails should get sent to indexers when the state of their changeset changes. But if an email cannot be sent, IMO the workflow should be able to continue anyway, and the changesets could be processed by people logging in. You are right that this changes required notifications into best-effort notifications.

This might be the wrong scope for it; I just included it here because it's where I had the problem. I could remove the email refactor from this PR if we want to address mail failure separately with an explicit delivery policy, retry/outbox mechanism, and monitoring (or just assume happy path).


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4882685047@github.com>

JochenGCD

unread,
Aug 7, 2026, 5:02:23 PM (2 days ago) Aug 7
to GrandComicsDatabase/gcd-django, gcd-github, Comment

@jochengcd commented on this pull request.


In apps/oi/views.py:

> @@ -221,6 +229,20 @@
 ##############################################################################
 
 
+def _send_notification(user, subject, body):
+    """Send non-critical email after commit and log delivery failures."""
+    def deliver():
+        try:
+            user.email_user(subject, body, settings.EMAIL_INDEXING)
+        except Exception:
+            # Email delivery must not turn a completed workflow action into a
+            # user-facing error, but operators still need the traceback.
+            logger.exception(

For dev-purposes please use one of the dev-backends provided by django, e.g.
https://docs.djangoproject.com/en/5.2/topics/email/#console-backend
we could add that to settings_local.py of the docker setup

I don't see why we should catch mail-sending errors. If mails cannot be send, there would be severe issues with the server, which needs actions. Silencing these errors would further delay that.

Please remove this part of the pull request.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4886529984@github.com>

JochenGCD

unread,
Aug 7, 2026, 5:22:51 PM (2 days ago) Aug 7
to GrandComicsDatabase/gcd-django, gcd-github, Comment

@jochengcd commented on this pull request.


On apps/oi/submission_validation.py:

We so far do not split out oi-functionality into different files then what we have. It is not ideal and needs reconsideration, but that would be a separate effort. Goes also for action_labels.py. Please integrate into views.py.


In apps/oi/submission_validation.py:

> +    valid = form.is_valid()
+    for formset in extra_forms.values():
+        if formset is not None:
+            if not formset.is_valid():
+                valid = False
+
+    if valid:
+        return []
+    return _validation_messages(form, extra_forms)
+
+
+def validate_changeset_revisions(changeset, request):
+    """Return invalid active issue/story revisions and their errors."""
+    invalid = []
+    revisions = list(changeset.issuerevisions.filter(deleted=False))
+    revisions.extend(changeset.storyrevisions.filter(deleted=False))

Thanks for tackling this.
While this is valid and wanted for revisions edited in a changeset, I don't think we want to force indexers to work on sequences they did not touch, i.e. existing data that would not validate.

We can use the changed status of a revision, if compare_changes was already run, not quite sure if it is when this is called.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4886563661@github.com>

jhunterjActual

unread,
Aug 7, 2026, 8:59:24 PM (2 days ago) Aug 7
to GrandComicsDatabase/gcd-django, gcd-github, Comment

@jhunterjActual commented on this pull request.


In apps/oi/submission_validation.py:

> +    valid = form.is_valid()
+    for formset in extra_forms.values():
+        if formset is not None:
+            if not formset.is_valid():
+                valid = False
+
+    if valid:
+        return []
+    return _validation_messages(form, extra_forms)
+
+
+def validate_changeset_revisions(changeset, request):
+    """Return invalid active issue/story revisions and their errors."""
+    invalid = []
+    revisions = list(changeset.issuerevisions.filter(deleted=False))
+    revisions.extend(changeset.storyrevisions.filter(deleted=False))

We currently make indexers work on sections they did not touch. I make edits to, say, sequence titles or first lines she have to fix problems with the character list and groups.

Or if you make an edit for groups with characters who aren't members, your have to deal with earlier shortcuts.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4887644008@github.com>

JochenGCD

unread,
Aug 8, 2026, 3:31:04 AM (2 days ago) Aug 8
to GrandComicsDatabase/gcd-django, gcd-github, Comment

@jochengcd commented on this pull request.


In apps/oi/submission_validation.py:

> +    valid = form.is_valid()
+    for formset in extra_forms.values():
+        if formset is not None:
+            if not formset.is_valid():
+                valid = False
+
+    if valid:
+        return []
+    return _validation_messages(form, extra_forms)
+
+
+def validate_changeset_revisions(changeset, request):
+    """Return invalid active issue/story revisions and their errors."""
+    invalid = []
+    revisions = list(changeset.issuerevisions.filter(deleted=False))
+    revisions.extend(changeset.storyrevisions.filter(deleted=False))

On sections, yes, but not sequences.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4888404545@github.com>

jhunterjActual

unread,
Aug 8, 2026, 8:20:55 AM (2 days ago) Aug 8
to GrandComicsDatabase/gcd-django, gcd-github, Comment

@jhunterjActual commented on this pull request.


In apps/oi/submission_validation.py:

> +    valid = form.is_valid()
+    for formset in extra_forms.values():
+        if formset is not None:
+            if not formset.is_valid():
+                valid = False
+
+    if valid:
+        return []
+    return _validation_messages(form, extra_forms)
+
+
+def validate_changeset_revisions(changeset, request):
+    """Return invalid active issue/story revisions and their errors."""
+    invalid = []
+    revisions = list(changeset.issuerevisions.filter(deleted=False))
+    revisions.extend(changeset.storyrevisions.filter(deleted=False))

Understood. Will refactor.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4888789378@github.com>

jhunterjActual

unread,
Aug 8, 2026, 8:23:50 AM (2 days ago) Aug 8
to GrandComicsDatabase/gcd-django, gcd-github, Comment

@jhunterjActual commented on this pull request.


On apps/oi/submission_validation.py:

Possibly a newbie question, but: What's the issue in adding files for this? Does it impact something elsewhere?

It's easy enough to refactor, just unexpected.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4888793538@github.com>

JochenGCD

unread,
Aug 8, 2026, 9:14:04 AM (2 days ago) Aug 8
to GrandComicsDatabase/gcd-django, gcd-github, Comment

@jochengcd commented on this pull request.


On apps/oi/submission_validation.py:

views.py/models.py is django recommendation for organising code. If, we would have dirs views/models with further files. It is about where to expect the code.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4888864949@github.com>

jhunterjActual

unread,
Aug 8, 2026, 10:42:54 AM (2 days ago) Aug 8
to GrandComicsDatabase/gcd-django, gcd-github, Push

@jhunterjActual pushed 1 commit.

  • c9ec8d0 Remove best-effort workflow email handling


View it on GitHub or unsubscribe.


Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <GrandComicsDatabase/gcd-django/pull/738/before/c7fa6fd4b2383370b5cc6fb44eb088eba498c272/after/c9ec8d0917afef24b229ad0f4c01912985215ba1@github.com>

jhunterjActual

unread,
Aug 8, 2026, 10:56:18 AM (2 days ago) Aug 8
to GrandComicsDatabase/gcd-django, gcd-github, Comment

@jhunterjActual commented on this pull request.


In apps/oi/views.py:

> @@ -221,6 +229,20 @@
 ##############################################################################
 
 
+def _send_notification(user, subject, body):
+    """Send non-critical email after commit and log delivery failures."""
+    def deliver():
+        try:
+            user.email_user(subject, body, settings.EMAIL_INDEXING)
+        except Exception:
+            # Email delivery must not turn a completed workflow action into a
+            # user-facing error, but operators still need the traceback.
+            logger.exception(

Commit c9ec8d0 removes this part.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4889027468@github.com>

jhunterjActual

unread,
Aug 8, 2026, 11:36:43 AM (2 days ago) Aug 8
to GrandComicsDatabase/gcd-django, gcd-github, Comment

@jhunterjActual commented on this pull request.


In apps/oi/views.py:

> @@ -221,6 +229,20 @@
 ##############################################################################
 
 
+def _send_notification(user, subject, body):
+    """Send non-critical email after commit and log delivery failures."""
+    def deliver():
+        try:
+            user.email_user(subject, body, settings.EMAIL_INDEXING)
+        except Exception:
+            # Email delivery must not turn a completed workflow action into a
+            # user-facing error, but operators still need the traceback.
+            logger.exception(

And I've updated the PR description to remove references to email handling changes.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4889089957@github.com>

jhunterjActual

unread,
Aug 8, 2026, 12:47:16 PM (2 days ago) Aug 8
to GrandComicsDatabase/gcd-django, gcd-github, Push

@jhunterjActual pushed 1 commit.

  • 16bf32b Consolidate OI workflow helpers in views


View it on GitHub or unsubscribe.


Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <GrandComicsDatabase/gcd-django/pull/738/before/c9ec8d0917afef24b229ad0f4c01912985215ba1/after/16bf32b7b2d0013556a7f39bc71efa2cb8a48e77@github.com>

jhunterjActual

unread,
Aug 8, 2026, 12:52:21 PM (2 days ago) Aug 8
to GrandComicsDatabase/gcd-django, gcd-github, Comment

@jhunterjActual commented on this pull request.


On apps/oi/submission_validation.py:

Commit 16bf32b has the refactoring


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4889225378@github.com>

jhunterjActual

unread,
Aug 8, 2026, 6:44:35 PM (2 days ago) Aug 8
to GrandComicsDatabase/gcd-django, gcd-github, Push

@jhunterjActual pushed 1 commit.

  • cabb14d Skip unchanged revisions during transition validation


View it on GitHub or unsubscribe.


Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <GrandComicsDatabase/gcd-django/pull/738/before/16bf32b7b2d0013556a7f39bc71efa2cb8a48e77/after/cabb14d7275622fee04e16760613668ae865645f@github.com>

jhunterjActual

unread,
Aug 8, 2026, 6:45:15 PM (2 days ago) Aug 8
to GrandComicsDatabase/gcd-django, gcd-github, Comment

@jhunterjActual commented on this pull request.


In apps/oi/submission_validation.py:

> +    valid = form.is_valid()
+    for formset in extra_forms.values():
+        if formset is not None:
+            if not formset.is_valid():
+                valid = False
+
+    if valid:
+        return []
+    return _validation_messages(form, extra_forms)
+
+
+def validate_changeset_revisions(changeset, request):
+    """Return invalid active issue/story revisions and their errors."""
+    invalid = []
+    revisions = list(changeset.issuerevisions.filter(deleted=False))
+    revisions.extend(changeset.storyrevisions.filter(deleted=False))

Refactored in cabb14d


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you commented.Message ID: <GrandComicsDatabase/gcd-django/pull/738/review/4889981904@github.com>

Reply all
Reply to author
Forward
0 new messages