Visualize version deliveries and task dependency branches
This commit is contained in:
+17
-4
@@ -43,6 +43,7 @@ TASK_REPORT_DEFAULTS = {'execution_status':'pending','last_report_at':None,'last
|
||||
|
||||
|
||||
TASK_RELATION_DEFAULTS = {
|
||||
'kind':'work', 'delivery_id':None,
|
||||
'goal':'', 'scope':'', 'coupling_assessment':'', 'owner':'', 'integration_owner':'', 'version':'',
|
||||
'parent_id':None, 'merged_into_id':None, 'depends_on':[], 'parallel_with':[], 'merge_sources':[],
|
||||
'parallel_scope':'', 'acceptance_criteria':[], 'sync_points':[], 'integration_status':'not_started'}
|
||||
@@ -327,7 +328,7 @@ class Store:
|
||||
def _task_defaults(record):
|
||||
return {**{k:list(v) if isinstance(v,list) else v for k,v in TASK_RELATION_DEFAULTS.items()},
|
||||
**ETA_DEFAULTS, **TASK_REPORT_DEFAULTS, 'report_evidence':[],
|
||||
'current_progress':'', 'progress_updated':None, **record}
|
||||
'current_progress':'', 'progress_updated':None, 'created_at':None, **record}
|
||||
|
||||
|
||||
@staticmethod
|
||||
@@ -350,7 +351,11 @@ class Store:
|
||||
if not isinstance(record[field],str):
|
||||
raise Invalid('invalid '+field)
|
||||
string(record[field],field,limit,True)
|
||||
for field in ('parent_id','merged_into_id'):
|
||||
if record['kind'] not in ('work','delivery'):
|
||||
raise Invalid('invalid task kind')
|
||||
if record['kind']=='delivery' and record['delivery_id'] is not None:
|
||||
raise Invalid('delivery cannot belong to another delivery')
|
||||
for field in ('parent_id','merged_into_id','delivery_id'):
|
||||
value = record[field]
|
||||
if value is not None:
|
||||
identifier(value,field)
|
||||
@@ -385,6 +390,13 @@ class Store:
|
||||
|
||||
@staticmethod
|
||||
def _validate_task_graphs(tasks):
|
||||
for task_id,task in tasks.items():
|
||||
delivery = task.get('delivery_id')
|
||||
if delivery is not None:
|
||||
if delivery==task_id or delivery not in tasks:
|
||||
raise Invalid('invalid delivery reference')
|
||||
if task.get('kind','work')=='delivery' or tasks[delivery].get('kind','work')!='delivery':
|
||||
raise Conflict('delivery reference requires a delivery task')
|
||||
graphs = [
|
||||
{key:([value['parent_id']] if value.get('parent_id') else []) for key,value in tasks.items()},
|
||||
{key:value.get('depends_on',[]) for key,value in tasks.items()},
|
||||
@@ -567,7 +579,7 @@ class Store:
|
||||
def task(self, data, key=None):
|
||||
if key is not None and 'id' in data and data['id'] != key:
|
||||
raise Invalid('task id differs from target')
|
||||
if 'progress_updated' in data or (ETA_MANAGED | set(TASK_REPORT_DEFAULTS)) & set(data):
|
||||
if 'created_at' in data or 'progress_updated' in data or (ETA_MANAGED | set(TASK_REPORT_DEFAULTS)) & set(data):
|
||||
raise Invalid('server managed task field')
|
||||
key = identifier(key or data.get('id') or secrets.token_hex(12))
|
||||
rejected = False
|
||||
@@ -578,7 +590,7 @@ class Store:
|
||||
record = dict(old, **data)
|
||||
record['id'] = key
|
||||
allowed = {'id','name','session_id','status','phase','eta_min_minutes','eta_max_minutes',
|
||||
'eta_basis','decision','updated','current_progress','progress_updated'} | set(ETA_DEFAULTS) | set(TASK_RELATION_DEFAULTS) | set(TASK_REPORT_DEFAULTS)
|
||||
'eta_basis','decision','updated','current_progress','progress_updated','created_at'} | set(ETA_DEFAULTS) | set(TASK_RELATION_DEFAULTS) | set(TASK_REPORT_DEFAULTS)
|
||||
if set(record) - allowed:
|
||||
raise Invalid('unknown task field')
|
||||
record['name'] = string(record.get('name'), 'name', 200)
|
||||
@@ -600,6 +612,7 @@ class Store:
|
||||
record['current_progress'] = string(progress,'current_progress',1000,True)
|
||||
record, related = self._stage_task_relations(db,record,old,set(data))
|
||||
now = time.time()
|
||||
record['created_at'] = old.get('created_at') if row else now
|
||||
rejected = self._eta_change(record,old,data,now)
|
||||
if rejected:
|
||||
record = self._task_defaults(old)
|
||||
|
||||
Reference in New Issue
Block a user