feat: redirect to release information at github (#3746)

* chore: remove unused import

* feat: redirect to release information at github.
This commit is contained in:
Robert Sparks 2022-03-24 15:38:33 -05:00 committed by GitHub
parent 32bf50ef1b
commit 79bcc6448e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 6 additions and 395 deletions

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2012-2020, All Rights Reserved
# Copyright The IETF Trust 2012-2022, All Rights Reserved
# -*- coding: utf-8 -*-
@ -12,14 +12,6 @@ from ietf.utils.test_utils import TestCase
class ReleasePagesTest(TestCase):
def test_release(self):
url = reverse('ietf.release.views.release', kwargs={'version':'6.0.0'})
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
releases = [ e.text.strip() for e in q('#content table td a') if e.text ]
for num in ["2.00", "3.00", "4.00", "5.0.0"]:
self.assertIn(num, releases)
def test_about(self):
url = reverse('ietf.release.views.release')+"about"
@ -29,17 +21,3 @@ class ReleasePagesTest(TestCase):
text = q('#content').text()
for word in ["About", "2.00", "3.00", "4.00", "5.0.0"]:
self.assertIn(word, text)
def test_stats(self):
url = reverse('ietf.release.views.stats')
r = self.client.get(url)
q = PyQuery(r.content)
# grab the script element text, split off the json data
s = q('#coverage-data').text()
self.assertIn("type: 'line',", s)
self.assertIn('"data": [[1426018457000, ', s)
s = q('#frequency-data').text()
self.assertIn("type: 'column',", s)
self.assertIn('"data": [[2007, 7], ', s)

View file

@ -1,16 +1,14 @@
# Copyright The IETF Trust 2015-2020, All Rights Reserved
# Copyright The IETF Trust 2015-2022, All Rights Reserved
# -*- coding: utf-8 -*-
from django.views.generic import TemplateView
from django.views.generic import RedirectView, TemplateView
from ietf.release import views
from ietf.utils.urls import url
urlpatterns = [
url(r'^$', views.release),
url(r'^(?P<version>[0-9.]+.*)/$', views.release),
url(r'^$', RedirectView.as_view(url='https://github.com/ietf-tools/datatracker/releases', permanent=False), name='ietf.release.views.release'),
url(r'^(?P<version>[0-9.]+.*)/$', RedirectView.as_view(url='https://github.com/ietf-tools/datatracker/releases/tag/%(version)s', permanent=False)),
url(r'^about/?$', TemplateView.as_view(template_name='release/about.html'), name='releaseabout'),
url(r'^stats/?$', views.stats),
url(r'^stats/?$', RedirectView.as_view(url='https://github.com/ietf-tools/datatracker/releases', permanent=False)),
]

View file

@ -1,156 +0,0 @@
# Copyright The IETF Trust 2012-2020, All Rights Reserved
# -*- coding: utf-8 -*-
import io
import os
import re
import json
import datetime
import gzip
from tzparse import tzparse
from calendar import timegm
from django.shortcuts import render
from django.conf import settings
from django.core.cache import cache
from django.http import HttpResponse
from django.utils.html import escape
from django.utils.safestring import mark_safe
import changelog
import debug # pyflakes:ignore
# workaround for thread import lock problem, http://bugs.python.org/issue7980
import time
time.strptime('1984', '%Y') # we do this to force lib loading, instead of it happening lazily when changelog calls tzparse later
def trac_links(text):
# changeset links
text = re.sub(r'\[(\d+)\]', r'<a href="https://trac.ietf.org/trac/ietfdb/changeset/\1">[\1]</a>', text)
# issue links
text = re.sub(r'([^&])#(\d+)', r'\1<a href="https://trac.ietf.org/trac/ietfdb/ticket/\2">#\2</a>', text)
return text
def get_coverage_data():
cache_key = 'release:get_coverage_data'
coverage_data = cache.get(cache_key)
if not coverage_data:
coverage_data = {}
if os.path.exists(settings.TEST_COVERAGE_MASTER_FILE):
if settings.TEST_COVERAGE_MASTER_FILE.endswith(".gz"):
with gzip.open(settings.TEST_COVERAGE_MASTER_FILE, "rb") as file:
coverage_data = json.load(file)
else:
with io.open(settings.TEST_COVERAGE_MASTER_FILE) as file:
coverage_data = json.load(file)
cache.set(cache_key, coverage_data, 60*60*24)
return coverage_data
def get_changelog_entries():
cache_key = 'release:get_changelog_entries'
log_entries = cache.get(cache_key)
if not log_entries:
if os.path.exists(settings.CHANGELOG_PATH):
log_entries = changelog.parse(settings.CHANGELOG_PATH)
cache.set(cache_key, log_entries, 60*60*24)
return log_entries
entries = None
log_entries = None
coverage_data = None
def release(request, version=None):
global entries, log_entries, coverage_data
if not entries:
log_entries = get_changelog_entries()
if not log_entries:
return HttpResponse("Error: changelog file %s not found" % settings.CHANGELOG_PATH)
next = None
for entry in log_entries:
if next:
next.prev = entry
entry.next = next
next = entry
entries = dict((entry.version, entry) for entry in log_entries)
if version == None or version not in entries:
version = log_entries[0].version
if not hasattr(entries[version], 'html'):
entries[version].html = trac_links(escape(entries[version].logentry.strip('\n')))
code_coverage_url = None
code_coverage_time = None
if os.path.exists(settings.TEST_CODE_COVERAGE_REPORT_FILE) and version == log_entries[0].version:
code_coverage_url = settings.TEST_CODE_COVERAGE_REPORT_URL
code_coverage_time = datetime.datetime.fromtimestamp(os.path.getmtime(settings.TEST_CODE_COVERAGE_REPORT_FILE))
coverage = {}
if not coverage_data:
coverage_data = get_coverage_data()
if version in coverage_data:
coverage = coverage_data[version]
for key in coverage:
if "coverage" in coverage[key]:
coverage[key]["percentage"] = coverage[key]["coverage"] * 100
return render(request, 'release/release.html',
{
'releases': log_entries,
'version': version,
'entry': entries[version],
'coverage': coverage,
'code_coverage_url': code_coverage_url,
'code_coverage_time': code_coverage_time,
} )
def stats(request):
coverage_chart_data = []
frequency_chart_data = []
coverage_data = get_coverage_data()
coverage_series_data = {}
for version in coverage_data:
if 'time' in coverage_data[version]:
t = coverage_data[version]['time']
secs = timegm(tzparse(t, "%Y-%m-%dT%H:%M:%SZ").timetuple()) * 1000
for coverage_type in coverage_data[version]:
if 'coverage' in coverage_data[version][coverage_type]:
cov = round(coverage_data[version][coverage_type]['coverage'], 3)
if not coverage_type in coverage_series_data:
coverage_series_data[coverage_type] = []
coverage_series_data[coverage_type].append([secs, cov])
for coverage_type in coverage_series_data:
coverage_series_data[coverage_type].sort()
# skip some early values
coverage_series_data[coverage_type] = coverage_series_data[coverage_type][2:]
coverage_chart_data.append({
'data': coverage_series_data[coverage_type],
'name': coverage_type,
})
log_entries = get_changelog_entries()
frequency = {}
frequency_series_data = []
for entry in log_entries:
year = entry.time.year
if not year in frequency:
frequency[year] = 0
frequency[year] += 1
for year in frequency:
frequency_series_data.append([year, frequency[year]])
frequency_series_data.sort()
frequency_chart_data.append({
'data': frequency_series_data,
'name': 'Releases',
})
return render(request, 'release/stats.html',
{
'coverage_chart_data': mark_safe(json.dumps(coverage_chart_data)),
'frequency_chart_data': mark_safe(json.dumps(frequency_chart_data)),
})

View file

@ -1,91 +0,0 @@
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% extends "base.html" %}
{% load origin textfilters ietf_filters %}
{% load cache %}
{% block title %}Release information{% endblock %}
{% block content %}
{% origin %}
<div class="row">
<h1 class="col-11">
<a class="text-reset text-decoration-none"
href="https://trac.ietf.org/trac/ietfdb/browser/tags/{{ entry.version }}">
Version {{ entry.version }}
</a>
<br>
<small class="text-muted">Released {{ entry.date }}</small>
</h1>
<div class="col-1 text-end">
<a href="{% url "ietf.release.views.stats" %}" class="icon-link">
<i class="bi bi-bar-chart-line"></i>
</a>
</div>
</div>
<ul class="pagination d-flex py-2">
<li class="me-auto page-item {% if not entry.prev %}disabled{% endif %}">
<a class="page-link"
href="{% if entry.prev %}/release/{{ entry.prev.version }}/{% else %}#{% endif %}">
<i class="bi bi-arrow-left"></i> Previous release
</a>
</li>
<li class="page-item {% if not entry.next %}disabled{% endif %}">
<a class="page-link"
href="{% if entry.next %}/release/{{ entry.next.version }}/{% else %}#{% endif %}">
Next release <i class="bi bi-arrow-right"></i>
</a>
</li>
</ul>
<p>
{% if coverage %}
Tested:
<b>Code</b>: {{ coverage.code.percentage|stringformat:".2f" }}%,
<b>Templates</b>: {{ coverage.template.percentage|stringformat:".2f" }}%,
<b>URLs</b>: {{ coverage.url.percentage|stringformat:".2f" }}%
{% endif %}
{% if code_coverage_url %}
(A
<a href="{{ code_coverage_url }}">code test coverage report</a>
dated {{ code_coverage_time }} is available.)
{% endif %}
</p>
<h2 class="mt-3">{{ entry.version }} release notes</h2>
{% if entry.title %}<h3 class="mt-3">{{ entry.title }}</h3>{% endif %}
<pre>{{ entry.html|linkify|urlize_ietf_docs }}</pre>
<div class="text-muted mt-1 ms-3">&mdash; {{ entry.author }} &lt;{{ entry.email|linkify }}&gt; {{ entry.date }}</div>
{% cache 3600 ietf_release_list %}
<div id="release-list"></div>
<h2 class="mt-3">Release list</h2>
<table class="table table-striped table-sm">
<thead>
<tr>
<th>Version</th>
<th>Release date</th>
<th>Feature summary</th>
</tr>
</thead>
<tbody>
{% for item in releases %}
{% ifchanged %}
<tr class="table-info">
<th></th>
<th class="text-end">{{ item.date|slice:"7:11" }}</th>
<th></th>
</tr>
{% endifchanged %}
<tr>
<td class="text-end">
<a href="/release/{{ item.version }}/">{{ item.version }}</a>
</td>
<td class="text-end">{{ item.date|slice:":11" }}</td>
<td>{{ item.title|linkify|urlize_ietf_docs }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endcache %}
{% endblock %}
{% block footer %}
<p class="text-center">
<a href="https://trac.ietf.org/trac/ietfdb/wiki/ContractorInstructions">Contractor instructions</a>
</p>
{{ block.super }}
{% endblock %}

View file

@ -1,117 +0,0 @@
{# Copyright The IETF Trust 2017, All Rights Reserved #}
{% extends "base.html" %}
{% load origin %}
{% load ietf_filters static django_bootstrap5 %}
{% block title %}Release Statistics{% endblock %}
{% block pagehead %}{% endblock %}
{% block content %}
{% origin %}
<h1>Release Statistics</h1>
<div id="coverage-chart"></div>
<script id="coverage-data">
var coverageChartConf = {
chart: {
type: 'line',
},
credits: {
enabled: false
},
exporting: {
fallbackToExportServer: false
},
legend: {
align: "right",
verticalAlign: "middle",
layout: "vertical",
enabled: true
},
plotOptions: {
line: {
marker: {
enabled: false
},
animation: false
}
},
title: {
text: 'Test coverage'
},
xAxis: {
type: 'datetime',
title: {
text: 'Release date'
},
},
units: [
[ 'day', [1]],
[ 'week', [1]],
[ 'month', [1, 3, 6]],
[ 'year', null ]
],
yAxis: {
min: 0,
title: {
text: 'Test coverage'
},
labels: {
formatter: function() {
return this.value*100+"%";
}
}
},
series: {{ coverage_chart_data }}
};
</script>
<div id="frequency-chart"></div>
<script id="frequency-data">
var frequencyChartConf = {
chart: {
type: 'column',
},
credits: {
enabled: false
},
exporting: {
fallbackToExportServer: false
},
legend: {
align: "right",
verticalAlign: "middle",
layout: "vertical",
enabled: true
},
plotOptions: {
column: {
animation: false
}
},
title: {
text: 'Releases per year'
},
xAxis: {
type: 'category',
title: {
text: 'Year'
},
},
yAxis: {
min: 0,
title: {
text: 'Number of releases'
}
},
series: {{ frequency_chart_data }}
};
</script>
{% endblock %}
{% block js %}
<script src="{% static 'ietf/js/highcharts-highcharts.js' %}"></script>
<script src="{% static 'ietf/js/highcharts-exporting.js' %}"></script>
<script src="{% static 'ietf/js/highcharts-offline-exporting.js' %}"></script>
<script>
$(document).ready(function () {
Highcharts.chart('coverage-chart', window.coverageChartConf);
Highcharts.chart('frequency-chart', window.frequencyChartConf);
});
</script>
{% endblock %}

View file

@ -5,7 +5,6 @@
import io
import os.path
import shutil
import sys
import types
from pyquery import PyQuery