More documentation for enqueue-ref

enqueue-ref didn't make it into the client documentation, add it with
some details about what it does, including some discussion of common
operations you might perform.

Change-Id: Ibd7ee306bc461d1597c9c8febcaad89a48b9ff96
diff --git a/doc/source/admin/client.rst b/doc/source/admin/client.rst
index 961b205..8ee6b6f 100644
--- a/doc/source/admin/client.rst
+++ b/doc/source/admin/client.rst
@@ -40,6 +40,62 @@
 
 Note that the format of change id is <number>,<patchset>.
 
+Enqueue-ref
+^^^^^^^^^^^
+
+.. program-output:: zuul enqueue-ref --help
+
+This command is provided to manually simulate a trigger from an
+external source.  It can be useful for testing or replaying a trigger
+that is difficult or impossible to recreate at the source.  The
+arguments to ``enqueue-ref`` will vary depending on the source and
+type of trigger.  Some familiarity with the arguments emitted by
+``gerrit`` `update hooks
+<https://gerrit-review.googlesource.com/admin/projects/plugins/hooks>`__
+such as ``patchset-created`` and ``ref-updated`` is recommended.  Some
+examples of common operations are provided below.
+
+Manual enqueue examples
+***********************
+
+It is common to have a ``release`` pipeline that listens for new tags
+coming from ``gerrit`` and performs a range of code packaging jobs.
+If there is an unexpected issue in the release jobs, the same tag can
+not be recreated in ``gerrit`` and the user must either tag a new
+release or request a manual re-triggering of the jobs.  To re-trigger
+the jobs, pass the failed tag as the ``ref`` argument and set
+``newrev`` to the change associated with the tag in the project
+repository (i.e. what you see from ``git show X.Y.Z``)::
+
+  zuul enqueue-ref --tenant openstack --trigger gerrit --pipeline release --project openstack/example_project --ref refs/tags/X.Y.Z --newrev abc123...
+
+The command can also be used asynchronosly trigger a job in a
+``periodic`` pipeline that would usually be run at a specific time by
+the ``timer`` driver.  For example, the following command would
+trigger the ``periodic`` jobs against the current ``master`` branch
+top-of-tree for a project::
+
+  zuul enqueue-ref --tenant openstack --trigger timer --pipeline periodic --project openstack/example_project --ref refs/heads/master
+
+Another common pipeline is a ``post`` queue listening for ``gerrit``
+merge results.  Triggering here is slightly more complicated as you
+wish to recreate the full ``ref-updated`` event from ``gerrit``.  For
+a new commit on ``master``, the gerrit ``ref-updated`` trigger
+expresses "reset ``refs/heads/master`` for the project from ``oldrev``
+to ``newrev``" (``newrev`` being the committed change).  Thus to
+replay the event, you could ``git log`` in the project and take the
+current ``HEAD`` and the prior change, then enqueue the event::
+
+  NEW_REF=$(git rev-parse HEAD)
+  OLD_REF=$(git rev-parse HEAD~1)
+
+  zuul enqueue-ref --tenant openstack --trigger gerrit --pipeline post --project openstack/example_project --ref refs/heads/master --newrev $NEW_REF --oldrev $OLD_REF
+
+Note that zero values for ``oldrev`` and ``newrev`` can indicate
+branch creation and deletion; the source code is the best reference
+for these more advanced operations.
+
+
 Promote
 ^^^^^^^
 .. program-output:: zuul promote --help
diff --git a/zuul/cmd/client.py b/zuul/cmd/client.py
index c9e399a..a11f2f0 100755
--- a/zuul/cmd/client.py
+++ b/zuul/cmd/client.py
@@ -21,6 +21,7 @@
 import prettytable
 import sys
 import time
+import textwrap
 
 
 import zuul.rpcclient
@@ -78,8 +79,15 @@
                                  required=True)
         cmd_enqueue.set_defaults(func=self.enqueue)
 
-        cmd_enqueue = subparsers.add_parser('enqueue-ref',
-                                            help='enqueue a ref')
+        cmd_enqueue = subparsers.add_parser(
+            'enqueue-ref', help='enqueue a ref',
+            formatter_class=argparse.RawDescriptionHelpFormatter,
+            description=textwrap.dedent('''\
+            Submit a trigger event
+
+            Directly enqueue a trigger event.  This is usually used
+            to manually "replay" a trigger received from an external
+            source such as gerrit.'''))
         cmd_enqueue.add_argument('--tenant', help='tenant name',
                                  required=True)
         cmd_enqueue.add_argument('--trigger', help='trigger name',