Merge lp:~mabac/launchpad-work-items-tracker/linaro-cards-to-blueprints into lp:~linaro-automation/launchpad-work-items-tracker/linaro

Proposed by Mattias Backman
Status: Merged
Approved by: James Westby
Approved revision: 304
Merged at revision: 300
Proposed branch: lp:~mabac/launchpad-work-items-tracker/linaro-cards-to-blueprints
Merge into: lp:~linaro-automation/launchpad-work-items-tracker/linaro
Diff against target: 327 lines (+175/-15)
8 files modified
collect_roadmap (+4/-1)
generate-all (+4/-0)
html-report (+31/-0)
lpworkitems/database.py (+5/-1)
lpworkitems/models_roadmap.py (+3/-1)
report_tools.py (+40/-4)
templates/roadmap_card.html (+78/-0)
templates/roadmap_lane.html (+10/-8)
To merge this branch: bzr merge lp:~mabac/launchpad-work-items-tracker/linaro-cards-to-blueprints
Reviewer Review Type Date Requested Status
James Westby (community) Approve
Review via email: mp+78606@code.launchpad.net

Description of the change

Hi,

This branch adds roadmap Cards pages that display a list of blueprints linked to that card.

The link consists of entering
    Meta:
    Roadmap id: id123
in the blueprint whiteboard and entering the same id in the external_link field of the Kanbantool card.

Thanks,

Mattias

To post a comment you must log in.
Revision history for this message
James Westby (james-w) wrote :

Very nice.

Thanks,

James

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'collect_roadmap'
2--- collect_roadmap 2011-09-29 08:09:22 +0000
3+++ collect_roadmap 2011-10-07 14:09:14 +0000
4@@ -92,7 +92,9 @@
5 lane_id = task_status['parent_id']
6 assert lane_id is not None
7 model_card = Card(unicode_or_None(task['task']['name']),
8- task['task']['id'], lane_id)
9+ task['task']['id'], lane_id,
10+# unicode_or_None(task['task']['external_id']))
11+ unicode_or_None(task['task']['external_link']))
12 model_card.status = unicode_or_None(task_status['name'])
13 collector.store_card(model_card)
14 else:
15@@ -103,6 +105,7 @@
16 '''Collect roadmap items from KanbanTool into DB.'''
17 board_url = get_kanban_url('boards/%s.json' % board_id, api_token)
18 board = get_kanban_data(board_url)
19+ assert board is not None, "Could not access board %s." % board_id
20 status_list = kanban_import_lanes(collector,
21 board['board']['workflow_stages'])
22
23
24=== modified file 'generate-all'
25--- generate-all 2011-09-19 06:47:13 +0000
26+++ generate-all 2011-10-07 14:09:14 +0000
27@@ -160,6 +160,10 @@
28 basename = os.path.join(opts.output_dir, 'roadmap-' + lane.name)
29 report_tools.roadmap_pages(my_path, opts.database, basename, opts.config, lane, root=opts.root)
30
31+# roadmap cards
32+for card in report_tools.cards(store):
33+ basename = os.path.join(opts.output_dir, 'roadmap-card-%s' % card.card_id)
34+ report_tools.roadmap_cards(my_path, opts.database, basename, opts.config, card, root=opts.root)
35
36 def copy_files(source_dir):
37 for filename in os.listdir(source_dir):
38
39=== modified file 'html-report'
40--- html-report 2011-09-19 06:47:13 +0000
41+++ html-report 2011-10-07 14:09:14 +0000
42@@ -486,6 +486,35 @@
43 "roadmap_lane.html", data, theme=opts.theme)
44
45
46+ def roadmap_card(self, store, opts):
47+ if opts.card is None:
48+ print "<h1>Error, no card specified.</h1>"
49+
50+ data = self.template_data(store, opts)
51+ card = report_tools.card(store, int(opts.card)).one()
52+ lane = report_tools.lane(store, None, id=card.lane_id).one()
53+
54+ if not opts.title:
55+ title = card.name
56+ else:
57+ title = opts.title
58+
59+ blueprints = report_tools.card_blueprints(store, card.roadmap_id)
60+
61+ data.update(dict(page_type="roadmap_card"))
62+ data.update(dict(card=title))
63+ data.update(dict(status=card.status))
64+ data.update(dict(lane=lane.name))
65+ data.update(dict(blueprints=blueprints))
66+ data.update(dict(description=""))
67+ data.update(dict(acceptance_criteria=""))
68+ data.update(dict(sponsor_name=""))
69+ data.update(dict(contact_name=""))
70+
71+ print report_tools.fill_template(
72+ "roadmap_card.html", data, theme=opts.theme)
73+
74+
75 class WorkitemsOnDate(object):
76
77 def __init__(self, date, done, delta_done, todo, delta_todo):
78@@ -565,6 +594,8 @@
79 help="The theme to use.", default="linaro")
80 optparser.add_option('--lane',
81 help='Roadmap lane', dest='lane')
82+ optparser.add_option('--card',
83+ help='Roadmap card', dest='card')
84
85 (opts, args) = optparser.parse_args()
86 if not opts.database:
87
88=== modified file 'lpworkitems/database.py'
89--- lpworkitems/database.py 2011-09-07 14:04:38 +0000
90+++ lpworkitems/database.py 2011-10-07 14:09:14 +0000
91@@ -7,7 +7,7 @@
92 store.execute('''CREATE TABLE version (
93 db_layout_ref INT NOT NULL
94 )''')
95- store.execute('''INSERT INTO version VALUES (11)''')
96+ store.execute('''INSERT INTO version VALUES (12)''')
97
98 store.execute('''CREATE TABLE specs (
99 name VARCHAR(255) PRIMARY KEY,
100@@ -100,6 +100,7 @@
101 name VARCHAR(200) NOT NULL,
102 card_id NOT NULL,
103 status VARCHAR(50),
104+ roadmap_id VARCHAR(50),
105 lane_id REFERENCES lane(lane_id)
106 )''')
107
108@@ -205,6 +206,9 @@
109 )''')
110 store.execute('UPDATE version SET db_layout_ref = 11')
111 ver = 11
112+ if ver == 11:
113+ store.execute('ALTER TABLE card ADD COLUMN roadmap_id VARCHAR(50)')
114+ store.execute('UPDATE version SET db_layout_ref = 12')
115
116
117 def get_store(dbpath):
118
119=== modified file 'lpworkitems/models_roadmap.py'
120--- lpworkitems/models_roadmap.py 2011-09-12 14:41:07 +0000
121+++ lpworkitems/models_roadmap.py 2011-10-07 14:09:14 +0000
122@@ -13,11 +13,13 @@
123 status = Unicode()
124 card_id = Int(primary=True)
125 lane_id = Int()
126+ roadmap_id = Unicode()
127
128- def __init__(self, name, card_id, lane_id):
129+ def __init__(self, name, card_id, lane_id, roadmap_id):
130 self.lane_id = lane_id
131 self.card_id = card_id
132 self.name = name
133+ self.roadmap_id = roadmap_id
134
135
136 class Lane(object):
137
138=== modified file 'report_tools.py'
139--- report_tools.py 2011-09-19 06:47:13 +0000
140+++ report_tools.py 2011-10-07 14:09:14 +0000
141@@ -13,6 +13,9 @@
142 Lane,
143 Card,
144 )
145+from lpworkitems.models import (
146+ Meta,
147+)
148
149 valid_states = [u'inprogress', u'blocked', u'todo', u'done', u'postponed']
150 state_labels = [u'In Progress', u'Blocked', u'Todo', u'Done', u'Postponed']
151@@ -217,6 +220,23 @@
152 fh.close()
153
154
155+def roadmap_cards(my_path, database, basename, config, card, root=None):
156+ cfg = load_config(config)
157+ fh = open(basename + '.html', 'w')
158+ try:
159+ args = [os.path.join(my_path, 'html-report'), '-d', database]
160+ args += ['--report-type', 'roadmap_card']
161+ args += ['--card', '%s' % card.card_id]
162+ if root:
163+ args += ['--root', root]
164+ report_args(args, theme=get_theme(cfg))
165+ proc = Popen(args, stdout=fh)
166+ print basename + '.html'
167+ proc.wait()
168+ finally:
169+ fh.close()
170+
171+
172 def run_reports(my_path, database, basename, config, milestone=None, team=None,
173 user=None, trend_starts=None, trend_override=None, burnup=False, root=None, date=None):
174
175@@ -920,13 +940,15 @@
176 return store.find(Lane)
177
178
179-def lane(store, lane):
180- return store.find(Lane, Lane.name == unicode(lane))
181+def lane(store, name, id=None):
182+ if id is None:
183+ return store.find(Lane, Lane.name == unicode(name))
184+ else:
185+ return store.find(Lane, Lane.lane_id == id)
186
187
188 def lane_cards(store, lane):
189- return store.find(Card, Card.lane_id == lane.lane_id)
190-
191+ return lane.cards
192
193 def statuses(store, lane):
194 result = []
195@@ -938,6 +960,20 @@
196 return result
197
198
199+def cards(store):
200+ return store.find(Card)
201+
202+
203+def card(store, card_id):
204+ return store.find(Card, Card.card_id == card_id)
205+
206+
207+def card_blueprints(store, roadmap_id):
208+ metas = store.find(Meta,
209+ Meta.key == u'Roadmap id',
210+ Meta.value == roadmap_id)
211+ return [meta.blueprint for meta in metas]
212+
213 def subteams(store, team):
214 result = store.execute('SELECT name from team_structure where team = ?', (unicode(team),))
215 return [i[0] for i in result]
216
217=== added file 'templates/roadmap_card.html'
218--- templates/roadmap_card.html 1970-01-01 00:00:00 +0000
219+++ templates/roadmap_card.html 2011-10-07 14:09:14 +0000
220@@ -0,0 +1,78 @@
221+<%inherit file="body.html"/>
222+<%namespace name="util" file="util.html"/>
223+<%namespace name="terminology" file="terminology.html"/>
224+
225+<%!
226+import report_tools
227+%>
228+
229+<%def name="title()">
230+${card}
231+</%def>
232+
233+<h1>${title()}</h1>
234+<h2>${status} in <a href="roadmap-${lane}.html">${lane}</a></h2>
235+<p>
236+<ul>
237+ <li>Description: ${description}
238+ <li>Acceptance criteria: ${acceptance_criteria}
239+ <li>Sponsor: ${sponsor_name}
240+ <li>Contact: ${contact_name}
241+</ul>
242+
243+<p>
244+% if blueprints == []:
245+There are no blueprints registered to implement this requirement.
246+% else:
247+<table>
248+<thead>
249+ <tr><th>Title</th>
250+ <th>Assignee</th>
251+ <th>Priority</th>
252+ <th>Status</th>
253+ <th>Expected milestone</th>
254+ <th>Health check</th>
255+ </tr>
256+</thead>
257+% for bp in blueprints:
258+ <tr><td><a href="${bp.url}">${bp.name}</a></td>
259+ <td>${bp.assignee_name}</td>
260+ <td>${bp.priority}</td>
261+ <td>${bp.implementation}</td>
262+ <td>${bp.milestone_name}</td>
263+ <td>xxx</td>
264+ </tr>
265+% endfor
266+</table>
267+% endif
268+<h3>Health check</h3>
269+<table>
270+ <tr><td>Has Description</td>
271+ <td>
272+% if description == "":
273+ No
274+% else:
275+ Yes
276+% endif
277+ </td></tr>
278+ <tr><td>Has Acceptance Criteria</td>
279+ <td>
280+% if acceptance_criteria == "":
281+ No
282+% else:
283+ Yes
284+% endif
285+ </td></tr>
286+ <tr><td>Has Blueprints</td>
287+ <td>
288+% if blueprints == []:
289+ No
290+% else:
291+ Yes
292+% endif
293+ </td></tr>
294+ <tr><td>Is Ready</td>
295+ <td>
296+ TODO
297+ </td></tr>
298+</table>
299
300=== modified file 'templates/roadmap_lane.html'
301--- templates/roadmap_lane.html 2011-09-29 08:09:22 +0000
302+++ templates/roadmap_lane.html 2011-10-07 14:09:14 +0000
303@@ -16,14 +16,16 @@
304 <p><b>${status['name']}</b>
305 % for card in status['cards']:
306
307-<table><tr><td>
308-<a href="">${card.name}</a><br>
309- <table>
310- <tr><td colspan=2>Description of what this requirement is all about.</td></tr>
311- <tr><td>Done: n</td><td>&nbsp</td></tr>
312- <tr><td><a href="">Team X</a></td><td align=right>Priority</td></tr>
313- </table>
314-</td></tr></table>
315+<table>
316+<thead>
317+ <tr><th>
318+ <a href="roadmap-card-${card.card_id}.html">${card.name}</a>
319+ </th></tr>
320+</thead>
321+ <tr><td colspan=2>Description of what this requirement is all about.</td></tr>
322+ <tr><td>Done: n</td><td>&nbsp</td></tr>
323+ <tr><td><a href="">Team X</a></td><td align=right>Priority</td></tr>
324+</table>
325 <p><p>
326 % endfor
327 % endfor

Subscribers

People subscribed via source and target branches