mirror of
git://git.yoctoproject.org/layerindex-web.git
synced 2025-07-19 20:59:01 +02:00
RRS: support grouping upgrades by version for multi-version recipes
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
This commit is contained in:
parent
ecb053472b
commit
51d7f139f8
|
@ -15,7 +15,8 @@ from django.core.exceptions import ValidationError
|
||||||
from rrs.models import Release, Milestone, Maintainer, RecipeMaintainerHistory, \
|
from rrs.models import Release, Milestone, Maintainer, RecipeMaintainerHistory, \
|
||||||
RecipeMaintainer, RecipeDistro, RecipeUpgrade, RecipeUpstream, \
|
RecipeMaintainer, RecipeDistro, RecipeUpgrade, RecipeUpstream, \
|
||||||
RecipeUpstreamHistory, MaintenancePlan, MaintenancePlanLayerBranch, \
|
RecipeUpstreamHistory, MaintenancePlan, MaintenancePlanLayerBranch, \
|
||||||
RecipeMaintenanceLink, RecipeSymbol
|
RecipeMaintenanceLink, RecipeSymbol, RecipeUpgradeGroupRule, \
|
||||||
|
RecipeUpgradeGroup
|
||||||
|
|
||||||
class MaintenancePlanLayerBranchFormSet(BaseInlineFormSet):
|
class MaintenancePlanLayerBranchFormSet(BaseInlineFormSet):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -210,3 +211,5 @@ admin.site.register(RecipeUpstreamHistory, RecipeUpstreamHistoryAdmin)
|
||||||
admin.site.register(RecipeUpstream, RecipeUpstreamAdmin)
|
admin.site.register(RecipeUpstream, RecipeUpstreamAdmin)
|
||||||
admin.site.register(RecipeMaintenanceLink, RecipeMaintenanceLinkAdmin)
|
admin.site.register(RecipeMaintenanceLink, RecipeMaintenanceLinkAdmin)
|
||||||
admin.site.register(RecipeSymbol, RecipeSymbolAdmin)
|
admin.site.register(RecipeSymbol, RecipeSymbolAdmin)
|
||||||
|
admin.site.register(RecipeUpgradeGroupRule)
|
||||||
|
admin.site.register(RecipeUpgradeGroup)
|
||||||
|
|
39
rrs/migrations/0026_recipeupgrade_grouping.py
Normal file
39
rrs/migrations/0026_recipeupgrade_grouping.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.22 on 2019-08-19 00:56
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('layerindex', '0041_recipe_configopts'),
|
||||||
|
('rrs', '0025_recipeupgrade_move'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='RecipeUpgradeGroup',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('title', models.CharField(help_text='Group title', max_length=100)),
|
||||||
|
('recipesymbol', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rrs.RecipeSymbol')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='RecipeUpgradeGroupRule',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('pn', models.CharField(help_text='Regular expression to match recipe to apply to', max_length=100)),
|
||||||
|
('version', models.CharField(help_text='Regular expression to split version component on', max_length=100)),
|
||||||
|
('layerbranch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='layerindex.LayerBranch')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='recipeupgrade',
|
||||||
|
name='group',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='rrs.RecipeUpgradeGroup'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import os.path
|
import re
|
||||||
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '../')))
|
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '../')))
|
||||||
|
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
|
@ -429,6 +429,38 @@ class RecipeDistro(models.Model):
|
||||||
return recipe_distros
|
return recipe_distros
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeUpgradeGroup(models.Model):
|
||||||
|
recipesymbol = models.ForeignKey(RecipeSymbol)
|
||||||
|
title = models.CharField(max_length=100, help_text='Group title')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '%s: %s' % (self.recipesymbol, self.title)
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeUpgradeGroupRule(models.Model):
|
||||||
|
layerbranch = models.ForeignKey(LayerBranch)
|
||||||
|
pn = models.CharField(max_length=100, help_text='Regular expression to match recipe to apply to')
|
||||||
|
version = models.CharField(max_length=100, help_text='Regular expression to split version component on')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def group_for_params(recipesymbol, version):
|
||||||
|
for rule in RecipeUpgradeGroupRule.objects.filter(layerbranch=recipesymbol.layerbranch):
|
||||||
|
if re.match(rule.pn, recipesymbol.pn):
|
||||||
|
res = re.match(rule.version, version)
|
||||||
|
if res:
|
||||||
|
if res.groups():
|
||||||
|
match = res.groups()[0]
|
||||||
|
else:
|
||||||
|
match = res.string[res.start(0):res.end(0)]
|
||||||
|
group, _ = RecipeUpgradeGroup.objects.get_or_create(recipesymbol=recipesymbol, title=match)
|
||||||
|
group.save()
|
||||||
|
return group
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '%s: %s' % (self.layerbranch, self.pn)
|
||||||
|
|
||||||
|
|
||||||
class RecipeUpgrade(models.Model):
|
class RecipeUpgrade(models.Model):
|
||||||
UPGRADE_TYPE_CHOICES = (
|
UPGRADE_TYPE_CHOICES = (
|
||||||
('U', 'Upgrade'),
|
('U', 'Upgrade'),
|
||||||
|
@ -448,6 +480,7 @@ class RecipeUpgrade(models.Model):
|
||||||
upgrade_type = models.CharField(max_length=1, choices=UPGRADE_TYPE_CHOICES, default='U', db_index=True)
|
upgrade_type = models.CharField(max_length=1, choices=UPGRADE_TYPE_CHOICES, default='U', db_index=True)
|
||||||
filepath = models.CharField(max_length=512, blank=True)
|
filepath = models.CharField(max_length=512, blank=True)
|
||||||
orig_filepath = models.CharField(max_length=512, blank=True)
|
orig_filepath = models.CharField(max_length=512, blank=True)
|
||||||
|
group = models.ForeignKey(RecipeUpgradeGroup, blank=True, null=True, on_delete=models.SET_NULL)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_by_recipe_and_date(recipe, end_date):
|
def get_by_recipe_and_date(recipe, end_date):
|
||||||
|
@ -462,6 +495,14 @@ class RecipeUpgrade(models.Model):
|
||||||
def commit_url(self):
|
def commit_url(self):
|
||||||
return self.recipesymbol.layerbranch.commit_url(self.sha1)
|
return self.recipesymbol.layerbranch.commit_url(self.sha1)
|
||||||
|
|
||||||
|
def regroup(self):
|
||||||
|
group = RecipeUpgradeGroupRule.group_for_params(self.recipesymbol, self.version)
|
||||||
|
if group != self.group:
|
||||||
|
self.group = group
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self.upgrade_type == 'R':
|
if self.upgrade_type == 'R':
|
||||||
return '%s: deleted [final] (%s)' % (self.recipesymbol.pn,
|
return '%s: deleted [final] (%s)' % (self.recipesymbol.pn,
|
||||||
|
|
|
@ -86,7 +86,7 @@ def run_internal(maintplanlayerbranch, commit, commitdate, options, logger, bitb
|
||||||
Upgrade history handler.
|
Upgrade history handler.
|
||||||
"""
|
"""
|
||||||
def upgrade_history(options, logger):
|
def upgrade_history(options, logger):
|
||||||
from rrs.models import MaintenancePlan, RecipeUpgrade, Release, Milestone
|
from rrs.models import MaintenancePlan, RecipeUpgrade, Release, Milestone, RecipeUpgradeGroupRule
|
||||||
|
|
||||||
logger.debug('=== BEGIN; cmdline: %s' % (' '.join(sys.argv)))
|
logger.debug('=== BEGIN; cmdline: %s' % (' '.join(sys.argv)))
|
||||||
|
|
||||||
|
@ -101,6 +101,16 @@ def upgrade_history(options, logger):
|
||||||
logger.error('No enabled maintenance plans found')
|
logger.error('No enabled maintenance plans found')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
if options.regroup:
|
||||||
|
for maintplan in maintplans:
|
||||||
|
for maintplanbranch in maintplan.maintenanceplanlayerbranch_set.all():
|
||||||
|
layerbranch = maintplanbranch.layerbranch
|
||||||
|
if RecipeUpgradeGroupRule.objects.filter(layerbranch=layerbranch).exists():
|
||||||
|
for ru in RecipeUpgrade.objects.filter(recipesymbol__layerbranch=layerbranch):
|
||||||
|
if ru.regroup():
|
||||||
|
ru.save()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
lockfn = os.path.join(fetchdir, "layerindex.lock")
|
lockfn = os.path.join(fetchdir, "layerindex.lock")
|
||||||
lockfile = utils.lock_file(lockfn)
|
lockfile = utils.lock_file(lockfn)
|
||||||
if not lockfile:
|
if not lockfile:
|
||||||
|
@ -237,6 +247,10 @@ if __name__=="__main__":
|
||||||
help="Specify maintenance plan to operate on (default is all plans that have updates enabled)",
|
help="Specify maintenance plan to operate on (default is all plans that have updates enabled)",
|
||||||
action="store", dest="plan", default=None)
|
action="store", dest="plan", default=None)
|
||||||
|
|
||||||
|
parser.add_option("--regroup",
|
||||||
|
help="Re-group records only",
|
||||||
|
action="store_true", dest="regroup", default=False)
|
||||||
|
|
||||||
options, args = parser.parse_args(sys.argv)
|
options, args = parser.parse_args(sys.argv)
|
||||||
logger.setLevel(options.loglevel)
|
logger.setLevel(options.loglevel)
|
||||||
|
|
||||||
|
|
|
@ -117,11 +117,12 @@ oecore_bad_revs = {
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Store upgrade into RecipeUpgrade model.
|
Store upgrade into RecipeUpgrade model.
|
||||||
"""
|
"""
|
||||||
def _save_upgrade(recipesymbol, layerbranch, pv, commit, title, info, filepath, logger, upgrade_type=None, orig_filepath=None):
|
def _save_upgrade(recipesymbol, layerbranch, pv, commit, title, info, filepath, logger, upgrade_type=None, orig_filepath=None):
|
||||||
from rrs.models import Maintainer, RecipeUpgrade, RecipeSymbol
|
from rrs.models import Maintainer, RecipeUpgrade
|
||||||
|
|
||||||
maintainer_name = info.split(';')[0]
|
maintainer_name = info.split(';')[0]
|
||||||
maintainer_email = info.split(';')[1]
|
maintainer_email = info.split(';')[1]
|
||||||
|
@ -143,13 +144,14 @@ def _save_upgrade(recipesymbol, layerbranch, pv, commit, title, info, filepath,
|
||||||
upgrade.upgrade_type = upgrade_type
|
upgrade.upgrade_type = upgrade_type
|
||||||
if orig_filepath:
|
if orig_filepath:
|
||||||
upgrade.orig_filepath = orig_filepath
|
upgrade.orig_filepath = orig_filepath
|
||||||
|
upgrade.regroup()
|
||||||
upgrade.save()
|
upgrade.save()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Create upgrade receives new recipe_data and cmp versions.
|
Create upgrade receives new recipe_data and cmp versions.
|
||||||
"""
|
"""
|
||||||
def _create_upgrade(recipe_data, layerbranch, ct, title, info, filepath, logger, pn_recipes, initial=False, orig_filepath=None):
|
def _create_upgrade(recipe_data, layerbranch, ct, title, info, filepath, logger, pn_recipes, initial=False, orig_filepath=None):
|
||||||
from rrs.models import RecipeUpgrade, RecipeSymbol
|
from rrs.models import RecipeUpgrade, RecipeSymbol, RecipeUpgradeGroupRule
|
||||||
from bb.utils import vercmp_string
|
from bb.utils import vercmp_string
|
||||||
|
|
||||||
pn = recipe_data.getVar('PN', True)
|
pn = recipe_data.getVar('PN', True)
|
||||||
|
|
19
rrs/views.py
19
rrs/views.py
|
@ -624,9 +624,11 @@ class RecipeUpgradeDetail():
|
||||||
commit = None
|
commit = None
|
||||||
commit_url = None
|
commit_url = None
|
||||||
upgrade_type = None
|
upgrade_type = None
|
||||||
|
group = None
|
||||||
|
|
||||||
def __init__(self, title, version, maintplan_name, release_name, milestone_name, date,
|
def __init__(self, title, version, maintplan_name, release_name, milestone_name, date,
|
||||||
maintainer_name, is_recipe_maintainer, commit, commit_url, upgrade_type):
|
maintainer_name, is_recipe_maintainer, commit, commit_url, upgrade_type,
|
||||||
|
group):
|
||||||
self.title = title
|
self.title = title
|
||||||
self.version = version
|
self.version = version
|
||||||
self.maintplan_name = maintplan_name
|
self.maintplan_name = maintplan_name
|
||||||
|
@ -638,6 +640,7 @@ class RecipeUpgradeDetail():
|
||||||
self.commit = commit
|
self.commit = commit
|
||||||
self.commit_url = commit_url
|
self.commit_url = commit_url
|
||||||
self.upgrade_type = upgrade_type
|
self.upgrade_type = upgrade_type
|
||||||
|
self.group = group
|
||||||
|
|
||||||
def _get_recipe_upgrade_detail(maintplan, recipe_upgrade):
|
def _get_recipe_upgrade_detail(maintplan, recipe_upgrade):
|
||||||
release_name = ''
|
release_name = ''
|
||||||
|
@ -672,7 +675,8 @@ def _get_recipe_upgrade_detail(maintplan, recipe_upgrade):
|
||||||
|
|
||||||
rud = RecipeUpgradeDetail(recipe_upgrade.title, recipe_upgrade.version, \
|
rud = RecipeUpgradeDetail(recipe_upgrade.title, recipe_upgrade.version, \
|
||||||
maintplan.name, release_name, milestone_name, commit_date, maintainer_name, \
|
maintplan.name, release_name, milestone_name, commit_date, maintainer_name, \
|
||||||
is_recipe_maintainer, commit, commit_url, recipe_upgrade.upgrade_type)
|
is_recipe_maintainer, commit, commit_url, recipe_upgrade.upgrade_type, \
|
||||||
|
recipe_upgrade.group)
|
||||||
|
|
||||||
return rud
|
return rud
|
||||||
|
|
||||||
|
@ -730,10 +734,13 @@ class RecipeDetailView(DetailView):
|
||||||
else:
|
else:
|
||||||
context['maintainer_name'] = 'No maintainer'
|
context['maintainer_name'] = 'No maintainer'
|
||||||
|
|
||||||
context['recipe_upgrade_details'] = []
|
details = []
|
||||||
for ru in RecipeUpgrade.objects.filter(recipesymbol=recipesymbol).exclude(upgrade_type='M').order_by('-commit_date'):
|
for ru in RecipeUpgrade.objects.filter(recipesymbol=recipesymbol).exclude(upgrade_type='M').order_by('group', '-commit_date'):
|
||||||
context['recipe_upgrade_details'].append(_get_recipe_upgrade_detail(maintplan, ru))
|
details.append(_get_recipe_upgrade_detail(maintplan, ru))
|
||||||
context['recipe_upgrade_detail_count'] = len(context['recipe_upgrade_details'])
|
details.sort(key=lambda s: list(map(int, s.group.title.split('.') if s.group else [])), reverse=True)
|
||||||
|
context['recipe_upgrade_details'] = details
|
||||||
|
context['recipe_upgrade_detail_count'] = len(details)
|
||||||
|
|
||||||
|
|
||||||
if not recipe:
|
if not recipe:
|
||||||
ru = RecipeUpgrade.objects.filter(recipesymbol=recipesymbol).order_by('-commit_date').first()
|
ru = RecipeUpgrade.objects.filter(recipesymbol=recipesymbol).order_by('-commit_date').first()
|
||||||
|
|
|
@ -93,6 +93,9 @@
|
||||||
<th>Commit</th>
|
<th>Commit</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for rud in recipe_upgrade_details %}
|
{% for rud in recipe_upgrade_details %}
|
||||||
|
{% ifchanged rud.group %}
|
||||||
|
<tr><td colspan="6"><b>{{ rud.group.title }}</b></td></tr>
|
||||||
|
{% endifchanged %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ rud.title }}</td>
|
<td>{{ rud.title }}</td>
|
||||||
<td>{% if rud.upgrade_type != 'R' %}{{ rud.version }}{% if rud.upgrade_type == 'D' %} <span class="label label-warning">downgrade</span>{% endif %}{% endif %}</td>
|
<td>{% if rud.upgrade_type != 'R' %}{{ rud.version }}{% if rud.upgrade_type == 'D' %} <span class="label label-warning">downgrade</span>{% endif %}{% endif %}</td>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user