Bug 1506267 - Add android-api-lint to automation; r=nalexander
☠☠ backed out by 563e860bea95 ☠ ☠
authorAgi Sferro <agi@mozilla.com>
Fri, 16 Nov 2018 22:18:09 +0000
changeset 446866 7a53f4ea811be066559b13ac702ff358e1c356b1
parent 446865 5d1c5593fdf3109c1754144cd6d42fc1fe10b02d
child 446867 ed2f2725f3206c94fe1bd27dfc7d138a3c249dcd
push id35052
push userapavel@mozilla.com
push dateSat, 17 Nov 2018 11:25:40 +0000
treeherdermozilla-central@efc1da42132b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs1506267
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1506267 - Add android-api-lint to automation; r=nalexander Depends on D11821 Differential Revision: https://phabricator.services.mozilla.com/D12166
mobile/android/gradle.configure
mobile/android/mach_commands.py
taskcluster/ci/build/android-stuff.yml
testing/mozharness/configs/builds/releng_sub_android_configs/64_api_lint.py
testing/mozharness/mozharness/mozilla/building/buildbase.py
--- a/mobile/android/gradle.configure
+++ b/mobile/android/gradle.configure
@@ -64,16 +64,42 @@ def gradle_android_build_config():
         ),
         geckoview_example=namespace(
             variant=variant(('withGeckoBinaries',), 'debug'),
         ),
     )
 
 
 @depends(gradle_android_build_config)
+@imports(_from='itertools', _import='imap')
+def gradle_android_intermediates_folder(build_config):
+    '''Path to intermediates classes folder.'''
+    def uncapitalize(s):
+        if s:
+            return s[0].lower() + s[1:]
+        else:
+            return s
+
+    def capitalize(s):
+        # str.capitalize lower cases trailing letters.
+        if s:
+            return s[0].upper() + s[1:]
+        else:
+            return s
+
+    productFlavor = uncapitalize(''.join(imap(capitalize, build_config.geckoview.variant.productFlavors)))
+    buildType = uncapitalize(build_config.geckoview.variant.buildType)
+
+    return "gradle/build/mobile/android/geckoview/intermediates/classes/{}/{}".format(
+            productFlavor,
+            buildType)
+
+set_config('GRADLE_ANDROID_GECKOVIEW_APILINT_FOLDER', gradle_android_intermediates_folder)
+
+@depends(gradle_android_build_config)
 def gradle_android_variant_name(build_config):
     '''Like "withoutGeckoBinariesDebug".'''
     def uncapitalize(s):
         if s:
             return s[0].lower() + s[1:]
         else:
             return s
 
@@ -195,16 +221,25 @@ set_config('GRADLE_ANDROID_TEST_CCOV_REP
 def gradle_android_lint_tasks(build_config):
     '''Gradle tasks run by |mach android lint|.'''
     return [
         'app:lint{app.variant.name}'.format(app=build_config.app),
     ]
 
 set_config('GRADLE_ANDROID_LINT_TASKS', gradle_android_lint_tasks)
 
+@depends(gradle_android_build_config)
+def gradle_android_api_lint_tasks(build_config):
+    '''Gradle tasks run by |mach android api-lint|.'''
+    return [
+        'geckoview:apiLint{geckoview.variant.name}'.format(geckoview=build_config.geckoview),
+    ]
+
+set_config('GRADLE_ANDROID_API_LINT_TASKS', gradle_android_api_lint_tasks)
+
 
 @dependable
 def gradle_android_checkstyle_tasks():
     '''Gradle tasks run by |mach android checkstyle|.'''
     return [
         'app:checkstyle',
     ]
 
@@ -268,16 +303,17 @@ def gradle_android_install_geckoview_exa
         'geckoview_example:install{geckoview_example.variant.name}AndroidTest'.format(geckoview_example=build_config.geckoview_example),
     ]
 
 set_config('GRADLE_ANDROID_INSTALL_GECKOVIEW_EXAMPLE_TASKS', gradle_android_install_geckoview_example_tasks)
 
 
 @depends(
     gradle_android_app_tasks,
+    gradle_android_api_lint_tasks,
     gradle_android_test_tasks,
     gradle_android_lint_tasks,
     gradle_android_checkstyle_tasks,
     gradle_android_findbugs_tasks,
     gradle_android_archive_geckoview_tasks,
     gradle_android_generate_sdk_bindings_tasks,
     gradle_android_generate_generated_jni_wrappers_tasks,
     gradle_android_generate_fennec_jni_wrappers_tasks,
--- a/mobile/android/mach_commands.py
+++ b/mobile/android/mach_commands.py
@@ -5,16 +5,17 @@
 from __future__ import absolute_import, print_function, unicode_literals
 
 import argparse
 import logging
 import os
 import shutil
 import subprocess
 import zipfile
+import json
 
 from zipfile import ZipFile
 
 import mozpack.path as mozpath
 
 from mozfile import TemporaryDirectory
 
 from mozbuild.base import (
@@ -107,16 +108,37 @@ class MachCommands(MachCommandBase):
                 Firefox for Android.""")
     @CommandArgument('args', nargs=argparse.REMAINDER)
     def android_generate_fennec_jni_wrappers(self, args):
         ret = self.gradle(
             self.substs['GRADLE_ANDROID_GENERATE_FENNEC_JNI_WRAPPERS_TASKS'] + args, verbose=True)
 
         return ret
 
+    @SubCommand('android', 'api-lint',
+                """Runs apilint against GeckoView.""")
+    @CommandArgument('args', nargs=argparse.REMAINDER)
+    def android_api_lint(self, args):
+        ret = self.gradle(self.substs['GRADLE_ANDROID_API_LINT_TASKS'] + args, verbose=True)
+        folder = self.substs['GRADLE_ANDROID_GECKOVIEW_APILINT_FOLDER']
+
+        with open(os.path.join(
+                self.topobjdir,
+                '{}/apilint-result.json'.format(folder))) as f:
+            result = json.load(f)
+
+            print('SUITE-START | android-api-lint')
+            for r in result['compat_failures'] + result['failures']:
+                print ('TEST-UNEXPECTED-FAIL | {} | {}'.format(r['detail'], r['msg']))
+            for r in result['api_changes']:
+                print ('TEST-UNEXPECTED-FAIL | {} | Unexpected api change'.format(r))
+            print('SUITE-END | android-api-lint')
+
+        return ret
+
     @SubCommand('android', 'test',
                 """Run Android local unit tests.
                 See https://developer.mozilla.org/en-US/docs/Mozilla/Android-specific_test_suites#android-test""")  # NOQA: E501
     @CommandArgument('args', nargs=argparse.REMAINDER)
     def android_test(self, args):
         ret = self.gradle(self.substs['GRADLE_ANDROID_TEST_TASKS'] +
                           ["--continue"] + args, verbose=True)
 
--- a/taskcluster/ci/build/android-stuff.yml
+++ b/taskcluster/ci/build/android-stuff.yml
@@ -144,16 +144,63 @@ android-lint/opt:
             - "mobile/android/**/*.svg"
             - "mobile/android/**/*.xml"
             - "mobile/android/**/Makefile.in"
             - "mobile/android/config/**"
             - "mobile/android/gradle.configure"
             - "mobile/android/**/moz.build"
             - "**/*.gradle"
 
+android-api-lint/opt:
+    description: "Android apilint"
+    index:
+        product: mobile
+        job-name: android-api-lint
+    treeherder:
+        platform: android-4-0-armv7-api16/opt
+        kind: build
+        tier: 1
+        symbol: A(apilint)
+    worker-type: aws-provisioner-v1/gecko-{level}-b-android
+    worker:
+        docker-image: {in-tree: android-build}
+        env:
+            GRADLE_USER_HOME: "/builds/worker/workspace/build/src/mobile/android/gradle/dotgradle-offline"
+            PERFHERDER_EXTRA_OPTIONS: android-api-lint
+        artifacts:
+            - name: public/android/geckoview/api.txt
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/intermediates/classes/withGeckoBinaries/debug/api.txt
+              type: file
+            - name: public/android/geckoview/apilint-result.json
+              path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/intermediates/classes/withGeckoBinaries/debug/apilint-result.json
+              type: file
+        max-run-time: 7200
+    run:
+        using: mozharness
+        actions: [get-secrets, build]
+        config:
+            - builds/releng_base_android_64_builds.py
+        script: "mozharness/scripts/fx_desktop_build.py"
+        secrets: true
+        custom-build-variant-cfg: android-api-lint
+        tooltool-downloads: internal
+    toolchains:
+        - android-gradle-dependencies
+        - android-sdk-linux
+        - linux64-node
+    optimization:
+        skip-unless-changed:
+            - "mobile/android/**/*.java"
+            - "mobile/android/**/*.kt"
+            - "mobile/android/**/Makefile.in"
+            - "mobile/android/config/**"
+            - "mobile/android/gradle.configure"
+            - "mobile/android/**/moz.build"
+            - "**/*.gradle"
+
 android-checkstyle/opt:
     description: "Android checkstyle"
     index:
         product: mobile
         job-name: android-checkstyle
     treeherder:
         platform: android-4-0-armv7-api16/opt
         kind: build
new file mode 100644
--- /dev/null
+++ b/testing/mozharness/configs/builds/releng_sub_android_configs/64_api_lint.py
@@ -0,0 +1,14 @@
+config = {
+    'stage_platform': 'android-api-lint',
+    'src_mozconfig': 'mobile/android/config/mozconfigs/android-api-16-frontend/nightly',
+    'multi_locale_config_platform': 'android',
+    # apilint doesn't produce a package. So don't collect package metrics.
+    'disable_package_metrics': True,
+    'postflight_build_mach_commands': [
+        ['android',
+         'api-lint',
+        ],
+    ],
+    'artifact_flag_build_variant_in_try': None, # There's no artifact equivalent.
+    'max_build_output_timeout': 0,
+}
--- a/testing/mozharness/mozharness/mozilla/building/buildbase.py
+++ b/testing/mozharness/mozharness/mozilla/building/buildbase.py
@@ -383,16 +383,17 @@ class BuildOptionParser(object):
         'x86-fuzzing-debug': 'builds/releng_sub_%s_configs/%s_x86_fuzzing_debug.py',
         'x86_64': 'builds/releng_sub_%s_configs/%s_x86_64.py',
         'x86_64-artifact': 'builds/releng_sub_%s_configs/%s_x86_64_artifact.py',
         'api-16-partner-sample1': 'builds/releng_sub_%s_configs/%s_api_16_partner_sample1.py',
         'aarch64': 'builds/releng_sub_%s_configs/%s_aarch64.py',
         'android-test': 'builds/releng_sub_%s_configs/%s_test.py',
         'android-test-ccov': 'builds/releng_sub_%s_configs/%s_test_ccov.py',
         'android-checkstyle': 'builds/releng_sub_%s_configs/%s_checkstyle.py',
+        'android-api-lint': 'builds/releng_sub_%s_configs/%s_api_lint.py',
         'android-lint': 'builds/releng_sub_%s_configs/%s_lint.py',
         'android-findbugs': 'builds/releng_sub_%s_configs/%s_findbugs.py',
         'android-geckoview-docs': 'builds/releng_sub_%s_configs/%s_geckoview_docs.py',
         'valgrind': 'builds/releng_sub_%s_configs/%s_valgrind.py',
         'artifact': 'builds/releng_sub_%s_configs/%s_artifact.py',
         'debug-artifact': 'builds/releng_sub_%s_configs/%s_debug_artifact.py',
         'tup': 'builds/releng_sub_%s_configs/%s_tup.py',
     }