{"action":"created","comment":{"url":"https://api.github.com/repos/mozilla/socorro/pulls/comments/84098003","pull_request_review_id":4896867,"id":84098003,"diff_hunk":"@@ -0,0 +1,138 @@\n+import re\n+\n+import requests\n+\n+from configman import Namespace\n+from crontabber.base import BaseCronApp\n+from crontabber.mixins import (\n+    with_postgres_transactions,\n+    with_single_postgres_transaction,\n+)\n+\n+\n+def alias_list_to_dict(input_string):\n+    aliases = {}\n+    for item in input_string.split(','):\n+        if not item.strip():\n+            continue\n+        key, value = item.split(':')\n+        aliases[key.strip()] = value.strip()\n+    return aliases\n+\n+\n+class DownloadError(Exception):\n+    \"\"\"when downloading a network resource fails\"\"\"\n+\n+\n+@with_postgres_transactions()\n+@with_single_postgres_transaction()\n+class FeaturedVersionsAutomaticCronApp(BaseCronApp):\n+    app_name = 'featured-versions-automatic'\n+    app_description = \"\"\"Use https://product-details.mozilla.org/1.0/\n+    to automatically figure out what product versions should be\n+    set as featured.\n+    \"\"\"\n+\n+    required_config = Namespace()\n+    required_config.add_option(\n+        'api_endpoint_url',\n+        default=(\n+            'https://product-details.mozilla.org/1.0/'\n+        ),\n+        doc='URL from which we can download all the featured versions'\n+    )\n+    required_config.add_option(\n+        'products',\n+        default='firefox,mobile,thunderbird',\n+        from_string_converter=lambda line: tuple(\n+            [x.strip() for x in line.split(',') if x.strip()]\n+        ),\n+        doc='a comma-delimited list of products to recognize'\n+    )\n+    required_config.add_option(\n+        'aliases',\n+        default='mobile:FennecAndroid',\n+        from_string_converter=alias_list_to_dict,\n+        doc=(\n+            'a comma-delimited list of name:RealName. If a product '\n+            'does not need an alias match it by capitalizing the name '\n+            '(e.g. \"thunderbird\" -> \"Thunderbird\")'\n+        )\n+    )\n+\n+    def run(self, connection):\n+        assert isinstance(self.config.api_endpoint_url, basestring)\n+        assert self.config.api_endpoint_url.endswith('/')\n+\n+        # The @with_single_postgres_transaction decorator makes\n+        # sure this cursor is committed or rolled back and cleaned up.\n+        cursor = connection.cursor()\n+\n+        for product in self.config.products:\n+            url = '{}{}_versions.json'.format(","path":"socorro/cron/jobs/featured_versions_automatic.py","position":72,"original_position":72,"commit_id":"9ddcec5bbbc82620d4b948a9e29048bc79ea5929","original_commit_id":"9ddcec5bbbc82620d4b948a9e29048bc79ea5929","user":{"login":"peterbe","id":26739,"avatar_url":"https://avatars.githubusercontent.com/u/26739?v=3","gravatar_id":"","url":"https://api.github.com/users/peterbe","html_url":"https://github.com/peterbe","followers_url":"https://api.github.com/users/peterbe/followers","following_url":"https://api.github.com/users/peterbe/following{/other_user}","gists_url":"https://api.github.com/users/peterbe/gists{/gist_id}","starred_url":"https://api.github.com/users/peterbe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peterbe/subscriptions","organizations_url":"https://api.github.com/users/peterbe/orgs","repos_url":"https://api.github.com/users/peterbe/repos","events_url":"https://api.github.com/users/peterbe/events{/privacy}","received_events_url":"https://api.github.com/users/peterbe/received_events","type":"User","site_admin":false},"body":"Much better!","created_at":"2016-10-19T15:30:49Z","updated_at":"2016-10-19T15:30:49Z","html_url":"https://github.com/mozilla/socorro/pull/3537#discussion_r84098003","pull_request_url":"https://api.github.com/repos/mozilla/socorro/pulls/3537","_links":{"self":{"href":"https://api.github.com/repos/mozilla/socorro/pulls/comments/84098003"},"html":{"href":"https://github.com/mozilla/socorro/pull/3537#discussion_r84098003"},"pull_request":{"href":"https://api.github.com/repos/mozilla/socorro/pulls/3537"}}},"pull_request":{"url":"https://api.github.com/repos/mozilla/socorro/pulls/3537","id":89858911,"html_url":"https://github.com/mozilla/socorro/pull/3537","diff_url":"https://github.com/mozilla/socorro/pull/3537.diff","patch_url":"https://github.com/mozilla/socorro/pull/3537.patch","issue_url":"https://api.github.com/repos/mozilla/socorro/issues/3537","number":3537,"state":"open","locked":false,"title":"bug 1260420 - set featured versions by product-defails.m.o","user":{"login":"peterbe","id":26739,"avatar_url":"https://avatars.githubusercontent.com/u/26739?v=3","gravatar_id":"","url":"https://api.github.com/users/peterbe","html_url":"https://github.com/peterbe","followers_url":"https://api.github.com/users/peterbe/followers","following_url":"https://api.github.com/users/peterbe/following{/other_user}","gists_url":"https://api.github.com/users/peterbe/gists{/gist_id}","starred_url":"https://api.github.com/users/peterbe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peterbe/subscriptions","organizations_url":"https://api.github.com/users/peterbe/orgs","repos_url":"https://api.github.com/users/peterbe/repos","events_url":"https://api.github.com/users/peterbe/events{/privacy}","received_events_url":"https://api.github.com/users/peterbe/received_events","type":"User","site_admin":false},"body":"I appreciate this is a bit hard to test manually. But I've done it. Perhaps you can simply trust me with the manual testing.\r\n\r\nHere's what I did:\r\n```\r\n$ pg_dump -p 5433 -h localhost -U breakpad_rw -a -t product_versions -t products  breakpad  > /tmp/stagedbstuff.sql\r\n$ psql socorro_integration_test < /tmp/stagedbstuff.sql\r\n```\r\nNow, I have in my local PG a bunch of realistic `product_versions` data. \r\n\r\nThen I run crontabber like this:\r\n```\r\n$ python socorro/cron/crontabber_app.py --admin.conf=../local-crontabber.ini \r\n```\r\nIn my `../local-crontabber.ini` the postgres credentials are set up to point to my local `socorro_integration_test` database. And the last couple of lines of that ini file are these:\r\n```\r\n    jobs='''\r\n    #socorro.cron.jobs.bugzilla.BugzillaCronApp|1d\r\n    socorro.cron.jobs.featured_versions_automatic.FeaturedVersionsAutomaticCronApp|1h\r\n    '''\r\n```\r\n\r\nWhen I run it I get this output:\r\n\r\n```\r\n2016-10-18 13:07:06,827 DEBUG - MainThread -  - MainThread - about to run <class 'socorro.cron.jobs.featured_versions_automatic.FeaturedVersionsAutomaticCronApp'>\r\n2016-10-18 13:07:07,514 INFO - MainThread -  - MainThread - Set featured versions for Firefox to: 49.0.1, 50.0b, 51.0a2, 52.0a1\r\n2016-10-18 13:07:08,026 INFO - MainThread -  - MainThread - Set featured versions for FennecAndroid to: 49.0, 50.0b6, 51.0a2, 52.0a1\r\n2016-10-18 13:07:08,544 INFO - MainThread -  - MainThread - Set featured versions for Thunderbird to: 45.4.0, 50.0b1, 51.0a2\r\n2016-10-18 13:07:08,545 DEBUG - MainThread -  - MainThread - successfully ran <class 'socorro.cron.jobs.featured_versions_automatic.FeaturedVersionsAutomaticCronApp'> on 2016-10-18 17:07:06.843628+00:00\r\n2016-10-18 13:07:08,564 INFO - MainThread -  - MainThread - done.\r\n```\r\n\r\nThe most important thing to note is the featured versions specifically for Firefox are: `49.0.1, 50.0b, 51.0a2, 52.0a1`\r\nThat `50.0b` comes from taking `\"LATEST_FIREFOX_DEVEL_VERSION\"`  from https://product-details.mozilla.org/1.0/firefox_versions.json and carefully drop the number after the `b`. ","created_at":"2016-10-18T17:08:36Z","updated_at":"2016-10-19T15:30:49Z","closed_at":null,"merged_at":null,"merge_commit_sha":"042087e9b28307ca2daa934dedadbab2cd31431c","assignee":{"login":"adngdb","id":328790,"avatar_url":"https://avatars.githubusercontent.com/u/328790?v=3","gravatar_id":"","url":"https://api.github.com/users/adngdb","html_url":"https://github.com/adngdb","followers_url":"https://api.github.com/users/adngdb/followers","following_url":"https://api.github.com/users/adngdb/following{/other_user}","gists_url":"https://api.github.com/users/adngdb/gists{/gist_id}","starred_url":"https://api.github.com/users/adngdb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adngdb/subscriptions","organizations_url":"https://api.github.com/users/adngdb/orgs","repos_url":"https://api.github.com/users/adngdb/repos","events_url":"https://api.github.com/users/adngdb/events{/privacy}","received_events_url":"https://api.github.com/users/adngdb/received_events","type":"User","site_admin":false},"assignees":[{"login":"adngdb","id":328790,"avatar_url":"https://avatars.githubusercontent.com/u/328790?v=3","gravatar_id":"","url":"https://api.github.com/users/adngdb","html_url":"https://github.com/adngdb","followers_url":"https://api.github.com/users/adngdb/followers","following_url":"https://api.github.com/users/adngdb/following{/other_user}","gists_url":"https://api.github.com/users/adngdb/gists{/gist_id}","starred_url":"https://api.github.com/users/adngdb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adngdb/subscriptions","organizations_url":"https://api.github.com/users/adngdb/orgs","repos_url":"https://api.github.com/users/adngdb/repos","events_url":"https://api.github.com/users/adngdb/events{/privacy}","received_events_url":"https://api.github.com/users/adngdb/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/mozilla/socorro/pulls/3537/commits","review_comments_url":"https://api.github.com/repos/mozilla/socorro/pulls/3537/comments","review_comment_url":"https://api.github.com/repos/mozilla/socorro/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mozilla/socorro/issues/3537/comments","statuses_url":"https://api.github.com/repos/mozilla/socorro/statuses/9ddcec5bbbc82620d4b948a9e29048bc79ea5929","head":{"label":"peterbe:bug-1260420-set-featured-versions-by-product-defailsmo","ref":"bug-1260420-set-featured-versions-by-product-defailsmo","sha":"9ddcec5bbbc82620d4b948a9e29048bc79ea5929","user":{"login":"peterbe","id":26739,"avatar_url":"https://avatars.githubusercontent.com/u/26739?v=3","gravatar_id":"","url":"https://api.github.com/users/peterbe","html_url":"https://github.com/peterbe","followers_url":"https://api.github.com/users/peterbe/followers","following_url":"https://api.github.com/users/peterbe/following{/other_user}","gists_url":"https://api.github.com/users/peterbe/gists{/gist_id}","starred_url":"https://api.github.com/users/peterbe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peterbe/subscriptions","organizations_url":"https://api.github.com/users/peterbe/orgs","repos_url":"https://api.github.com/users/peterbe/repos","events_url":"https://api.github.com/users/peterbe/events{/privacy}","received_events_url":"https://api.github.com/users/peterbe/received_events","type":"User","site_admin":false},"repo":{"id":2920665,"name":"socorro","full_name":"peterbe/socorro","owner":{"login":"peterbe","id":26739,"avatar_url":"https://avatars.githubusercontent.com/u/26739?v=3","gravatar_id":"","url":"https://api.github.com/users/peterbe","html_url":"https://github.com/peterbe","followers_url":"https://api.github.com/users/peterbe/followers","following_url":"https://api.github.com/users/peterbe/following{/other_user}","gists_url":"https://api.github.com/users/peterbe/gists{/gist_id}","starred_url":"https://api.github.com/users/peterbe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peterbe/subscriptions","organizations_url":"https://api.github.com/users/peterbe/orgs","repos_url":"https://api.github.com/users/peterbe/repos","events_url":"https://api.github.com/users/peterbe/events{/privacy}","received_events_url":"https://api.github.com/users/peterbe/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/peterbe/socorro","description":"Socorro is a server to accept and process Breakpad crash reports. ","fork":true,"url":"https://api.github.com/repos/peterbe/socorro","forks_url":"https://api.github.com/repos/peterbe/socorro/forks","keys_url":"https://api.github.com/repos/peterbe/socorro/keys{/key_id}","collaborators_url":"https://api.github.com/repos/peterbe/socorro/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/peterbe/socorro/teams","hooks_url":"https://api.github.com/repos/peterbe/socorro/hooks","issue_events_url":"https://api.github.com/repos/peterbe/socorro/issues/events{/number}","events_url":"https://api.github.com/repos/peterbe/socorro/events","assignees_url":"https://api.github.com/repos/peterbe/socorro/assignees{/user}","branches_url":"https://api.github.com/repos/peterbe/socorro/branches{/branch}","tags_url":"https://api.github.com/repos/peterbe/socorro/tags","blobs_url":"https://api.github.com/repos/peterbe/socorro/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/peterbe/socorro/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/peterbe/socorro/git/refs{/sha}","trees_url":"https://api.github.com/repos/peterbe/socorro/git/trees{/sha}","statuses_url":"https://api.github.com/repos/peterbe/socorro/statuses/{sha}","languages_url":"https://api.github.com/repos/peterbe/socorro/languages","stargazers_url":"https://api.github.com/repos/peterbe/socorro/stargazers","contributors_url":"https://api.github.com/repos/peterbe/socorro/contributors","subscribers_url":"https://api.github.com/repos/peterbe/socorro/subscribers","subscription_url":"https://api.github.com/repos/peterbe/socorro/subscription","commits_url":"https://api.github.com/repos/peterbe/socorro/commits{/sha}","git_commits_url":"https://api.github.com/repos/peterbe/socorro/git/commits{/sha}","comments_url":"https://api.github.com/repos/peterbe/socorro/comments{/number}","issue_comment_url":"https://api.github.com/repos/peterbe/socorro/issues/comments{/number}","contents_url":"https://api.github.com/repos/peterbe/socorro/contents/{+path}","compare_url":"https://api.github.com/repos/peterbe/socorro/compare/{base}...{head}","merges_url":"https://api.github.com/repos/peterbe/socorro/merges","archive_url":"https://api.github.com/repos/peterbe/socorro/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/peterbe/socorro/downloads","issues_url":"https://api.github.com/repos/peterbe/socorro/issues{/number}","pulls_url":"https://api.github.com/repos/peterbe/socorro/pulls{/number}","milestones_url":"https://api.github.com/repos/peterbe/socorro/milestones{/number}","notifications_url":"https://api.github.com/repos/peterbe/socorro/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/peterbe/socorro/labels{/name}","releases_url":"https://api.github.com/repos/peterbe/socorro/releases{/id}","deployments_url":"https://api.github.com/repos/peterbe/socorro/deployments","created_at":"2011-12-05T23:07:30Z","updated_at":"2014-06-24T00:26:16Z","pushed_at":"2016-10-18T19:19:34Z","git_url":"git://github.com/peterbe/socorro.git","ssh_url":"git@github.com:peterbe/socorro.git","clone_url":"https://github.com/peterbe/socorro.git","svn_url":"https://github.com/peterbe/socorro","homepage":"https://wiki.mozilla.org/Socorro","size":169947,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"mozilla:master","ref":"master","sha":"689293059be3f2e90f8acd79979d427d178d182b","user":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"repo":{"id":2263742,"name":"socorro","full_name":"mozilla/socorro","owner":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mozilla/socorro","description":"Socorro is a server to accept and process Breakpad crash reports. ","fork":false,"url":"https://api.github.com/repos/mozilla/socorro","forks_url":"https://api.github.com/repos/mozilla/socorro/forks","keys_url":"https://api.github.com/repos/mozilla/socorro/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mozilla/socorro/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mozilla/socorro/teams","hooks_url":"https://api.github.com/repos/mozilla/socorro/hooks","issue_events_url":"https://api.github.com/repos/mozilla/socorro/issues/events{/number}","events_url":"https://api.github.com/repos/mozilla/socorro/events","assignees_url":"https://api.github.com/repos/mozilla/socorro/assignees{/user}","branches_url":"https://api.github.com/repos/mozilla/socorro/branches{/branch}","tags_url":"https://api.github.com/repos/mozilla/socorro/tags","blobs_url":"https://api.github.com/repos/mozilla/socorro/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mozilla/socorro/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mozilla/socorro/git/refs{/sha}","trees_url":"https://api.github.com/repos/mozilla/socorro/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mozilla/socorro/statuses/{sha}","languages_url":"https://api.github.com/repos/mozilla/socorro/languages","stargazers_url":"https://api.github.com/repos/mozilla/socorro/stargazers","contributors_url":"https://api.github.com/repos/mozilla/socorro/contributors","subscribers_url":"https://api.github.com/repos/mozilla/socorro/subscribers","subscription_url":"https://api.github.com/repos/mozilla/socorro/subscription","commits_url":"https://api.github.com/repos/mozilla/socorro/commits{/sha}","git_commits_url":"https://api.github.com/repos/mozilla/socorro/git/commits{/sha}","comments_url":"https://api.github.com/repos/mozilla/socorro/comments{/number}","issue_comment_url":"https://api.github.com/repos/mozilla/socorro/issues/comments{/number}","contents_url":"https://api.github.com/repos/mozilla/socorro/contents/{+path}","compare_url":"https://api.github.com/repos/mozilla/socorro/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mozilla/socorro/merges","archive_url":"https://api.github.com/repos/mozilla/socorro/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mozilla/socorro/downloads","issues_url":"https://api.github.com/repos/mozilla/socorro/issues{/number}","pulls_url":"https://api.github.com/repos/mozilla/socorro/pulls{/number}","milestones_url":"https://api.github.com/repos/mozilla/socorro/milestones{/number}","notifications_url":"https://api.github.com/repos/mozilla/socorro/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mozilla/socorro/labels{/name}","releases_url":"https://api.github.com/repos/mozilla/socorro/releases{/id}","deployments_url":"https://api.github.com/repos/mozilla/socorro/deployments","created_at":"2011-08-24T19:21:49Z","updated_at":"2016-10-17T15:01:41Z","pushed_at":"2016-10-19T14:40:08Z","git_url":"git://github.com/mozilla/socorro.git","ssh_url":"git@github.com:mozilla/socorro.git","clone_url":"https://github.com/mozilla/socorro.git","svn_url":"https://github.com/mozilla/socorro","homepage":"https://wiki.mozilla.org/Socorro","size":178474,"stargazers_count":320,"watchers_count":320,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":164,"mirror_url":null,"open_issues_count":4,"forks":164,"open_issues":4,"watchers":320,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mozilla/socorro/pulls/3537"},"html":{"href":"https://github.com/mozilla/socorro/pull/3537"},"issue":{"href":"https://api.github.com/repos/mozilla/socorro/issues/3537"},"comments":{"href":"https://api.github.com/repos/mozilla/socorro/issues/3537/comments"},"review_comments":{"href":"https://api.github.com/repos/mozilla/socorro/pulls/3537/comments"},"review_comment":{"href":"https://api.github.com/repos/mozilla/socorro/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mozilla/socorro/pulls/3537/commits"},"statuses":{"href":"https://api.github.com/repos/mozilla/socorro/statuses/9ddcec5bbbc82620d4b948a9e29048bc79ea5929"}}}}
{"actor":{"display_login":"peterbe"}}