pushimage: add cli option for forcing channels

This makes it easier to run pushimage by hand and send to a custom channel.

BUG=chromium:728130
TEST=`./scripts/pushimage_unittest` & precq passes

Change-Id: I7b8015b05b5fcfcf23c4ab570ac9ca921bcc0b29
Reviewed-on: https://chromium-review.googlesource.com/647781
Commit-Ready: Mike Frysinger <vapier@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Mattias Nissler <mnissler@chromium.org>
Reviewed-by: Ningning Xia <nxia@chromium.org>
diff --git a/scripts/pushimage.py b/scripts/pushimage.py
index 1c38e06..fbc0d50 100644
--- a/scripts/pushimage.py
+++ b/scripts/pushimage.py
@@ -280,7 +280,8 @@
 
 
 def PushImage(src_path, board, versionrev=None, profile=None, priority=50,
-              sign_types=None, dry_run=False, mock=False, force_keysets=()):
+              sign_types=None, dry_run=False, mock=False, force_keysets=(),
+              force_channels=None):
   """Push the image from the archive bucket to the release bucket.
 
   Args:
@@ -295,6 +296,7 @@
     dry_run: Show what would be done, but do not upload anything.
     mock: Upload to a testing bucket rather than the real one.
     force_keysets: Set of keysets to use rather than what the inputs say.
+    force_channels: Set of channels to use rather than what the inputs say.
 
   Returns:
     A dictionary that maps 'channel' -> ['gs://signer_instruction_uri1',
@@ -335,7 +337,12 @@
     logging.warning('Missing base instruction file: %s', e)
     logging.warning('not uploading anything for signing')
     return
-  channels = input_insns.GetChannels()
+
+  if force_channels is None:
+    channels = input_insns.GetChannels()
+  else:
+    # Filter out duplicates.
+    channels = sorted(set(force_channels))
 
   # We want force_keysets as a set.
   force_keysets = set(force_keysets)
@@ -576,6 +583,8 @@
                       help='board profile in use (e.g. "asan")')
   parser.add_argument('--version', default=None,
                       help='version info (normally extracted from image_dir)')
+  parser.add_argument('--channels', default=None, action='split_extend',
+                      help='override list of channels to process')
   parser.add_argument('-n', '--dry-run', default=False, action='store_true',
                       help='show what would be done, but do not upload')
   parser.add_argument('-M', '--mock', default=False, action='store_true',
@@ -617,4 +626,4 @@
   PushImage(opts.image_dir, opts.board, versionrev=opts.version,
             profile=opts.profile, priority=opts.priority,
             sign_types=opts.sign_types, dry_run=opts.dry_run, mock=opts.mock,
-            force_keysets=force_keysets)
+            force_keysets=force_keysets, force_channels=opts.channels)