add script with support parsing releases from git

pull/5919/head
Martin Gano 2020-08-06 16:58:47 +02:00 zatwierdzone przez martin.gano
rodzic 5db977c512
commit 9e099f97d9
4 zmienionych plików z 363 dodań i 0 usunięć

BIN
docs/chart.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 62 KiB

Wyświetl plik

@ -70,6 +70,8 @@ As a general guideline:
- If possible, periodically update the project to a new major or minor ESP-IDF version (for example, once a year.) The update process should be straightforward for Minor updates, but may require some planning and checking of the release notes for Major updates.
- Always plan to update to a newer release before the release you are using becomes End of Life.
.. image:: ../chart.png
Checking the Current Version
----------------------------

265
generate_chart.py 100644
Wyświetl plik

@ -0,0 +1,265 @@
#!/usr/bin/env python
import datetime as dt
import requests
import json
import os
import re
import matplotlib.dates
import matplotlib.font_manager as font_manager
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
import numpy as np
from dateutil import parser
from dateutil.relativedelta import relativedelta
from matplotlib.dates import WEEKLY, DateFormatter, RRuleLocator, rrulewrapper
class Version(object):
def __init__(self, version_name,
explicit_start_date=None,
explicit_end_date=None,
explicit_end_service_date=None,
is_lts=None):
self.version_name = version_name
self.is_lts = is_lts or self.is_version_lts()
self.is_major_minor = Version.is_minor_major_version(self.version_name)
self._start_date = parser.parse(
explicit_start_date) if explicit_start_date is not None else self._retrieve_start_date()
self._end_of_life_date = parser.parse(
explicit_end_date) if explicit_end_date is not None else self._retrieve_end_of_life_date()
self._end_service_date = parser.parse(
explicit_end_service_date) if explicit_end_service_date is not None else self.get_end_service_date()
self.start_date_matplotlib_format = matplotlib.dates.date2num(self._start_date)
self.end_of_life_date_matplotlib_format = matplotlib.dates.date2num(self._end_of_life_date)
self.end_service_date_matplotlib_format = matplotlib.dates.date2num(
self._end_service_date) if self._end_service_date is not None else None
@staticmethod
def get_config(config_path):
return json.load(open(config_path))
@staticmethod
def add_months(source_date, months):
return source_date + relativedelta(months=+months)
@staticmethod
def is_minor_major_version(version_name):
return True if len(version_name.split(".")) <= 2 else False
def is_version_lts(self):
version = self.version_name
return version >= 'v4.1'
def get_start_date(self):
return self._start_date
def get_end_of_life_date(self):
return self._end_of_life_date
def _retrieve_start_date(self):
return parser.parse(os.popen("git log -1 --format=%ai " + self.version_name))
def _retrieve_end_of_life_date(self):
return self.add_months(self._start_date, 30 if self.is_lts else 18)
def get_end_service_date(self):
return self.add_months(self._start_date, 12)
class ChartVersions(object):
def __init__(self):
self.all_versions = self.get_all_versions_from_git()
self._releases = self._get_releases_from_url(url="https://dl.espressif.com/dl/esp-idf/idf_versions.js")
self._patches = self._get_patches_from_url(url="https://dl.espressif.com/dl/esp-idf/idf_versions.js")
self.sorted_releases_supported = sorted(self.filter_old_versions(self._releases), key=lambda x: x.version_name)
self.patches_supported = self.filter_old_versions(self._patches)
# TODO test higher versions
# self.sorted_releases_supported.append(Version(version_name='v4.1', explicit_start_date="28-9-2020"))
# self.sorted_releases_supported.append(Version(version_name='v4.2', explicit_start_date="28-5-2021"))
def get_releases_as_json(self):
return {
x.version_name: {
"start_date": x.get_start_date().strftime("%Y-%m-%d"),
"end_date": x.get_end_of_life_date().strftime("%Y-%m-%d"),
"is_lts": x.is_lts
} for x in self.sorted_releases_supported + self.patches_supported
}
@staticmethod
def parse_chart_releases_from_js(js_as_string):
return json.loads(js_as_string[js_as_string.find("RELEASES: ") + len("RELEASES: "):js_as_string.rfind("};")])
def _get_all_version_from_url(self, url=None, filename=None):
releases_file = requests.get(url).text if url is not None else "".join(open(filename).readlines())
return self.parse_chart_releases_from_js(releases_file)
def _get_releases_from_url(self, url=None, filename=None):
all_versions = self._get_all_version_from_url(url, filename)
return [
Version(version_name=x,
explicit_start_date=all_versions[x]['start_date'],
explicit_end_date=all_versions[x]['end_date'] if 'end_date' in all_versions[x].keys() else None,
explicit_end_service_date=all_versions[x]['end_service'] if 'end_service' in all_versions[x].keys() else None)
for x in all_versions.keys() if Version.is_minor_major_version(x)
]
def _get_patches_from_url(self, url=None, filename=None):
all_versions = self._get_all_version_from_url(url, filename)
return [
Version(version_name=x,
explicit_start_date=all_versions[x]['start_date'],
explicit_end_date=all_versions[x]['end_date'] if 'end_date' in all_versions[x].keys() else None,
is_lts=all_versions[x]['new_policy'] if 'new_policy' in all_versions[x].keys() else None)
for x in all_versions.keys() if not Version.is_minor_major_version(x)
]
def _get_releases(self, all_versions):
return [Version(release) for release in self._get_releases_names(all_versions)]
def _get_patches(self, all_versions):
return [Version(patch, explicit_end_date=self.get_super_end_date_as_string(patch),
is_lts=self.get_super_lts_state(patch)) for patch in self._get_patches_names(all_versions)]
@staticmethod
def _get_releases_names(all_versions):
return list(filter(lambda x: Version.is_minor_major_version(x), all_versions))
@staticmethod
def _get_patches_names(all_versions):
return list(filter(lambda x: not Version.is_minor_major_version(x), all_versions))
def get_super_version(self, patch):
return list(filter(lambda x: x.version_name == self.get_super_version_name(patch), self._releases))[0]
def get_super_end_date_as_string(self, patch):
return self.get_super_version(patch).get_end_of_life_date().strftime("%m/%d/%Y, %H:%M:%S")
def get_super_lts_state(self, patch):
return self.get_super_version(patch).is_lts
@staticmethod
def get_all_versions_from_git():
"""
:returns: list of string variables meaning name of the versions or patches (e.g. v4.1, v3.3.1, etc.)
"""
all_git_tags = os.popen("git tag")
stable_releases_regex = "(?:^|)(v\d+\.\d+(?:\.\d+){0,1})(?=\n|$)"
results = [re.match(stable_releases_regex, line) for line in all_git_tags]
all_versions = [regex_result.group(1) for regex_result in results if regex_result is not None]
return all_versions
@staticmethod
def filter_old_versions(versions):
return list(
filter(lambda x: x.get_end_of_life_date() >= dt.datetime.now(x.get_end_of_life_date().tzinfo), versions))
@staticmethod
def get_super_version_name(version_name):
return ".".join(version_name.split(".")[:2])
def create_chart(self,
figure_size=(20, 8),
subplot=111,
step_size=0.5,
bar_height=0.3,
version_alpha=0.8,
patch_width=1,
lts_service_color='darkred',
lts_maintenance_color='red',
bar_align='center',
patch_color='black',
patch_alpha=1,
date_interval=10,
output_chart_name='docs/chart',
output_chart_extension='.png',
months_surrounding_chart=5):
fig = plt.figure(figsize=figure_size)
ax = fig.add_subplot(subplot)
labels_count = len(self.sorted_releases_supported)
pos = np.arange(step_size, labels_count * step_size + step_size, step_size)
mapping_releases_index = {release.version_name: i for release, i in
zip(self.sorted_releases_supported, range(labels_count))}
for release, i in zip(self.sorted_releases_supported, range(labels_count)):
start_date = release.start_date_matplotlib_format
end_of_service_date = release.end_service_date_matplotlib_format
end_date = release.end_of_life_date_matplotlib_format
ax.barh((i * step_size) + step_size, (end_of_service_date or end_date) - start_date, left=start_date,
height=bar_height, align=bar_align,
color=lts_service_color,
alpha=version_alpha,
edgecolor=lts_service_color)
if end_of_service_date is not None:
ax.barh((i * step_size) + step_size, end_date - end_of_service_date, left=end_of_service_date,
height=bar_height, align=bar_align,
color=lts_maintenance_color, alpha=version_alpha, edgecolor=lts_maintenance_color)
for patch, i in zip(self.patches_supported, range(len(self.patches_supported))):
start_date = patch.start_date_matplotlib_format
ax.barh(mapping_releases_index[self.get_super_version_name(patch.version_name)] * step_size + step_size,
patch_width, left=start_date, height=bar_height, align=bar_align, color=patch_color,
alpha=patch_alpha,
edgecolor=patch_color)
ax.text(start_date - 5, mapping_releases_index[
self.get_super_version_name(patch.version_name)] * step_size + step_size - 0.2,
patch.version_name.split('.')[-1],
fontsize='xx-small', color='darkred')
plt.setp(plt.yticks(pos, map(lambda x: x.version_name, self.sorted_releases_supported))[1], fontsize=14)
ax.set_ylim(bottom=0, ymax=labels_count * step_size + step_size)
ax.set_xlim(
xmin=Version.add_months(
min(self.sorted_releases_supported,
key=lambda version: version.get_start_date().replace(tzinfo=None)).get_start_date(),
-months_surrounding_chart),
xmax=Version.add_months(
max(self.sorted_releases_supported,
key=lambda version: version.get_end_of_life_date().replace(tzinfo=None)).get_end_of_life_date(),
months_surrounding_chart))
ax.grid(color='g', linestyle=':')
ax.xaxis_date()
rule = rrulewrapper(WEEKLY, interval=date_interval)
loc = RRuleLocator(rule)
formatter = DateFormatter("%d-%b '%y")
ax.xaxis.set_major_locator(loc)
ax.xaxis.set_major_formatter(formatter)
x_labels = ax.get_xticklabels()
plt.setp(x_labels, rotation=30, fontsize=10)
ax.legend(loc=1, prop=font_manager.FontProperties(size='small'))
ax.invert_yaxis()
fig.autofmt_xdate()
darkred_patch = mpatches.Patch(color='darkred', label='Service period (Recommended for new designs)')
red_patch = mpatches.Patch(color='red', label='Maintenance period')
plt.legend(handles=[darkred_patch, red_patch], prop={'size': 6})
fig.set_size_inches(10, 5, forward=True)
plt.savefig(output_chart_name + output_chart_extension)
plt.show()
if __name__ == '__main__':
ChartVersions().create_chart()

96
idf_versions.js 100644
Wyświetl plik

@ -0,0 +1,96 @@
var DOCUMENTATION_VERSIONS = {
DEFAULTS: {
has_targets: false,
supported_targets: ["esp32"]
},
VERSIONS: [{
name: "latest",
has_targets: true,
supported_targets: ["esp32", "esp32s2"]
},
{
name: "v4.1-rc",
pre_release: true
},
{
name: "v4.0.1",
old: false
},
{
name: "v4.0",
old: true
},
{
name: "v3.3.2"
},
{
name: "v3.3.1",
old: true
},
{
name: "v3.3",
old: true
},
{
name: "v3.2.3",
old: false
},
{
name: "v3.1.7",
old: false
},
{
name: "v3.1.6",
old: true
},
{
name: "v3.0.9",
old: true
},
{
name: "release-v4.2",
pre_release: true,
has_targets: true,
supported_targets: ["esp32", "esp32s2"]
},
{
name: "release-v4.1",
pre_release: true
},
{
name: "release-v4.0",
pre_release: true
},
{
name: "release-v3.3",
pre_release: true
},
{
name: "release-v3.2",
pre_release: true
},
{
name: "release-v3.1",
pre_release: true
}
],
RELEASES: {
"v3.1": {
"start_date": "2018-09-07",
"end_date": "2020-10-31"
},
"v3.2": {
"start_date": "2019-04-11",
"end_date": "2020-10-31"
},
"v3.3": {
"start_date": "2019-09-05",
"end_date": "2022-03-31"
},
"v4.0": {
"start_date": "2020-02-11",
"end_service": "2021-02-11",
"end_date": "2021-10-31"
}
}
};