Repository: celery/celery

Issue:
celery worker command option -A is not working with version 5.0.0
Hi, I am running celery worker command as follows:-
pipenv run celery worker -A <celery_instance_file> -l info on windows OS.

I checked the version of celery module installed in python. It says 5.0.0.

#Python interpreter
import celery
celery.__version__
'5.0.0'

So the error is as follows:-
Usage: celery worker [OPTIONS]
Try 'celery worker --help' for help.

Error: no such option: -A

I checked the documentation of celery version 5.0.0, and it still has the option -A.
https://docs.celeryproject.org/en/latest/reference/cli.html

So let me know if this is limitation with windows or if this is a bug.


Discussion:
Hi,

example celery run command 
```bash
celery -A celery_main worker \
    --loglevel INFO \
    --without-gossip \
    --without-mingle \
    -O fair \
    -P eventlet \
    -c 10
```
I get the same error on Ubuntu 20.04.1 with Celery 5.0.0 upgrade.
Problem also occurs when using `--app`

I am passing App as first parameter after the celery binary:
```
ExecStart=/bin/sh -c '${CELERY_BIN} -A ${CELERY_APP} multi start ${CELERYD_NODES} \
  --pidfile=${CELERYD_PID_FILE} \
  --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'
```
Ignore my previous comment here, apparently when I tried that it was erroneously with 4.4.7
I had the same problem in celery beat
```
celery v4.4.7 :
celery beat -A celery_main --loglevel=info

celery v5.0.0 :
celery -A celery_main beat -s celerybeat-schedule.db --loglevel INFO
```

Resolving patch:
diff --git a/celery/bin/base.py b/celery/bin/base.py
--- a/celery/bin/base.py
+++ b/celery/bin/base.py
@@ -39,8 +39,7 @@ def __init__(self, app, no_color, workdir, quiet=False):
 
     @cached_property
     def OK(self):
-        return self.style("OK", fg="green", bold=True)    \
-
+        return self.style("OK", fg="green", bold=True)
 
     @cached_property
     def ERROR(self):
@@ -72,7 +71,7 @@ def error(self, message=None, **kwargs):
             kwargs['color'] = False
             click.echo(message, **kwargs)
         else:
-            click.echo(message, **kwargs)
+            click.secho(message, **kwargs)
 
     def pretty(self, n):
         if isinstance(n, list):
diff --git a/celery/bin/celery.py b/celery/bin/celery.py
--- a/celery/bin/celery.py
+++ b/celery/bin/celery.py
@@ -2,6 +2,7 @@
 import os
 
 import click
+import click.exceptions
 from click.types import ParamType
 from click_didyoumean import DYMGroup
 
@@ -104,7 +105,8 @@ def celery(ctx, app, broker, result_backend, loader, config, workdir,
         os.environ['CELERY_RESULT_BACKEND'] = result_backend
     if config:
         os.environ['CELERY_CONFIG_MODULE'] = config
-    ctx.obj = CLIContext(app=app, no_color=no_color, workdir=workdir, quiet=quiet)
+    ctx.obj = CLIContext(app=app, no_color=no_color, workdir=workdir,
+                         quiet=quiet)
 
     # User options
     worker.params.extend(ctx.obj.app.user_options.get('worker', []))
@@ -139,6 +141,32 @@ def report(ctx):
 celery.add_command(shell)
 celery.add_command(multi)
 
+# Monkey-patch click to display a custom error
+# when -A or --app are used as sub-command options instead of as options
+# of the global command.
+
+previous_show_implementation = click.exceptions.NoSuchOption.show
+
+WRONG_APP_OPTION_USAGE_MESSAGE = """You are using `{option_name}` as an option of the {info_name} sub-command:
+celery {info_name} {option_name} celeryapp <...>
+
+The support for this usage was removed in Celery 5.0. Instead you should use `{option_name}` as a global option:
+celery {option_name} celeryapp {info_name} <...>"""
+
+
+def _show(self, file=None):
+    if self.option_name in ('-A', '--app'):
+        self.ctx.obj.error(
+            WRONG_APP_OPTION_USAGE_MESSAGE.format(
+                option_name=self.option_name,
+                info_name=self.ctx.info_name),
+            fg='red'
+        )
+    previous_show_implementation(self, file=file)
+
+
+click.exceptions.NoSuchOption.show = _show
+
 
 def main() -> int:
     """Start celery umbrella command.


Test patch: