cq_label: Reorganize into functions

No logical changes and no changes to expectation files.

Bug: b/231587812
Change-Id: Ib0648bc4041ae528f24d27d14384fa423e8a4ec1
Reviewed-on: https://pigweed-review.googlesource.com/c/infra/recipes/+/93720
Pigweed-Auto-Submit: Rob Mohr <mohrr@google.com>
Reviewed-by: Ted Pudlik <tpudlik@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
diff --git a/recipes/cq_label.py b/recipes/cq_label.py
index 457d7c4..09663a9 100644
--- a/recipes/cq_label.py
+++ b/recipes/cq_label.py
@@ -11,7 +11,11 @@
 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 # License for the specific language governing permissions and limitations under
 # the License.
-"""Set a "Verified" label with the results of CQ."""
+"""Set a "Verified" label with the results of CQ.
+
+Find CLs where CQ has completed and set a label to +1 or -1 based on the status
+of CQ. Also find CLs where CQ is running and clear that +1 or -1.
+"""
 
 import re
 
@@ -33,21 +37,18 @@
 PYTHON_VERSION_COMPATIBILITY = 'PY3'
 
 
-def RunSteps(api, props):
-    assert re.match(r'^[-\w]+$', props.label)
-    assert re.match(r'^[-\w.@]+$', props.cq_account)
-    assert re.match(r'^[-\w./_]*$', props.project)
+def _summary(api, host, change_id, action):
+    return '[{change_id}](https://{host}/{change_id}): {action}'.format(
+        change_id=change_id,
+        host=api.gerrit.normalize_host(host),
+        action=action,
+    )
 
-    def _summary(change_id, action):
-        return '[{change_id}](https://{host}/{change_id}): {action}'.format(
-            change_id=change_id,
-            host=api.gerrit.normalize_host(props.host),
-            action=action,
-        )
 
+def _label_completed_unlabelled(api, host, label, cq_account, project, dry_run):
     project_part = ''
-    if props.project:
-        project_part = 'project:{} '.format(props.project)
+    if project:
+        project_part = 'project:{} '.format(project)
 
     query_string = (
         'is:open '
@@ -55,38 +56,32 @@
         '-(label:{label}-1 OR label:{label}+1) '
         '(r:{cq_account} OR cc:{cq_account}) '
         '{project_part} '
-    ).format(
-        label=props.label,
-        cq_account=props.cq_account,
-        project_part=project_part,
-    )
+    ).format(label=label, cq_account=cq_account, project_part=project_part,)
 
     changes = api.gerrit.change_query(
         name='get unlabeled changes',
         query_string=query_string,
-        host=props.host,
+        host=host,
         max_attempts=5,
         timeout=30,
     ).json.output
 
-    actions = []
-
     for change in changes or ():
         change_id = str(change['_number'])
 
         with api.step.nest(change_id) as pres:
             pres.links[change_id] = 'https://{}/{}'.format(
-                api.gerrit.normalize_host(props.host), change_id,
+                api.gerrit.normalize_host(host), change_id,
             )
 
             details = api.gerrit.change_details(
                 'details',
                 change_id,
                 query_params=['CURRENT_REVISION'],
-                host=props.host,
+                host=host,
             ).json.output
 
-            if props.project and props.project != details['project']:
+            if project and project != details['project']:
                 continue
 
             patch = details['revisions'][details['current_revision']]['_number']
@@ -94,7 +89,7 @@
             # Look at messages in reverse order so we always set based on the
             # most recent CQ results.
             for message in reversed(details['messages']):
-                if message['author']['email'] != props.cq_account:
+                if message['author']['email'] != cq_account:
                     continue
 
                 passed = re.search(
@@ -118,44 +113,46 @@
                         break
 
             if value:
-                if props.dry_run:
-                    action = 'would set {} to {}'.format(props.label, value)
+                if dry_run:
+                    action = 'would set {} to {}'.format(label, value)
                     pres.step_summary_text = action
                     with api.step.nest(action):
                         pass
 
                 else:
-                    action = 'set {} to {}'.format(props.label, value)
+                    action = 'set {} to {}'.format(label, value)
                     pres.step_summary_text = action
                     api.gerrit.set_review(
                         action,
                         change_id,
-                        labels={props.label: value},
-                        host=props.host,
+                        labels={label: value},
+                        host=host,
                         notify='NONE',
                     )
 
-                actions.append(_summary(change_id, action))
+                yield _summary(api, host, change_id, action)
 
             else:
                 pres.step_summary_text = 'no action'
 
+
+def _remove_running_labelled(api, host, label, cq_account, project, dry_run):
+    project_part = ''
+    if project:
+        project_part = 'project:{} '.format(project)
+
     query_string = (
         'is:open '
         '(label:Commit-Queue+1 OR label:Commit-Queue+2) '
         '(label:{label}-1 OR label:{label}+1) '
         '(r:{cq_account} OR cc:{cq_account}) '
         '{project_part} '
-    ).format(
-        label=props.label,
-        cq_account=props.cq_account,
-        project_part=project_part,
-    )
+    ).format(label=label, cq_account=cq_account, project_part=project_part,)
 
     changes = api.gerrit.change_query(
         name='get labeled changes',
         query_string=query_string,
-        host=props.host,
+        host=host,
         max_attempts=5,
         timeout=30,
     ).json.output
@@ -165,27 +162,57 @@
 
         with api.step.nest(change_id) as pres:
             pres.links[change_id] = 'https://{}/{}'.format(
-                api.gerrit.normalize_host(props.host), change_id,
+                api.gerrit.normalize_host(host), change_id,
             )
 
-            if props.dry_run:
-                action = 'would clear {}'.format(props.label)
+            if dry_run:
+                action = 'would clear {}'.format(label)
                 pres.step_summary_text = action
                 with api.step.nest(action):
                     pass
 
             else:
-                action = 'clear {}'.format(props.label)
+                action = 'clear {}'.format(label)
                 pres.step_summary_text = action
                 api.gerrit.set_review(
                     action,
                     change_id,
-                    labels={props.label: 0},
-                    host=props.host,
+                    labels={label: 0},
+                    host=host,
                     notify='NONE',
                 )
 
-            actions.append(_summary(change_id, action))
+            yield _summary(api, host, change_id, action)
+
+
+def RunSteps(api, props):
+    assert re.match(r'^[-\w]+$', props.label)
+    assert re.match(r'^[-\w.@]+$', props.cq_account)
+    assert re.match(r'^[-\w./_]*$', props.project)
+
+    actions = []
+
+    actions.extend(
+        _label_completed_unlabelled(
+            api=api,
+            host=props.host,
+            label=props.label,
+            cq_account=props.cq_account,
+            project=props.project,
+            dry_run=props.dry_run,
+        )
+    )
+
+    actions.extend(
+        _remove_running_labelled(
+            api=api,
+            host=props.host,
+            label=props.label,
+            cq_account=props.cq_account,
+            project=props.project,
+            dry_run=props.dry_run,
+        )
+    )
 
     return result.RawResult(
         summary_markdown='\n\n'.join(actions), status=common.SUCCESS,