Bug 1482395: [mozrelease] Add support for generating update metadata; r=mtabara
authorTom Prince <mozilla@hocat.ca>
Tue, 27 Nov 2018 18:47:14 +0000
changeset 501398 e0e9425868e01468879f3cc77a6b8b360b419ded
parent 501397 563339c115b0dda1880ffa71c1adaf3ffb1014ae
child 501399 88ab1bde62780758f0234c0ba7704db281397716
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmtabara
bugs1482395
milestone64.0
Bug 1482395: [mozrelease] Add support for generating update metadata; r=mtabara Differential Revision: https://phabricator.services.mozilla.com/D12707
python/mozrelease/mozrelease/balrog.py
python/mozrelease/mozrelease/util.py
python/mozrelease/test/data/Firefox-62.0.3.update.json
python/mozrelease/test/data/Firefox-62.0b11-update.json
python/mozrelease/test/data/Firefox-62.0b11.update.json
python/mozrelease/test/data/whatsnew-62.0.3.yml
python/mozrelease/test/data/whatsnew-release.yml
python/mozrelease/test/python.ini
python/mozrelease/test/test_balrog.py
taskcluster/ci/source-test/python.yml
new file mode 100644
--- /dev/null
+++ b/python/mozrelease/mozrelease/balrog.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+
+def _generate_show_url(context, entry):
+    url = entry['url']
+    return {
+        "actions": "showURL",
+        "openURL": url.format(**context),
+    }
+
+
+def _generate_product_details(context, entry):
+    url = entry['url']
+    return {
+        'detailsURL': url.format(**context),
+        'type': 'minor',
+    }
+
+
+_FIELD_TYPES = {
+    'show-url': _generate_show_url,
+    'product-details': _generate_product_details,
+}
+
+
+def _generate_conditions(context, entry):
+    if 'release-types' in entry and context['release-type'] not in entry['release-types']:
+        return None
+    if 'blob-types' in entry and context['blob-type'] not in entry['blob-types']:
+        return None
+    if 'products' in entry and context['product'] not in entry['products']:
+        return None
+
+    conditions = {}
+    if 'locales' in entry:
+        conditions['locales'] = entry['locales']
+    if 'versions' in entry:
+        conditions['versions'] = [
+            version.format(**context)
+            for version in entry['versions']
+        ]
+    if 'update-channel' in entry:
+        conditions['channels'] = [
+            entry['update-channel'] + suffix
+            for suffix in ('', '-localtest', '-cdntest')
+        ]
+    return conditions
+
+
+def generate_update_properties(context, config):
+    result = []
+    for entry in config:
+        fields = _FIELD_TYPES[entry['type']](context, entry)
+        conditions = _generate_conditions(context, entry.get('conditions', {}))
+
+        if conditions is not None:
+            result.append({
+                'fields': fields,
+                'for': conditions,
+            })
+    return result
new file mode 100644
--- /dev/null
+++ b/python/mozrelease/mozrelease/util.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+from yaml.loader import SafeLoader
+
+
+class UnicodeLoader(SafeLoader):
+    def construct_yaml_str(self, node):
+        return self.construct_scalar(node)
+
+
+UnicodeLoader.add_constructor(
+    'tag:yaml.org,2002:str',
+    UnicodeLoader.construct_yaml_str)
+
+
+def load(stream):
+    """
+    Parse the first YAML document in a stream
+    and produce the corresponding Python object.
+    """
+    loader = UnicodeLoader(stream)
+    try:
+        return loader.get_single_data()
+    finally:
+        loader.dispose()
new file mode 100644
--- /dev/null
+++ b/python/mozrelease/test/data/Firefox-62.0.3.update.json
@@ -0,0 +1,74 @@
+[
+    {
+        "fields": {
+            "detailsURL": "https://www.mozilla.org/%LOCALE%/firefox/62.0.3/releasenotes/",
+            "type": "minor"
+        },
+        "for": {}
+    },
+    {
+        "fields": {
+            "actions": "showURL",
+            "openURL": "https://www.mozilla.org/%LOCALE%/firefox/62.0.3/whatsnew/?oldversion=%OLD_VERSION%"
+        },
+        "for": {
+            "channels": [
+                "release",
+                "release-localtest",
+                "release-cdntest"
+            ],
+            "locales": [
+                "cak",
+                "cy",
+                "da",
+                "de",
+                "dsb",
+                "en-CA",
+                "en-US",
+                "es-AR",
+                "es-CL",
+                "es-ES",
+                "es-MX",
+                "et",
+                "fa",
+                "fi",
+                "fr",
+                "fy-NL",
+                "gn",
+                "gu-IN",
+                "hsb",
+                "hu",
+                "ia",
+                "id",
+                "it",
+                "ja",
+                "ja-JP-mac",
+                "ka",
+                "kab",
+                "ko",
+                "lij",
+                "lt",
+                "ms",
+                "nb-NO",
+                "nl",
+                "nn-NO",
+                "pl",
+                "pt-BR",
+                "pt-PT",
+                "sk",
+                "sl",
+                "sq",
+                "sr",
+                "sv-SE",
+                "tr",
+                "uk",
+                "vi",
+                "zh-CN",
+                "zh-TW"
+            ],
+            "versions": [
+                "<62.0"
+            ]
+        }
+    }
+]
new file mode 100644
--- /dev/null
+++ b/python/mozrelease/test/data/Firefox-62.0b11-update.json
@@ -0,0 +1,74 @@
+[
+    {
+        "fields": {
+            "detailsURL": "https://www.mozilla.org/%LOCALE%/firefox/62.0.3/releasenotes/",
+            "type": "minor"
+        },
+        "for": {}
+    },
+    {
+        "fields": {
+            "actions": "showURL",
+            "openURL": "https://www.mozilla.org/%LOCALE%/firefox/62.0.3/whatsnew/?oldversion=%OLD_VERSION%"
+        },
+        "for": {
+            "channels": [
+                "release",
+                "release-localtest",
+                "release-cdntest"
+            ],
+            "locales": [
+                "cak",
+                "cy",
+                "da",
+                "de",
+                "dsb",
+                "en-CA",
+                "en-US",
+                "es-AR",
+                "es-CL",
+                "es-ES",
+                "es-MX",
+                "et",
+                "fa",
+                "fi",
+                "fr",
+                "fy-NL",
+                "gn",
+                "gu-IN",
+                "hsb",
+                "hu",
+                "ia",
+                "id",
+                "it",
+                "ja",
+                "ja-JP-mac",
+                "ka",
+                "kab",
+                "ko",
+                "lij",
+                "lt",
+                "ms",
+                "nb-NO",
+                "nl",
+                "nn-NO",
+                "pl",
+                "pt-BR",
+                "pt-PT",
+                "sk",
+                "sl",
+                "sq",
+                "sr",
+                "sv-SE",
+                "tr",
+                "uk",
+                "vi",
+                "zh-CN",
+                "zh-TW"
+            ],
+            "versions": [
+                "<62.0"
+            ]
+        }
+    }
+]
new file mode 100644
--- /dev/null
+++ b/python/mozrelease/test/data/Firefox-62.0b11.update.json
@@ -0,0 +1,9 @@
+[
+    {
+        "fields": {
+            "detailsURL": "https://www.mozilla.org/%LOCALE%/firefox/62.0b11/releasenotes/",
+            "type": "minor"
+        },
+        "for": {}
+    }
+]
new file mode 100644
--- /dev/null
+++ b/python/mozrelease/test/data/whatsnew-62.0.3.yml
@@ -0,0 +1,65 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+---
+- type: product-details
+  url: "https://www.mozilla.org/%LOCALE%/{product}/{version}/releasenotes/"
+# %LOCALE% is automatically replaced by Balrog.
+- type: show-url
+  # yamllint disable-line rule:line-length
+  url: "https://www.mozilla.org/%LOCALE%/{product}/{version}/whatsnew/?oldversion=%OLD_VERSION%"
+  conditions:
+      release-types: [release]
+      products: [firefox]
+      update-channel: release
+      # e.g.: ["<61.0"]. {version.major_number} reflects the current version.
+      # This is done by taskgraph.
+      versions: ["<{version.major_number}.0"]
+      locales:
+          - cak
+          - cy
+          - da
+          - de
+          - dsb
+          - en-CA
+          - en-US
+          - es-AR
+          - es-CL
+          - es-ES
+          - es-MX
+          - et
+          - fa
+          - fi
+          - fr
+          - fy-NL
+          - gn
+          - gu-IN
+          - hsb
+          - hu
+          - ia
+          - id
+          - it
+          - ja
+          - ja-JP-mac
+          - ka
+          - kab
+          - ko
+          - lij
+          - lt
+          - ms
+          - nb-NO
+          - nl
+          - nn-NO
+          - pl
+          - pt-BR
+          - pt-PT
+          - sk
+          - sl
+          - sq
+          - sr
+          - sv-SE
+          - tr
+          - uk
+          - vi
+          - zh-CN
+          - zh-TW
new file mode 100644
--- /dev/null
+++ b/python/mozrelease/test/data/whatsnew-release.yml
@@ -0,0 +1,65 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+---
+- type: product-details
+  url: "https://www.mozilla.org/%LOCALE%/{product}/{version}/releasenotes/"
+# %LOCALE% is automatically replaced by Balrog.
+- type: show-url
+  # yamllint disable-line rule:line-length
+  url: "https://www.mozilla.org/%LOCALE%/{product}/{version}/whatsnew/?oldversion=%OLD_VERSION%"
+  conditions:
+      release-types: [release]
+      products: [firefox]
+      update-channel: release
+      # e.g.: ["<61.0"]. {version.major_number} reflects the current version.
+      # This is done by taskgraph.
+      versions: ["<{version.major_number}.0"]
+      locales:
+          - cak
+          - cy
+          - da
+          - de
+          - dsb
+          - en-CA
+          - en-US
+          - es-AR
+          - es-CL
+          - es-ES
+          - es-MX
+          - et
+          - fa
+          - fi
+          - fr
+          - fy-NL
+          - gn
+          - gu-IN
+          - hsb
+          - hu
+          - ia
+          - id
+          - it
+          - ja
+          - ja-JP-mac
+          - ka
+          - kab
+          - ko
+          - lij
+          - lt
+          - ms
+          - nb-NO
+          - nl
+          - nn-NO
+          - pl
+          - pt-BR
+          - pt-PT
+          - sk
+          - sl
+          - sq
+          - sr
+          - sv-SE
+          - tr
+          - uk
+          - vi
+          - zh-CN
+          - zh-TW
--- a/python/mozrelease/test/python.ini
+++ b/python/mozrelease/test/python.ini
@@ -1,6 +1,8 @@
 [DEFAULT]
 subsuite=mozrelease
-skip-if = python == 3
 
 [test_versions.py]
+skip-if = python == 3
+[test_balrog.py]
 [test_buglist_creator.py]
+skip-if = python == 3
new file mode 100644
--- /dev/null
+++ b/python/mozrelease/test/test_balrog.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+import mozunit
+import pytest
+
+import json
+from mozrelease.util import load as yaml_load
+from pathlib2 import Path
+
+from mozrelease.balrog import generate_update_properties
+from mozilla_version.gecko import GeckoVersion
+
+DATA_PATH = Path(__file__).parent.joinpath('data')
+
+
+@pytest.mark.parametrize('context,config_file,output_file', [
+    ({
+        'release-type': 'release',
+        'product': 'firefox',
+        'version': GeckoVersion.parse('62.0.3'),
+    }, 'whatsnew-62.0.3.yml', 'Firefox-62.0.3.update.json'),
+    ({
+        'release-type': 'beta',
+        'product': 'firefox',
+        'version': GeckoVersion.parse('62.0b11'),
+    }, 'whatsnew-62.0.3.yml', 'Firefox-62.0b11.update.json'),
+])
+def test_update_properties(context, config_file, output_file):
+    with DATA_PATH.joinpath(config_file).open('r', encoding='utf-8') as f:
+        config = yaml_load(f)
+
+    update_line = generate_update_properties(context, config)
+
+    assert update_line == json.load(DATA_PATH.joinpath(output_file).open('r', encoding='utf-8'))
+
+
+if __name__ == '__main__':
+    mozunit.main()
--- a/taskcluster/ci/source-test/python.yml
+++ b/taskcluster/ci/source-test/python.yml
@@ -123,17 +123,17 @@ mozlint:
         subsuite: mozlint
     when:
         files-changed:
             - 'python/mozlint/**'
             - 'tools/lint/**'
 
 mozrelease:
     description: python/mozrelease unit tests
-    python-version: [2]
+    python-version: [2, 3]
     treeherder:
         symbol: release
     run:
         using: python-test
         subsuite: mozrelease
     when:
         files-changed:
             - 'python/mozrelease/**'