docs_builder: Use type annotations

Change-Id: Ife5ffb6669dba1691dd353dbc80ab14acbb7c4b3
Reviewed-on: https://pigweed-review.googlesource.com/c/infra/recipes/+/180955
Reviewed-by: Ted Pudlik <tpudlik@google.com>
Pigweed-Auto-Submit: Rob Mohr <mohrr@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed-service-accounts.iam.gserviceaccount.com>
diff --git a/recipe_modules/checkout/api.py b/recipe_modules/checkout/api.py
index e19dece..d225445 100644
--- a/recipe_modules/checkout/api.py
+++ b/recipe_modules/checkout/api.py
@@ -347,6 +347,7 @@
 class CheckoutApi(recipe_api.RecipeApi):
     """Calls to checkout code."""
 
+    Change = Change
     CheckoutContext = CheckoutContext
 
     def _read_manifest(self, manifest_remote, manifest_file):
diff --git a/recipes/docs_builder.py b/recipes/docs_builder.py
index 23ac72e..12a5891 100644
--- a/recipes/docs_builder.py
+++ b/recipes/docs_builder.py
@@ -13,9 +13,12 @@
 # the License.
 """Generate docs using GN/Ninja and upload to GCS."""
 
+from typing import Any, Sequence
+
 from PB.go.chromium.org.luci.buildbucket.proto import common
 from PB.recipes.pigweed.docs_builder import InputProperties
 from PB.recipe_engine import result
+from recipe_engine import config_types, recipe_api
 
 DEPS = [
     'fuchsia/buildbucket_util',
@@ -34,19 +37,29 @@
 PROPERTIES = InputProperties
 
 
-def RunSteps(api, props):  # pylint: disable=invalid-name
-    checkout = api.checkout(props.checkout_options)
-    env = api.environment.init(checkout, props.environment_options)
+def RunSteps(
+    api: recipe_api.RecipeScriptApi,
+    props: InputProperties,
+) -> result.RawResult:
+    checkout: api.checkout.CheckoutContext = api.checkout(
+        props.checkout_options
+    )
+    env: api.environment.Environment = api.environment.init(
+        checkout, props.environment_options
+    )
 
+    out_dir: config_types.Path
     if props.HasField('build_options'):
-        build = api.build.create(checkout.root, props.build_options)
+        build: api.build.BuildContext = api.build.create(
+            checkout.root, props.build_options
+        )
         with env():
             api.build(build)
         out_dir = build.root
     elif props.HasField('pw_presubmit_options'):
         with env():
-            presubmit = api.pw_presubmit.init(
-                checkout.root, props.pw_presubmit_options
+            presubmit: api.pw_presubmit.PresubmitContext = (
+                api.pw_presubmit.init(checkout.root, props.pw_presubmit_options)
             )
             assert len(presubmit.steps) == 1
             for step in presubmit.steps:
@@ -55,11 +68,12 @@
     else:
         assert False  # pragma: no cover
 
-    html_path = props.html_path or 'docs/gen/docs/html'
-    html = out_dir.join(*html_path.split('/'))
+    html_path: str = props.html_path or 'docs/gen/docs/html'
+    html: config_types.Path = out_dir.join(*html_path.split('/'))
 
-    applied_changes = checkout.applied_changes()
+    applied_changes: Sequence[api.checkout.Change] = checkout.applied_changes()
 
+    paths: Sequence[str]
     if props.dry_run:
         paths = [
             f'testing/swarming-{api.swarming.task_id}/{checkout.revision()}',
@@ -71,7 +85,7 @@
     else:
         paths = [checkout.revision()]
 
-    bucket = props.bucket or 'pigweed-docs'
+    bucket: str = props.bucket or 'pigweed-docs'
     for path in paths:
         api.gsutil.upload(
             bucket=bucket,
@@ -86,7 +100,7 @@
     if not api.buildbucket_util.is_tryjob:
         # Getting gerrit details even if this is a dry run so testing will show
         # if it would have worked.
-        change = api.gerrit.change_details(
+        change: dict[str, Any] = api.gerrit.change_details(
             'get change details',
             change_id=str(checkout.revision()),
             host=checkout.gerrit_host(),
@@ -96,7 +110,7 @@
         ).json.output
 
         if change['branch'] in ('master', 'main') and not props.dry_run:
-            head = checkout.root.join('HEAD')
+            head: str = checkout.root.join('HEAD')
             api.file.write_text('write HEAD', head, checkout.revision())
             api.gsutil.upload(bucket=bucket, src=head, dst='HEAD')
 
@@ -108,10 +122,10 @@
                 multithreaded=True,
             )
 
-    link_template = props.link_template or 'https://pigweed.dev/?rev={}'
-    links = []
+    link_template: str = props.link_template or 'https://pigweed.dev/?rev={}'
+    links: list[str] = []
     for path in paths:
-        link = link_template.format(path)
+        link: str = link_template.format(path)
 
         if api.buildbucket_util.is_tryjob and '?' not in link:
             if len(applied_changes) == 1:
@@ -123,7 +137,7 @@
 
         links.append(link)
 
-    joined_links = ", ".join(links)
+    joined_links: str = ", ".join(links)
 
     if props.comment and api.buildbucket_util.is_tryjob:
         for change in applied_changes: