[firefox] Add automation (#67)

Signed-off-by: Benji Visser <benji@093b.org>
This commit is contained in:
Benji Visser
2023-01-08 06:43:43 -05:00
committed by GitHub
parent b63aa7c317
commit f9597f55d7
2 changed files with 656 additions and 0 deletions

503
releases/firefox.json Normal file
View File

@@ -0,0 +1,503 @@
{
"108.0.2": "2023-01-05",
"108.0.1": "2022-12-16",
"108.0": "2022-12-13",
"102.6.0": "2022-12-13",
"107.0.1": "2022-11-29",
"107.0": "2022-11-15",
"102.5.0": "2022-11-15",
"106.0.5": "2022-11-04",
"106.0.4": "2022-11-03",
"106.0.3": "2022-10-31",
"106.0.2": "2022-10-26",
"106.0.1": "2022-10-20",
"106.0": "2022-10-18",
"102.4.0": "2022-10-18",
"105.0.3": "2022-10-07",
"105.0.2": "2022-10-04",
"105.0.1": "2022-09-23",
"105.0": "2022-09-20",
"102.3.0": "2022-09-20",
"104.0.2": "2022-09-06",
"104.0.1": "2022-08-30",
"91.13.0": "2022-08-23",
"104.0": "2022-08-23",
"102.2.0": "2022-08-23",
"103.0.2": "2022-08-09",
"103.0.1": "2022-08-01",
"91.12.0": "2022-07-26",
"103.0": "2022-07-26",
"102.1.0": "2022-07-26",
"102.0.1": "2022-07-06",
"91.11.0": "2022-06-28",
"102.0": "2022-06-28",
"101.0.1": "2022-06-09",
"91.10.0": "2022-05-31",
"101.0": "2022-05-31",
"91.9.1": "2022-05-20",
"100.0.2": "2022-05-20",
"100.0.1": "2022-05-16",
"91.9.0": "2022-05-03",
"100.0": "2022-05-03",
"99.0.1": "2022-04-12",
"99.0": "2022-04-05",
"91.8.0": "2022-04-05",
"98.0.2": "2022-03-23",
"98.0.1": "2022-03-14",
"91.7.1": "2022-03-14",
"98.0": "2022-03-08",
"91.7.0": "2022-03-08",
"97.0.2": "2022-03-05",
"91.6.1": "2022-03-05",
"97.0.1": "2022-02-17",
"97.0": "2022-02-08",
"91.6.0": "2022-02-08",
"96.0.3": "2022-01-27",
"91.5.1": "2022-01-27",
"96.0.2": "2022-01-20",
"96.0.1": "2022-01-14",
"96.0": "2022-01-11",
"91.5.0": "2022-01-11",
"95.0.2": "2021-12-19",
"95.0.1": "2021-12-16",
"91.4.1": "2021-12-16",
"95.0": "2021-12-07",
"91.4.0": "2021-12-07",
"94.0.2": "2021-11-22",
"94.0.1": "2021-11-04",
"94.0": "2021-11-02",
"91.3.0": "2021-11-02",
"93.0": "2021-10-05",
"91.2.0": "2021-10-05",
"78.15.0": "2021-10-05",
"92.0.1": "2021-09-23",
"92.0": "2021-09-07",
"91.1.0": "2021-09-07",
"78.14.0": "2021-09-07",
"91.0.2": "2021-08-24",
"91.0.1": "2021-08-17",
"91.0": "2021-08-10",
"78.13.0": "2021-08-10",
"90.0.2": "2021-07-22",
"90.0.1": "2021-07-19",
"90.0": "2021-07-13",
"78.12.0": "2021-07-13",
"89.0.2": "2021-06-23",
"89.0.1": "2021-06-17",
"89.0": "2021-06-01",
"78.11.0": "2021-06-01",
"88.0.1": "2021-05-05",
"78.10.1": "2021-05-04",
"88.0": "2021-04-19",
"78.10.0": "2021-04-19",
"87.0": "2021-03-23",
"78.9.0": "2021-03-23",
"86.0.1": "2021-03-11",
"86.0": "2021-02-23",
"78.8.0": "2021-02-23",
"85.0.2": "2021-02-09",
"85.0.1": "2021-02-05",
"78.7.1": "2021-02-05",
"85.0": "2021-01-26",
"78.7.0": "2021-01-26",
"84.0.2": "2021-01-06",
"78.6.1": "2021-01-06",
"84.0.1": "2020-12-22",
"84.0": "2020-12-15",
"78.6.0": "2020-12-15",
"83.0": "2020-11-17",
"78.5.0": "2020-11-17",
"82.0.3": "2020-11-10",
"78.4.1": "2020-11-10",
"82.0.2": "2020-10-28",
"82.0.1": "2020-10-27",
"82.0": "2020-10-20",
"78.4.0": "2020-10-20",
"81.0.2": "2020-10-13",
"81.0.1": "2020-10-01",
"78.3.1": "2020-10-01",
"81.0": "2020-09-22",
"78.3.0": "2020-09-22",
"80.0.1": "2020-09-01",
"80.0": "2020-08-25",
"78.2.0": "2020-08-25",
"68.12.0": "2020-08-25",
"79.0": "2020-07-28",
"78.1.0": "2020-07-28",
"68.11.0": "2020-07-28",
"78.0.2": "2020-07-09",
"78.0.1": "2020-07-01",
"78.0": "2020-06-30",
"68.10.0": "2020-06-30",
"77.0.1": "2020-06-03",
"77.0": "2020-06-02",
"68.9.0": "2020-06-02",
"76.0.1": "2020-05-08",
"76.0": "2020-05-05",
"68.8.0": "2020-05-05",
"75.0": "2020-04-07",
"68.7.0": "2020-04-07",
"74.0.1": "2020-04-03",
"68.6.1": "2020-04-03",
"74.0": "2020-03-10",
"68.6.0": "2020-03-10",
"73.0.1": "2020-02-18",
"73.0": "2020-02-11",
"68.5.0": "2020-02-11",
"72.0.2": "2020-01-20",
"68.4.2": "2020-01-20",
"72.0.1": "2020-01-08",
"68.4.1": "2020-01-08",
"72.0": "2020-01-07",
"68.4.0": "2020-01-07",
"71.0": "2019-12-03",
"68.3.0": "2019-12-03",
"70.0.1": "2019-10-31",
"70.0": "2019-10-22",
"68.2.0": "2019-10-22",
"69.0.3": "2019-10-10",
"69.0.2": "2019-10-03",
"69.0.1": "2019-09-18",
"69.0": "2019-09-03",
"68.1.0": "2019-09-03",
"60.9.0": "2019-09-03",
"68.0.2": "2019-08-14",
"68.0.1": "2019-07-18",
"68.0": "2019-07-09",
"60.8.0": "2019-07-09",
"67.0.4": "2019-06-20",
"60.7.2": "2019-06-20",
"67.0.3": "2019-06-18",
"60.7.1": "2019-06-18",
"67.0.2": "2019-06-11",
"67.0.1": "2019-06-04",
"67.0": "2019-05-21",
"60.7.0": "2019-05-21",
"60.6.3": "2019-05-08",
"66.0.5": "2019-05-07",
"66.0.4": "2019-05-05",
"60.6.2": "2019-05-05",
"66.0.3": "2019-04-10",
"66.0.2": "2019-03-27",
"66.0.1": "2019-03-22",
"60.6.1": "2019-03-22",
"66.0": "2019-03-19",
"60.6.0": "2019-03-19",
"65.0.2": "2019-02-28",
"60.5.2": "2019-02-22",
"65.0.1": "2019-02-12",
"60.5.1": "2019-02-12",
"65.0": "2019-01-29",
"60.5.0": "2019-01-29",
"64.0.2": "2019-01-09",
"64.0": "2018-12-11",
"60.4.0": "2018-12-11",
"63.0.3": "2018-11-15",
"63.0.1": "2018-10-31",
"63.0": "2018-10-23",
"60.3.0": "2018-10-23",
"62.0.3": "2018-10-02",
"60.2.2": "2018-10-02",
"62.0.2": "2018-09-21",
"60.2.1": "2018-09-21",
"62.0": "2018-09-05",
"60.2.0": "2018-09-05",
"61.0.2": "2018-08-08",
"61.0.1": "2018-07-05",
"61.0": "2018-06-26",
"60.1.0": "2018-06-26",
"52.9.0": "2018-06-26",
"60.0.2": "2018-06-06",
"52.8.1": "2018-06-06",
"60.0.1": "2018-05-16",
"60.0": "2018-05-09",
"52.8.0": "2018-05-09",
"59.0.3": "2018-04-30",
"52.7.4": "2018-04-30",
"59.0.2": "2018-03-26",
"52.7.3": "2018-03-26",
"59.0.1": "2018-03-16",
"52.7.2": "2018-03-16",
"52.7.1": "2018-03-14",
"59.0": "2018-03-13",
"52.7.0": "2018-03-13",
"58.0.2": "2018-02-07",
"58.0.1": "2018-01-29",
"58.0": "2018-01-23",
"52.6.0": "2018-01-23",
"57.0.4": "2018-01-04",
"57.0.3": "2017-12-28",
"52.5.3": "2017-12-28",
"57.0.2": "2017-12-07",
"52.5.2": "2017-12-07",
"57.0.1": "2017-11-29",
"57.0": "2017-11-14",
"52.5.0": "2017-11-14",
"56.0.2": "2017-10-26",
"56.0.1": "2017-10-09",
"52.4.1": "2017-10-09",
"56.0": "2017-09-28",
"52.4.0": "2017-09-28",
"55.0.3": "2017-08-25",
"55.0.2": "2017-08-16",
"55.0.1": "2017-08-10",
"55.0": "2017-08-08",
"52.3.0": "2017-08-08",
"54.0.1": "2017-06-29",
"52.2.1": "2017-06-29",
"54.0": "2017-06-13",
"52.2.0": "2017-06-13",
"53.0.3": "2017-05-19",
"52.1.2": "2017-05-19",
"53.0.2": "2017-05-05",
"52.1.1": "2017-05-05",
"53.0": "2017-04-19",
"52.1.0": "2017-04-19",
"45.9.0": "2017-04-19",
"52.0.2": "2017-03-28",
"52.0.1": "2017-03-17",
"52.0": "2017-03-07",
"45.8.0": "2017-03-07",
"51.0.1": "2017-01-26",
"51.0": "2017-01-24",
"45.7.0": "2017-01-24",
"50.1.0": "2016-12-13",
"45.6.0": "2016-12-13",
"50.0.2": "2016-11-30",
"45.5.1": "2016-11-30",
"50.0.1": "2016-11-28",
"50.0": "2016-11-15",
"45.5.0": "2016-11-15",
"47.0.2": "2016-11-01",
"49.0.2": "2016-10-20",
"49.0.1": "2016-09-23",
"49.0": "2016-09-20",
"45.4.0": "2016-09-20",
"48.0.2": "2016-08-24",
"48.0.1": "2016-08-18",
"48.0": "2016-08-02",
"45.3.0": "2016-08-02",
"47.0.1": "2016-06-28",
"47.0": "2016-06-07",
"45.2.0": "2016-06-07",
"46.0.1": "2016-05-03",
"45.1.1": "2016-05-03",
"46.0": "2016-04-26",
"38.8.0": "2016-04-26",
"45.0.2": "2016-04-11",
"45.0.1": "2016-03-16",
"38.7.1": "2016-03-16",
"45.0": "2016-03-08",
"38.7.0": "2016-03-08",
"44.0.2": "2016-02-11",
"38.6.1": "2016-02-11",
"44.0.1": "2016-02-08",
"44.0": "2016-01-26",
"38.6.0": "2016-01-26",
"43.0.4": "2016-01-06",
"43.0.3": "2015-12-28",
"43.0.2": "2015-12-22",
"38.5.2": "2015-12-22",
"38.5.1": "2015-12-21",
"43.0.1": "2015-12-18",
"43.0": "2015-12-15",
"38.5.0": "2015-12-15",
"42.0": "2015-11-03",
"38.4.0": "2015-11-03",
"41.0.2": "2015-10-15",
"41.0.1": "2015-09-30",
"41.0": "2015-09-22",
"38.3.0": "2015-09-22",
"40.0.3": "2015-08-27",
"38.2.1": "2015-08-27",
"40.0.2": "2015-08-13",
"40.0": "2015-08-11",
"38.2.0": "2015-08-11",
"39.0.3": "2015-08-06",
"38.1.1": "2015-08-06",
"39.0": "2015-07-02",
"38.1.0": "2015-07-02",
"31.8.0": "2015-07-02",
"38.0.5": "2015-06-02",
"38.0.1": "2015-05-14",
"38.0": "2015-05-12",
"31.7.0": "2015-05-12",
"37.0.2": "2015-04-20",
"37.0.1": "2015-04-03",
"37.0": "2015-03-31",
"31.6.0": "2015-03-31",
"36.0.4": "2015-03-21",
"31.5.3": "2015-03-21",
"36.0.3": "2015-03-20",
"31.5.2": "2015-03-20",
"36.0.1": "2015-03-05",
"36.0": "2015-02-24",
"31.5.0": "2015-02-24",
"35.0.1": "2015-01-26",
"35.0": "2015-01-13",
"31.4.0": "2015-01-13",
"34.0.5": "2014-12-01",
"34.0": "2014-12-01",
"31.3.0": "2014-12-01",
"33.1.1": "2014-11-14",
"33.1": "2014-11-10",
"33.0.3": "2014-11-06",
"33.0.2": "2014-10-28",
"33.0.1": "2014-10-24",
"31.2.0": "2014-10-14",
"33.0": "2014-10-13",
"32.0.3": "2014-09-24",
"24.8.1": "2014-09-24",
"31.1.1": "2014-09-23",
"32.0.2": "2014-09-18",
"32.0.1": "2014-09-12",
"32.0": "2014-09-02",
"24.8.0": "2014-09-02",
"31.1.0": "2014-09-01",
"31.0": "2014-07-22",
"24.7.0": "2014-07-22",
"30.0": "2014-06-10",
"24.6.0": "2014-06-10",
"29.0.1": "2014-05-09",
"29.0": "2014-04-29",
"24.5.0": "2014-04-29",
"28.0": "2014-03-18",
"24.4.0": "2014-03-18",
"27.0.1": "2014-02-13",
"27.0": "2014-02-04",
"24.3.0": "2014-02-04",
"26.0": "2013-12-10",
"24.2.0": "2013-12-10",
"25.0.1": "2013-11-15",
"24.1.1": "2013-11-15",
"17.0.11": "2013-11-15",
"25.0": "2013-10-29",
"24.1.0": "2013-10-29",
"17.0.10": "2013-10-29",
"24.0": "2013-09-17",
"17.0.9": "2013-09-17",
"23.0.1": "2013-08-16",
"23.0": "2013-08-06",
"17.0.8": "2013-08-06",
"22.0": "2013-06-25",
"17.0.7": "2013-06-25",
"21.0": "2013-05-14",
"17.0.6": "2013-05-14",
"20.0.1": "2013-04-11",
"20.0": "2013-04-02",
"17.0.5": "2013-04-02",
"19.0.2": "2013-03-07",
"17.0.4": "2013-03-07",
"19.0.1": "2013-02-27",
"19.0": "2013-02-19",
"17.0.3": "2013-02-19",
"18.0.2": "2013-02-05",
"18.0.1": "2013-01-18",
"18.0": "2013-01-08",
"17.0.2": "2013-01-08",
"10.0.12": "2013-01-08",
"17.0.1": "2012-11-30",
"17.0": "2012-11-20",
"10.0.11": "2012-11-20",
"16.0.2": "2012-10-26",
"10.0.10": "2012-10-26",
"10.0.9": "2012-10-12",
"16.0.1": "2012-10-11",
"16.0": "2012-10-09",
"10.0.8": "2012-10-09",
"15.0.1": "2012-09-06",
"15.0": "2012-08-28",
"10.0.7": "2012-08-28",
"14.0.1": "2012-07-17",
"10.0.6": "2012-07-17",
"13.0.1": "2012-06-15",
"13.0": "2012-06-05",
"10.0.5": "2012-06-05",
"12.0": "2012-04-24",
"10.0.4": "2012-04-24",
"3.6.28": "2012-03-13",
"11.0": "2012-03-13",
"10.0.3": "2012-03-13",
"3.6.27": "2012-02-17",
"10.0.2": "2012-02-16",
"10.0.1": "2012-02-10",
"3.6.26": "2012-01-31",
"10.0": "2012-01-31",
"9.0.1": "2011-12-21",
"9.0": "2011-12-20",
"3.6.25": "2011-12-20",
"8.0.1": "2011-11-21",
"8.0": "2011-11-08",
"3.6.24": "2011-11-08",
"7.0.1": "2011-09-29",
"7.0": "2011-09-27",
"3.6.23": "2011-09-27",
"6.0.2": "2011-09-06",
"3.6.22": "2011-09-06",
"6.0.1": "2011-08-30",
"3.6.21": "2011-08-30",
"6.0": "2011-08-16",
"3.6.20": "2011-08-16",
"5.0.1": "2011-07-11",
"3.6.19": "2011-07-11",
"5.0": "2011-06-21",
"3.6.18": "2011-06-21",
"4.0.1": "2011-04-28",
"3.6.17": "2011-04-28",
"3.5.19": "2011-04-28",
"4.0": "2011-03-22",
"3.6.16": "2011-03-22",
"3.5.18": "2011-03-22",
"3.6.15": "2011-03-04",
"3.6.14": "2011-03-01",
"3.5.17": "2011-03-01",
"3.6.13": "2010-12-09",
"3.5.16": "2010-12-09",
"3.6.12": "2010-10-27",
"3.5.15": "2010-10-27",
"3.6.11": "2010-10-19",
"3.5.14": "2010-10-19",
"3.6.10": "2010-09-15",
"3.5.13": "2010-09-15",
"3.6.9": "2010-09-07",
"3.5.12": "2010-09-07",
"3.6.8": "2010-07-23",
"3.6.7": "2010-07-20",
"3.5.11": "2010-07-20",
"3.6.6": "2010-06-26",
"3.6.4": "2010-06-22",
"3.5.10": "2010-06-22",
"3.6.3": "2010-04-01",
"3.5.9": "2010-03-30",
"3.0.19": "2010-03-30",
"3.6.2": "2010-03-22",
"3.5.8": "2010-02-17",
"3.0.18": "2010-02-17",
"3.6": "2010-01-21",
"3.5.7": "2010-01-05",
"3.0.17": "2010-01-05",
"3.5.6": "2009-12-15",
"3.0.16": "2009-12-15",
"3.5.5": "2009-11-05",
"3.5.4": "2009-10-27",
"3.0.15": "2009-10-27",
"3.5.3": "2009-09-09",
"3.0.14": "2009-09-09",
"3.5.2": "2009-08-03",
"3.0.13": "2009-08-03",
"3.0.12": "2009-07-21",
"3.5.1": "2009-07-16",
"3.5": "2009-06-30",
"3.0.11": "2009-06-11",
"3.0.10": "2009-04-27",
"3.0.9": "2009-04-21",
"3.0.8": "2009-03-27",
"3.0.7": "2009-03-04",
"3.0.6": "2009-02-03",
"3.0.5": "2008-12-16",
"3.0.4": "2008-11-12",
"3.0.3": "2008-09-26",
"3.0.2": "2008-09-23",
"3.0.1": "2008-07-16",
"3.0": "2008-06-17"
}

153
src/firefox.py Normal file
View File

@@ -0,0 +1,153 @@
import json
from typing import Tuple
from datetime import datetime
import re
import requests
import urllib.request
from bs4 import BeautifulSoup
import concurrent.futures
"""Fetch Firefox versions with their dates from https://www.mozilla.org/en-US/firefox/releases/"""
URL = "https://www.mozilla.org/en-US/firefox/releases/"
PRODUCT = "firefox"
DATE_REGEX = r"(January|Jan|February|Feb|March|Mar|April|Apr|May|June|Jun|July|Jul|August|Aug|September|Sept|October|Oct|November|Nov|December|Dec)\s+\d{1,2}(st|nd|rd|th)?,\s+\d{4}"
VERSION_REGEX = r"\d+(\.\d+)*"
class UnsupportedReleasePageError(Exception):
"Raised when a firefox release page is not supported"
pass
class InvalidPageVariantError(Exception):
"Raised when an invalid variant is passed to get_version_and_date"
pass
def format_date(unformatted_date: str) -> str:
""" Format date from July 11, 2002 to 2002-07-11 """
date = re.sub(r'(\d)(st|nd|rd|th)', r'\1', unformatted_date)
formats = ["%b %d, %Y", "%B %d, %Y"]
for f in formats:
try:
return datetime.strptime(date, f).strftime("%Y-%m-%d")
except ValueError:
pass
return ""
def get_version_and_date_varant_1(soup: BeautifulSoup) -> Tuple[str, str]:
""" Version matching for firefox versions >= 28.0 (usually) """
# get version
version = soup.find("div", class_="c-release-version").get_text()
# get date
unformatted_date = soup.find("p", class_="c-release-date").get_text()
date = format_date(unformatted_date)
return (version, date)
def get_version_and_date_variant_2(soup: BeautifulSoup) -> Tuple[str, str]:
""" Version matching for firefox versions >= 10.0 (usually) """
release_info = soup.find("h2").find("small").text
# get version
version_match = re.search(VERSION_REGEX, soup.select('div#nav-access a')[0].get("href"))
if version_match is None:
raise InvalidPageVariantError("Unable to find version")
version = version_match.group()
# get date
unformatted_date_match = re.search(DATE_REGEX, release_info)
if unformatted_date_match is None:
raise InvalidPageVariantError("Unable to find date")
unformatted_date = unformatted_date_match.group()
date = format_date(unformatted_date)
return (version, date)
def get_version_and_date_variant_3(soup: BeautifulSoup) -> Tuple[str, str]:
""" Version matching for firefox versions >= 3.0 (usually) """
release_info = soup.select('div#main-feature p em')[0].get_text()
# get version
version_match = re.search(VERSION_REGEX, release_info)
if version_match is None:
raise InvalidPageVariantError("Unable to find version")
version = version_match.group()
# get date
unformatted_date_match = re.search(DATE_REGEX, release_info)
if unformatted_date_match is None:
raise InvalidPageVariantError("Unable to find date")
unformatted_date = unformatted_date_match.group()
date = format_date(unformatted_date)
return (version, date)
def get_version_and_date(release_page: str, release_version: str) -> Tuple[str, str]:
""" Get version and date from the given release page """
major = int(release_version.split(".")[0])
# firefox release pages for versions <3.0 don't include release dates so we
# can't match these versions for now.
# example: https://www.mozilla.org/en-US/firefox/2.0/releasenotes/
if major < 3:
raise UnsupportedReleasePageError("Unsupported release page: %s" % release_page)
# Firefox release pages come in 3 different variants. Unforunately, there is no
# consistent way to determine which variant a page is (say, by version number), so
# we have to try each variant until we find one that works.
functions = [get_version_and_date_varant_1, get_version_and_date_variant_2, get_version_and_date_variant_3]
soup = make_bs_request(release_page)
for function in functions:
try:
return function(soup)
except (InvalidPageVariantError, AttributeError, IndexError):
pass
raise UnsupportedReleasePageError("Unable to find version and date for %s" % release_page)
def make_bs_request(url: str) -> BeautifulSoup:
""" Make a request to the given url and return a BeautifulSoup object """
headers = {"user-agent": "mozilla"}
req = urllib.request.Request(url, headers=headers)
res = urllib.request.urlopen(req, timeout=5)
return BeautifulSoup(res.read(), features="html5lib")
def fetch_releases():
releases = {}
soup = make_bs_request(URL)
ff_releases = soup.find_all("ol", class_="c-release-list")
with concurrent.futures.ThreadPoolExecutor() as executor:
future_to_url = {
executor.submit(
get_version_and_date,
requests.compat.urljoin(URL, p.get("href")),
p.get_text()): p.get("href") for p in ff_releases[0].find_all("a")
}
for future in concurrent.futures.as_completed(future_to_url):
try:
(version, date) = future.result()
print("%s: %s" % (version, date))
releases[version] = date
except UnsupportedReleasePageError:
print("Unsupported release page: %s" % future_to_url[future])
return releases
def main():
print(f"::group::{PRODUCT}")
releases = fetch_releases()
with open(f"releases/{PRODUCT}.json", "w") as f:
f.write(json.dumps(dict(
# sort by date then version (desc)
sorted(releases.items(), key=lambda x: (x[1], x[0]), reverse=True)
), indent=2))
print("::endgroup::")
if __name__ == '__main__':
main()