_frontend: Fix shell completion with Click >= 8.2
diff --git a/src/buildstream/_frontend/cli.py b/src/buildstream/_frontend/cli.py
index 9d7619b..4f916df 100644
--- a/src/buildstream/_frontend/cli.py
+++ b/src/buildstream/_frontend/cli.py
@@ -15,6 +15,7 @@
 import re
 import sys
 from functools import partial
+from typing import TYPE_CHECKING
 
 import shutil
 import click
@@ -25,6 +26,15 @@
 from .._remotespec import RemoteSpec, RemoteSpecPurpose
 from ..utils import UtilError
 
+if TYPE_CHECKING or click.Command.__bases__ == (object,):
+    # Click >= 8.2
+    ClickCommandBaseClass = click.Command
+    ClickGroupBaseClass = click.Group
+else:
+    # Click < 8.2
+    ClickCommandBaseClass = click.BaseCommand
+    ClickGroupBaseClass = click.MultiCommand
+
 
 ##################################################################
 #              Helper classes and methods for Click              #
@@ -105,7 +115,7 @@
 # Completion for completing command names as help arguments
 def complete_commands(cmd, args, incomplete):
     command_ctx = search_command(args[1:])
-    if command_ctx and command_ctx.command and isinstance(command_ctx.command, click.MultiCommand):
+    if command_ctx and command_ctx.command and isinstance(command_ctx.command, ClickGroupBaseClass):
         return [
             subcommand + " "
             for subcommand in command_ctx.command.list_commands(command_ctx)
@@ -272,10 +282,10 @@
     original_main(self, args=args, prog_name=prog_name, complete_var=None, standalone_mode=standalone_mode, **extra)
 
 
-original_main = click.BaseCommand.main
+original_main = ClickCommandBaseClass.main
 # Disable type checking since mypy doesn't support assigning to a method.
 # See https://github.com/python/mypy/issues/2427.
-click.BaseCommand.main = override_main  # type: ignore
+ClickCommandBaseClass.main = override_main  # type: ignore
 
 
 ##################################################################
@@ -392,7 +402,7 @@
     click.echo(command_ctx.command.get_help(command_ctx), err=True)
 
     # Hint about available sub commands
-    if isinstance(command_ctx.command, click.MultiCommand):
+    if isinstance(command_ctx.command, ClickGroupBaseClass):
         detail = " "
         if command:
             detail = " {} ".format(" ".join(command))
diff --git a/src/buildstream/_frontend/complete.py b/src/buildstream/_frontend/complete.py
index 6fef9d2..787db6d 100644
--- a/src/buildstream/_frontend/complete.py
+++ b/src/buildstream/_frontend/complete.py
@@ -32,11 +32,19 @@
 import collections.abc
 import copy
 import os
+from typing import TYPE_CHECKING
 
 import click
-from click.core import MultiCommand, Option, Argument
+from click.core import Option, Argument
 from click.parser import split_arg_string
 
+if TYPE_CHECKING or click.Command.__bases__ == (object,):
+    # Click >= 8.2
+    ClickGroupBaseClass = click.Group
+else:
+    # Click < 8.2
+    ClickGroupBaseClass = click.MultiCommand
+
 WORDBREAK = "="
 
 COMPLETION_SCRIPT = """
@@ -176,7 +184,7 @@
     ctx = cli.make_context(prog_name, args, resilient_parsing=True)
     args_remaining = ctx.protected_args + ctx.args
     while ctx is not None and args_remaining:
-        if isinstance(ctx.command, MultiCommand):
+        if isinstance(ctx.command, ClickGroupBaseClass):
             cmd = ctx.command.get_command(ctx, args_remaining[0])
             if cmd is None:
                 return None
@@ -310,7 +318,7 @@
                 found_param = True
                 break
 
-    if not found_param and isinstance(ctx.command, MultiCommand):
+    if not found_param and isinstance(ctx.command, ClickGroupBaseClass):
         # completion for any subcommands
         choices.extend(
             [cmd + " " for cmd in ctx.command.list_commands(ctx) if not ctx.command.get_command(ctx, cmd).hidden]
@@ -319,7 +327,7 @@
     if (
         not start_of_option(incomplete)
         and ctx.parent is not None
-        and isinstance(ctx.parent.command, MultiCommand)
+        and isinstance(ctx.parent.command, ClickGroupBaseClass)
         and ctx.parent.command.chain
     ):
         # completion for chained commands