Bug 1426244 - 4. Add mach android geckoview-docs command; r=nalexander draft
authorJim Chen <nchen@mozilla.com>
Sat, 13 Jan 2018 17:41:09 -0500
changeset 720173 fcfe0d45b08968ff3371e44e2a3e545ca8a8954f
parent 720172 a51155ff6412a144cafa245f77eef707f69b508d
child 720174 f1cdef3839748dc09eb42028d3d3a0df972aab56
push id95466
push userbmo:nchen@mozilla.com
push dateMon, 15 Jan 2018 00:55:47 +0000
reviewersnalexander
bugs1426244
milestone59.0a1
Bug 1426244 - 4. Add mach android geckoview-docs command; r=nalexander Add a './mach android geckoview-docs' command that generates javadoc for GeckoView using Gradle. Specifying the '--archive' option will generate a geckoview-javadoc.jar archive. Specifying the '--upload' option, intended primarily for Taskcluster, will upload the javadoc to Github pages under the given user/repository. MozReview-Commit-ID: HfwXlf8aFhw
mobile/android/mach_commands.py
--- a/mobile/android/mach_commands.py
+++ b/mobile/android/mach_commands.py
@@ -301,16 +301,107 @@ class MachCommands(MachCommandBase):
         """Create GeckoView archives.
         See http://firefox-source-docs.mozilla.org/build/buildsystem/toolchains.html#firefox-for-android-with-gradle""")
     @CommandArgument('args', nargs=argparse.REMAINDER)
     def android_archive_geckoview(self, args):
         ret = self.gradle(self.substs['GRADLE_ANDROID_ARCHIVE_GECKOVIEW_TASKS'] + ["--continue"] + args, verbose=True)
 
         return ret
 
+    @SubCommand('android', 'geckoview-docs',
+        """Create GeckoView javadoc and optionally upload to Github""")
+    @CommandArgument('--archive', action='store_true',
+        help='Generate a javadoc archive.')
+    @CommandArgument('--upload', metavar='USER/REPO',
+        help='Upload generated javadoc to Github, '
+             'using the specified USER/REPO.')
+    @CommandArgument('--upload-branch', metavar='BRANCH[/PATH]',
+        default='gh-pages/javadoc',
+        help='Use the specified branch/path for commits.')
+    @CommandArgument('--upload-message', metavar='MSG',
+        default='GeckoView docs upload',
+        help='Use the specified message for commits.')
+    @CommandArgument('--variant', default='debug',
+        help='Gradle variant used to generate javadoc.')
+    def android_geckoview_docs(self, archive, upload, upload_branch,
+                               upload_message, variant):
+
+        def capitalize(s):
+            # Can't use str.capitalize because it lower cases trailing letters.
+            return (s[0].upper() + s[1:]) if s else ''
+
+        task = 'geckoview:javadoc' + ('Jar' if archive or upload else '') + capitalize(variant)
+        ret = self.gradle([task], verbose=True)
+        if ret or not upload:
+            return ret
+
+        # Upload to Github.
+        fmt = {
+            'level': os.environ.get('MOZ_SCM_LEVEL', '0'),
+            'project': os.environ.get('MH_BRANCH', 'unknown'),
+            'revision': os.environ.get('GECKO_HEAD_REV', 'tip'),
+        }
+        env = {}
+
+        # In order to push to GitHub from TaskCluster, we store a private key
+        # in the TaskCluster secrets store in the format {"content": "<KEY>"},
+        # and the corresponding public key as a writable deploy key for the
+        # destination repo on GitHub.
+        secret = os.environ.get('GECKOVIEW_DOCS_UPLOAD_SECRET', '').format(**fmt)
+        if secret:
+            # Set up a private key from the secrets store if applicable.
+            import requests
+            req = requests.get('http://taskcluster/secrets/v1/secret/' + secret)
+            req.raise_for_status()
+
+            keyfile = mozpath.abspath('gv-docs-upload-key')
+            with open(keyfile, 'w') as f:
+                os.chmod(keyfile, 0o600)
+                f.write(req.json()['secret']['content'])
+
+            # Turn off strict host key checking so ssh does not complain about
+            # unknown github.com host. We're not pushing anything sensitive, so
+            # it's okay to not check GitHub's host keys.
+            env['GIT_SSH_COMMAND'] = 'ssh -i "%s" -o StrictHostKeyChecking=no' % keyfile
+
+        # Clone remote repo.
+        branch, _, branch_path = upload_branch.partition('/')
+        repo_url = 'git@github.com:%s.git' % upload
+        repo_path = mozpath.abspath('gv-docs-repo')
+        self.run_process(['git', 'clone', '--branch', branch, '--depth', '1',
+                          repo_url, repo_path], append_env=env, pass_thru=True)
+        env['GIT_DIR'] = mozpath.join(repo_path, '.git')
+        env['GIT_WORK_TREE'] = repo_path
+        env['GIT_AUTHOR_NAME'] = env['GIT_COMMITTER_NAME'] = 'GeckoView Docs Bot'
+        env['GIT_AUTHOR_EMAIL'] = env['GIT_COMMITTER_EMAIL'] = 'nobody@mozilla.com'
+
+        # Extract new javadoc to specified directory inside repo.
+        import mozfile
+        src_tar = mozpath.join(self.topobjdir, 'gradle', 'build', 'mobile', 'android',
+                               'geckoview', 'libs', 'geckoview-javadoc.jar')
+        dst_path = mozpath.join(repo_path, branch_path.format(**fmt))
+        mozfile.remove(dst_path)
+        mozfile.extract_zip(src_tar, dst_path)
+
+        # Commit and push.
+        self.run_process(['git', 'add', '--all'], append_env=env, pass_thru=True)
+        if self.run_process(['git', 'diff', '--cached', '--quiet'],
+                            append_env=env, pass_thru=True, ensure_exit_code=False) != 0:
+            # We have something to commit.
+            self.run_process(['git', 'commit',
+                              '--message', upload_message.format(**fmt)],
+                             append_env=env, pass_thru=True)
+            self.run_process(['git', 'push', 'origin', 'gh-pages'],
+                             append_env=env, pass_thru=True)
+
+        mozfile.remove(repo_path)
+        if secret:
+            mozfile.remove(keyfile)
+        return 0
+
 
     @Command('gradle', category='devenv',
         description='Run gradle.',
         conditions=[conditions.is_android])
     @CommandArgument('-v', '--verbose', action='store_true',
         help='Verbose output for what commands the build is running.')
     @CommandArgument('args', nargs=argparse.REMAINDER)
     def gradle(self, args, verbose=False):