We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Wagtail 2.15 Bulk Publish for Inherited Page
Found a bug? Please fill out the sections below. 👍

### Issue Summary
Assume we have two classes:
class A(Page):
  name = models.CharField(max_length=255)

class B(A):
  nickname = models.CharField(max_length=255)

When do bulk action of publishing the pages with B, an error will occur:
![image](https://user-images.githubusercontent.com/81170508/140770606-161a016f-52c2-4bda-b45d-0cd78ba99310.png)

The existing solution I think is to customize bulk action according to https://docs.wagtail.io/en/stable/extending/custom_bulk_actions.html#custom-bulk-actions
But I would like to know if there is other solution?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `wagtail/admin/views/pages/bulk_actions/publish.py`
Content:
```
1 from django.utils.translation import gettext_lazy as _
2 from django.utils.translation import ngettext
3 
4 from wagtail.admin.views.pages.bulk_actions.page_bulk_action import PageBulkAction
5 
6 
7 class PublishBulkAction(PageBulkAction):
8     display_name = _("Publish")
9     action_type = "publish"
10     aria_label = _("Publish selected pages")
11     template_name = "wagtailadmin/pages/bulk_actions/confirm_bulk_publish.html"
12     action_priority = 40
13 
14     def check_perm(self, page):
15         return page.permissions_for_user(self.request.user).can_publish()
16 
17     def object_context(self, obj):
18         context = super().object_context(obj)
19         context['draft_descendant_count'] = context['item'].get_descendants().not_live().count()
20         return context
21 
22     def get_context_data(self, **kwargs):
23         context = super().get_context_data(**kwargs)
24         context['has_draft_descendants'] = any(map(lambda x: x['draft_descendant_count'], context['items']))
25         return context
26 
27     def get_execution_context(self):
28         return {
29             **super().get_execution_context(),
30             'include_descendants': self.cleaned_form.cleaned_data['include_descendants'],
31         }
32 
33     @classmethod
34     def execute_action(cls, objects, include_descendants=False, user=None, **kwargs):
35         num_parent_objects, num_child_objects = 0, 0
36         for page in objects:
37             revision = page.save_revision(user=user)
38             revision.publish(user=user)
39             num_parent_objects += 1
40 
41             if include_descendants:
42                 for draft_descendant_page in page.get_descendants().not_live().defer_streamfields().specific():
43                     if user is None or draft_descendant_page.permissions_for_user(user).can_publish():
44                         revision = draft_descendant_page.save_revision(user=user)
45                         revision.publish(user=user)
46                         num_child_objects += 1
47         return num_parent_objects, num_child_objects
48 
49     def get_success_message(self, num_parent_objects, num_child_objects):
50         include_descendants = self.cleaned_form.cleaned_data['include_descendants']
51         if num_parent_objects == 1:
52             if include_descendants:
53                 if num_child_objects == 0:
54                     success_message = _("1 page has been published")
55                 else:
56                     success_message = ngettext(
57                         "1 page and %(num_child_objects)d child page have been published",
58                         "1 page and %(num_child_objects)d child pages have been published",
59                         num_child_objects
60                     ) % {
61                         'num_child_objects': num_child_objects
62                     }
63             else:
64                 success_message = _("1 page has been published")
65         else:
66             if include_descendants:
67                 if num_child_objects == 0:
68                     success_message = _("%(num_parent_objects)d pages have been published") % {'num_parent_objects': num_parent_objects}
69                 else:
70                     success_message = ngettext(
71                         "%(num_parent_objects)d pages and %(num_child_objects)d child page have been published",
72                         "%(num_parent_objects)d pages and %(num_child_objects)d child pages have been published",
73                         num_child_objects
74                     ) % {
75                         'num_child_objects': num_child_objects,
76                         'num_parent_objects': num_parent_objects
77                     }
78             else:
79                 success_message = _("%(num_parent_objects)d pages have been published") % {'num_parent_objects': num_parent_objects}
80         return success_message
81
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/wagtail/admin/views/pages/bulk_actions/publish.py b/wagtail/admin/views/pages/bulk_actions/publish.py
--- a/wagtail/admin/views/pages/bulk_actions/publish.py
+++ b/wagtail/admin/views/pages/bulk_actions/publish.py
@@ -34,6 +34,7 @@
     def execute_action(cls, objects, include_descendants=False, user=None, **kwargs):
         num_parent_objects, num_child_objects = 0, 0
         for page in objects:
+            page = page.specific
             revision = page.save_revision(user=user)
             revision.publish(user=user)
             num_parent_objects += 1

{"golden_diff": "diff --git a/wagtail/admin/views/pages/bulk_actions/publish.py b/wagtail/admin/views/pages/bulk_actions/publish.py\n--- a/wagtail/admin/views/pages/bulk_actions/publish.py\n+++ b/wagtail/admin/views/pages/bulk_actions/publish.py\n@@ -34,6 +34,7 @@\n     def execute_action(cls, objects, include_descendants=False, user=None, **kwargs):\n         num_parent_objects, num_child_objects = 0, 0\n         for page in objects:\n+            page = page.specific\n             revision = page.save_revision(user=user)\n             revision.publish(user=user)\n             num_parent_objects += 1\n", "issue": "Wagtail 2.15 Bulk Publish for Inherited Page\nFound a bug? Please fill out the sections below. \ud83d\udc4d\r\n\r\n### Issue Summary\r\nAssume we have two classes:\r\nclass A(Page):\r\n  name = models.CharField(max_length=255)\r\n\r\nclass B(A):\r\n  nickname = models.CharField(max_length=255)\r\n\r\nWhen do bulk action of publishing the pages with B, an error will occur:\r\n![image](https://user-images.githubusercontent.com/81170508/140770606-161a016f-52c2-4bda-b45d-0cd78ba99310.png)\r\n\r\nThe existing solution I think is to customize bulk action according to https://docs.wagtail.io/en/stable/extending/custom_bulk_actions.html#custom-bulk-actions\r\nBut I would like to know if there is other solution?\n", "before_files": [{"content": "from django.utils.translation import gettext_lazy as _\nfrom django.utils.translation import ngettext\n\nfrom wagtail.admin.views.pages.bulk_actions.page_bulk_action import PageBulkAction\n\n\nclass PublishBulkAction(PageBulkAction):\n    display_name = _(\"Publish\")\n    action_type = \"publish\"\n    aria_label = _(\"Publish selected pages\")\n    template_name = \"wagtailadmin/pages/bulk_actions/confirm_bulk_publish.html\"\n    action_priority = 40\n\n    def check_perm(self, page):\n        return page.permissions_for_user(self.request.user).can_publish()\n\n    def object_context(self, obj):\n        context = super().object_context(obj)\n        context['draft_descendant_count'] = context['item'].get_descendants().not_live().count()\n        return context\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['has_draft_descendants'] = any(map(lambda x: x['draft_descendant_count'], context['items']))\n        return context\n\n    def get_execution_context(self):\n        return {\n            **super().get_execution_context(),\n            'include_descendants': self.cleaned_form.cleaned_data['include_descendants'],\n        }\n\n    @classmethod\n    def execute_action(cls, objects, include_descendants=False, user=None, **kwargs):\n        num_parent_objects, num_child_objects = 0, 0\n        for page in objects:\n            revision = page.save_revision(user=user)\n            revision.publish(user=user)\n            num_parent_objects += 1\n\n            if include_descendants:\n                for draft_descendant_page in page.get_descendants().not_live().defer_streamfields().specific():\n                    if user is None or draft_descendant_page.permissions_for_user(user).can_publish():\n                        revision = draft_descendant_page.save_revision(user=user)\n                        revision.publish(user=user)\n                        num_child_objects += 1\n        return num_parent_objects, num_child_objects\n\n    def get_success_message(self, num_parent_objects, num_child_objects):\n        include_descendants = self.cleaned_form.cleaned_data['include_descendants']\n        if num_parent_objects == 1:\n            if include_descendants:\n                if num_child_objects == 0:\n                    success_message = _(\"1 page has been published\")\n                else:\n                    success_message = ngettext(\n                        \"1 page and %(num_child_objects)d child page have been published\",\n                        \"1 page and %(num_child_objects)d child pages have been published\",\n                        num_child_objects\n                    ) % {\n                        'num_child_objects': num_child_objects\n                    }\n            else:\n                success_message = _(\"1 page has been published\")\n        else:\n            if include_descendants:\n                if num_child_objects == 0:\n                    success_message = _(\"%(num_parent_objects)d pages have been published\") % {'num_parent_objects': num_parent_objects}\n                else:\n                    success_message = ngettext(\n                        \"%(num_parent_objects)d pages and %(num_child_objects)d child page have been published\",\n                        \"%(num_parent_objects)d pages and %(num_child_objects)d child pages have been published\",\n                        num_child_objects\n                    ) % {\n                        'num_child_objects': num_child_objects,\n                        'num_parent_objects': num_parent_objects\n                    }\n            else:\n                success_message = _(\"%(num_parent_objects)d pages have been published\") % {'num_parent_objects': num_parent_objects}\n        return success_message\n", "path": "wagtail/admin/views/pages/bulk_actions/publish.py"}], "after_files": [{"content": "from django.utils.translation import gettext_lazy as _\nfrom django.utils.translation import ngettext\n\nfrom wagtail.admin.views.pages.bulk_actions.page_bulk_action import PageBulkAction\n\n\nclass PublishBulkAction(PageBulkAction):\n    display_name = _(\"Publish\")\n    action_type = \"publish\"\n    aria_label = _(\"Publish selected pages\")\n    template_name = \"wagtailadmin/pages/bulk_actions/confirm_bulk_publish.html\"\n    action_priority = 40\n\n    def check_perm(self, page):\n        return page.permissions_for_user(self.request.user).can_publish()\n\n    def object_context(self, obj):\n        context = super().object_context(obj)\n        context['draft_descendant_count'] = context['item'].get_descendants().not_live().count()\n        return context\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['has_draft_descendants'] = any(map(lambda x: x['draft_descendant_count'], context['items']))\n        return context\n\n    def get_execution_context(self):\n        return {\n            **super().get_execution_context(),\n            'include_descendants': self.cleaned_form.cleaned_data['include_descendants'],\n        }\n\n    @classmethod\n    def execute_action(cls, objects, include_descendants=False, user=None, **kwargs):\n        num_parent_objects, num_child_objects = 0, 0\n        for page in objects:\n            page = page.specific\n            revision = page.save_revision(user=user)\n            revision.publish(user=user)\n            num_parent_objects += 1\n\n            if include_descendants:\n                for draft_descendant_page in page.get_descendants().not_live().defer_streamfields().specific():\n                    if user is None or draft_descendant_page.permissions_for_user(user).can_publish():\n                        revision = draft_descendant_page.save_revision(user=user)\n                        revision.publish(user=user)\n                        num_child_objects += 1\n        return num_parent_objects, num_child_objects\n\n    def get_success_message(self, num_parent_objects, num_child_objects):\n        include_descendants = self.cleaned_form.cleaned_data['include_descendants']\n        if num_parent_objects == 1:\n            if include_descendants:\n                if num_child_objects == 0:\n                    success_message = _(\"1 page has been published\")\n                else:\n                    success_message = ngettext(\n                        \"1 page and %(num_child_objects)d child page have been published\",\n                        \"1 page and %(num_child_objects)d child pages have been published\",\n                        num_child_objects\n                    ) % {\n                        'num_child_objects': num_child_objects\n                    }\n            else:\n                success_message = _(\"1 page has been published\")\n        else:\n            if include_descendants:\n                if num_child_objects == 0:\n                    success_message = _(\"%(num_parent_objects)d pages have been published\") % {'num_parent_objects': num_parent_objects}\n                else:\n                    success_message = ngettext(\n                        \"%(num_parent_objects)d pages and %(num_child_objects)d child page have been published\",\n                        \"%(num_parent_objects)d pages and %(num_child_objects)d child pages have been published\",\n                        num_child_objects\n                    ) % {\n                        'num_child_objects': num_child_objects,\n                        'num_parent_objects': num_parent_objects\n                    }\n            else:\n                success_message = _(\"%(num_parent_objects)d pages have been published\") % {'num_parent_objects': num_parent_objects}\n        return success_message\n", "path": "wagtail/admin/views/pages/bulk_actions/publish.py"}]}