18 |
18 |
19 Description: |
19 Description: |
20 |
20 |
21 ============================================================================ |
21 ============================================================================ |
22 --> |
22 --> |
|
23 <!--* @package releases --> |
23 <project name="relnotes" default="release-notes" xmlns:hlm="http://www.nokia.com/helium"> |
24 <project name="relnotes" default="release-notes" xmlns:hlm="http://www.nokia.com/helium"> |
24 <description> |
25 <description> |
25 Generates a release note by modifying a template (that you can edit yourself) with |
26 Generates a release note by modifying a template (that you can edit yourself) with |
26 values from the build and Synergy. |
27 values from the build and Synergy. |
27 |
28 |
28 * Modifies a RTF template with values from build |
29 * Modifies a RTF template with values from build |
29 * Adds table of errors and warnings |
30 * Adds table of errors and warnings |
30 * Generates list of baselines, projects and tasks used |
31 * Generates list of baselines, projects and tasks used |
31 </description> |
32 </description> |
32 |
33 |
|
34 <!--* @property product.printname |
|
35 A printable name for a product used in release notes. |
|
36 @type string |
|
37 @editable required |
|
38 @scope public |
|
39 --> |
|
40 |
|
41 <!--* @property product.type |
|
42 Project ID in release notes. |
|
43 @type string |
|
44 @editable required |
|
45 @scope public |
|
46 --> |
|
47 |
|
48 <!--* @property relnotes.config.dir |
|
49 Defines the directory that contains release notes creation configuration files. |
|
50 @type string |
|
51 @editable required |
|
52 @scope public |
|
53 --> |
|
54 |
|
55 <!-- Defines the directory that will contain the output of release notes creation. |
|
56 @type string |
|
57 @scope private |
|
58 --> |
33 <property name="releasenotes.output.dir" value="${build.output.dir}/relnotes"/> |
59 <property name="releasenotes.output.dir" value="${build.output.dir}/relnotes"/> |
|
60 <!-- Defines the logo image file which will be used in release notes. |
|
61 @type string |
|
62 @scope private |
|
63 --> |
34 <property name="releasenotes.logo" value="${relnotes.config.dir}/logo.png"/> |
64 <property name="releasenotes.logo" value="${relnotes.config.dir}/logo.png"/> |
|
65 <!-- Property file with customer values |
|
66 @type string |
|
67 @scope private |
|
68 --> |
35 <property name="releasenotes.props" value="${relnotes.config.dir}/relnotes.properties"/> |
69 <property name="releasenotes.props" value="${relnotes.config.dir}/relnotes.properties"/> |
|
70 <!-- Temp file |
|
71 @type string |
|
72 @scope private |
|
73 --> |
36 <property name="releasenotes.temp.props" value="${temp.build.dir}/relnotes.properties"/> |
74 <property name="releasenotes.temp.props" value="${temp.build.dir}/relnotes.properties"/> |
|
75 <!-- Temp file |
|
76 @type string |
|
77 @scope private |
|
78 --> |
37 <property name="releasenotes.temp.props2" value="${temp.build.dir}/relnotes2.properties"/> |
79 <property name="releasenotes.temp.props2" value="${temp.build.dir}/relnotes2.properties"/> |
|
80 <!-- Defines the name of the release note template used. |
|
81 @type string |
|
82 @scope private |
|
83 --> |
38 <property name="releasenotes.template" value="${relnotes.config.dir}/template.rtf"/> |
84 <property name="releasenotes.template" value="${relnotes.config.dir}/template.rtf"/> |
|
85 <!-- Location of output rtf file |
|
86 @type string |
|
87 @scope private |
|
88 --> |
39 <property name="releasenotes.output" value="${releasenotes.output.dir}/${build.id}_relnotes.rtf"/> |
89 <property name="releasenotes.output" value="${releasenotes.output.dir}/${build.id}_relnotes.rtf"/> |
|
90 <!-- Temp file |
|
91 @type string |
|
92 @scope private |
|
93 --> |
40 <property name="releasenotes.temp.errors" value="${temp.build.dir}/errors.csv"/> |
94 <property name="releasenotes.temp.errors" value="${temp.build.dir}/errors.csv"/> |
|
95 <!-- Temp file |
|
96 @type string |
|
97 @scope private |
|
98 --> |
41 <property name="releasenotes.temp.output" value="${temp.build.dir}/tempDocument.rtf"/> |
99 <property name="releasenotes.temp.output" value="${temp.build.dir}/tempDocument.rtf"/> |
|
100 <!-- Location of scan2log HTML file |
|
101 @type string |
|
102 @scope private |
|
103 --> |
42 <property name="releasenotes.scan2log" value="${build.log.dir}/${build.id}.${product.family}_scan2.html"/> |
104 <property name="releasenotes.scan2log" value="${build.log.dir}/${build.id}.${product.family}_scan2.html"/> |
43 |
105 |
44 <import file="${relnotes.config.dir}/relnotes_properties.ant.xml" optional="true"/> |
106 <import file="${relnotes.config.dir}/relnotes_properties.ant.xml" optional="true"/> |
45 |
107 |
46 <!-- Private: --> |
108 <!-- @scope private --> |
47 <target name="release-notes-variant-configuration" depends="rombuild-prepare-input"> |
109 <target name="release-notes-variant-configuration" depends="imaker-merge-rom-xml"> |
48 |
|
49 <script language="jython" setbeans="false"> |
110 <script language="jython" setbeans="false"> |
50 tagnames = "" |
111 tagnames = "" |
51 for product in project.getProperty("product.list").split(","): |
112 for product in project.getProperty("product.list").split(","): |
52 tagnames += "Type%sVariantTableHere\n" % product |
113 tagnames += "Type%sVariantTableHere\n" % product |
53 project.setProperty("variant.product.tagnames", tagnames) |
114 project.setProperty("variant.product.tagnames", tagnames) |
54 </script> |
115 </script> |
55 <replace file="${releasenotes.output}" token="TypeVariantTableHere" value="${variant.product.tagnames}" summary="true"/> |
116 <replace file="${releasenotes.output}" token="TypeVariantTableHere" value="${variant.product.tagnames}" summary="true"/> |
56 <for list="${product.list}" delimiter="," param="product.name" > |
117 <for list="${product.list}" delimiter="," param="product.name" > |
57 <sequential> |
118 <sequential> |
58 <exec executable="python" dir="${helium.dir}/tools/relnotes" failonerror="${failonerror}"> |
119 <exec executable="python" failonerror="${failonerror}"> |
59 <arg value="getVariantConfiguration.py"/> |
120 <arg line="-m getVariantConfiguration"/> |
60 <arg value="@{product.name}"/> |
121 <arg value="@{product.name}"/> |
61 <arg value="${localisation.language.file}"/> |
|
62 <arg value="${rombuild.config.file.parsed}"/> |
122 <arg value="${rombuild.config.file.parsed}"/> |
63 <arg value="${temp.build.dir}/variant_@{product.name}.csv"/> |
123 <arg value="${temp.build.dir}/variant_@{product.name}.csv"/> |
64 </exec> |
124 </exec> |
65 <hlm:python> |
125 <hlm:python> |
66 import ant |
126 import ant |
73 <move file="${releasenotes.temp.output}" tofile="${releasenotes.output}"/> |
133 <move file="${releasenotes.temp.output}" tofile="${releasenotes.output}"/> |
74 </sequential> |
134 </sequential> |
75 </for> |
135 </for> |
76 </target> |
136 </target> |
77 |
137 |
78 <!-- Private: Create error list in release notes --> |
138 <!-- Create error list in release notes |
|
139 @scope private |
|
140 --> |
79 <target name="release-notes-error-summary"> |
141 <target name="release-notes-error-summary"> |
80 <exec executable="python" dir="${helium.dir}/tools/relnotes" failonerror="${failonerror}"> |
142 <fmpp sourceFile="${helium.dir}/tools/relnotes/templates/errors.csv.ftl" |
81 <arg value="readHTML.py"/> |
143 outputfile="${releasenotes.temp.errors}"> |
82 <arg value="${releasenotes.scan2log}"/> |
144 <freemarkerLinks expandProperties="yes"> |
83 <arg value="${releasenotes.temp.errors}"/> |
145 macro: ${helium.dir}/tools/common/templates/macro |
84 </exec> |
146 </freemarkerLinks> |
|
147 <data expandProperties="yes"> |
|
148 dbPath: ${metadata.dbfile} |
|
149 ant: antProperties() |
|
150 </data> |
|
151 </fmpp> |
85 <hlm:python> |
152 <hlm:python> |
86 import ant |
153 import ant |
87 import rtfutils |
154 import rtfutils |
88 rn = rtfutils.RTFUtils(ant.get_property(r'${releasenotes.output}')) |
155 rn = rtfutils.RTFUtils(ant.get_property(r'${releasenotes.output}')) |
89 rn.rtftable(ant.get_property(r'${releasenotes.temp.errors}'), ant.get_property(r'${releasenotes.temp.output}'), 'TypeErrorTableSummaryHere') |
156 rn.rtftable(ant.get_property(r'${releasenotes.temp.errors}'), ant.get_property(r'${releasenotes.temp.output}'), 'TypeErrorTableSummaryHere') |
90 </hlm:python> |
157 </hlm:python> |
91 <delete file="${releasenotes.output}"/> |
158 <delete file="${releasenotes.output}"/> |
92 <move file="${releasenotes.temp.output}" tofile="${releasenotes.output}"/> |
159 <move file="${releasenotes.temp.output}" tofile="${releasenotes.output}"/> |
93 </target> |
160 </target> |
94 |
161 |
95 <!-- Private: Add logo to release notes --> |
162 <!-- Add logo to release notes. @scope private --> |
96 <target name="release-notes-logo"> |
163 <target name="release-notes-logo"> |
97 <hlm:python> |
164 <hlm:python> |
98 import ant |
165 import ant |
99 import rtfutils |
166 import rtfutils |
100 rn = rtfutils.RTFUtils(ant.get_property(r'${releasenotes.output}')) |
167 rn = rtfutils.RTFUtils(ant.get_property(r'${releasenotes.output}')) |
101 rn.rtfimage(ant.get_property(r'${releasenotes.logo}'), ant.get_property(r'${releasenotes.temp.output}'), 'AddProductImageHere') |
168 rn.rtfimage(ant.get_property(r'${releasenotes.logo}'), ant.get_property(r'${releasenotes.temp.output}'), 'AddProductImageHere') |
102 </hlm:python> |
169 </hlm:python> |
103 <move file="${releasenotes.temp.output}" tofile="${releasenotes.output}"/> |
170 <move file="${releasenotes.temp.output}" tofile="${releasenotes.output}"/> |
104 </target> |
171 </target> |
105 |
172 |
106 <!-- Private: Find project and baseline of what is running helium --> |
173 <!-- Find project and baseline of what is running helium |
|
174 @scope private |
|
175 --> |
107 <target name="release-notes-getcmprojectname"> |
176 <target name="release-notes-getcmprojectname"> |
108 <script language="jython" setbeans="false"> |
177 <if> |
109 import nokia.nokiaccm |
178 <istrue value="${ccm.enabled}" /> |
|
179 <then> |
|
180 <script language="jython" setbeans="false"> |
110 import ccm.extra |
181 import ccm.extra |
111 import traceback |
182 import traceback |
112 import os |
183 import os |
113 import logging |
184 import logging |
|
185 import ccmutil |
|
186 |
114 #logging.basicConfig(level=logging.DEBUG) |
187 #logging.basicConfig(level=logging.DEBUG) |
115 session = None |
188 session = None |
116 try: |
189 try: |
117 database = project.getProperty('ccm.database') |
190 database = project.getProperty('ccm.database') |
118 username = project.getProperty('ccm.user.login') |
191 username = project.getProperty('ccm.user.login') |
119 password = project.getProperty('ccm.user.password') |
192 password = project.getProperty('ccm.user.password') |
120 engine = project.getProperty('ccm.engine.host') |
193 engine = project.getProperty('ccm.engine.host') |
121 dbpath = project.getProperty('ccm.database.path') |
194 dbpath = project.getProperty('ccm.database.path') |
122 waroot = project.getProperty('create.bom.workarea.root') |
195 waroot = project.getProperty('create.bom.workarea.root') |
123 if database != None: |
196 |
124 session = nokia.nokiaccm.open_session(username, password, database=database) |
197 session = ccmutil.get_session(database, username, password, engine, dbpath) |
125 else: |
|
126 session = nokia.nokiaccm.open_session(username, password, engine, dbpath) |
|
127 |
|
128 cmproject = ccm.extra.get_toplevel_project(session, waroot) |
198 cmproject = ccm.extra.get_toplevel_project(session, waroot) |
|
199 |
129 if cmproject == None: |
200 if cmproject == None: |
130 print 'Error: ' + waroot + ' must be a synergy project and still be in database' |
201 print 'Error: ' + waroot + ' must be a synergy project and still be in database' |
131 else: |
202 else: |
132 project.setProperty("ccm.toplevel.project", str(cmproject)) |
203 project.setProperty("ccm.toplevel.project", str(cmproject)) |
133 session.close() |
204 session.close() |
134 except Exception, ex: |
205 except Exception, ex: |
135 print 'Caught exception: ' + str(ex) |
206 print 'Caught exception: ' + str(ex) |
136 traceback.print_exc() |
207 traceback.print_exc() |
137 </script> |
208 if session: |
138 |
209 session.close() |
139 <hlm:python outputproperty="ccm.toplevel.baseline"> |
210 </script> |
140 import nokia.nokiaccm |
211 <hlm:python outputproperty="ccm.toplevel.baseline"> |
141 import traceback |
212 import traceback |
142 import ant |
213 import ant |
143 import logging |
214 import logging |
|
215 import ccmutil |
144 logging.disable(logging.INFO) |
216 logging.disable(logging.INFO) |
145 session = None |
217 session = None |
146 try: |
218 try: |
147 database = ant.get_property(r'${ccm.database}') |
219 database = ant.get_property(r'${ccm.database}') |
148 username = ant.get_property(r'${ccm.user.login}') |
220 username = ant.get_property(r'${ccm.user.login}') |
149 password = ant.get_property(r'${ccm.user.password}') |
221 password = ant.get_property(r'${ccm.user.password}') |
150 engine = ant.get_property(r'${ccm.engine.host}') |
222 engine = ant.get_property(r'${ccm.engine.host}') |
151 dbpath = ant.get_property(r'${ccm.database.path}') |
223 dbpath = ant.get_property(r'${ccm.database.path}') |
152 if database != None: |
224 session = ccmutil.get_session(database, username, password, engine, dbpath) |
153 session = nokia.nokiaccm.open_session(username, password, database=database) |
|
154 else: |
|
155 session = nokia.nokiaccm.open_session(username, password, engine, dbpath) |
|
156 |
|
157 cmproject = session.create(ant.get_property(r'${ccm.toplevel.project}')) |
225 cmproject = session.create(ant.get_property(r'${ccm.toplevel.project}')) |
158 print cmproject.baseline |
226 print cmproject.baseline |
159 session.close() |
227 session.close() |
160 except Exception, ex: |
228 except Exception, ex: |
161 print 'Caught exception: ' + str(ex) |
229 print 'Caught exception: ' + str(ex) |
162 traceback.print_exc() |
230 traceback.print_exc() |
163 </hlm:python> |
231 if session: |
164 </target> |
232 session.close() |
165 |
233 </hlm:python> |
166 <!-- Private: |
234 </then> |
167 Look at property 'project.startswith' and find complete CM name |
235 </if> |
168 Output property: '${project.startswith}.project' |
236 </target> |
169 --> |
237 |
170 <target name="release-notes-getprojectname"> |
238 <!-- |
171 <hlm:python outputproperty="release.notes.temp"> |
239 Look 'startsWith' and find complete CM name |
|
240 Output property: '{startsWith}.project'. |
|
241 |
|
242 @scope private |
|
243 --> |
|
244 <macrodef name="releaseNotesGetProjectName" uri="http://www.nokia.com/helium"> |
|
245 <attribute name="startsWith" /> |
|
246 <sequential> |
|
247 <if> |
|
248 <available file="${build.log.dir}/${build.id}_bom.xml" /> |
|
249 <then> |
|
250 <hlm:python outputproperty="@{startsWith}.project"> |
172 import amara |
251 import amara |
173 import ant |
252 import ant |
174 |
253 |
175 bomfile = open(r"${build.log.dir}/${build.id}_BOM.xml") |
254 bomfile = open(r"${build.log.dir}/${build.id}_bom.xml") |
176 bom = amara.parse(bomfile) |
255 bom = amara.parse(bomfile) |
177 |
256 |
178 for p in bom.bom.content.project: |
257 for p in bom.bom.content.project: |
179 if (str(p.name).startswith(ant.get_property(r'${project.startswith}'))): |
258 if (str(p.name).startswith(ant.get_property(r'@{startsWith}'))): |
180 print str(p.name) |
259 print str(p.name) |
181 bomfile.close() |
260 bomfile.close() |
182 </hlm:python> |
261 </hlm:python> |
183 <script language="jython" setbeans="false"> |
262 </then> |
184 project.setProperty(project.getProperty('project.startswith') + '.project', project.getProperty('release.notes.temp')) |
263 </if> |
185 </script> |
264 </sequential> |
186 |
265 </macrodef> |
187 </target> |
266 |
188 |
267 <!-- Write projects, baselines and task list for MC and IBUSAL |
189 <!-- Private: Write projects, baselines and task list for MC and IBUSAL --> |
268 @scope private |
|
269 --> |
190 <target name="release-notes-ccm" depends="get-ccm-password,release-notes-getcmprojectname,create-bom"> |
270 <target name="release-notes-ccm" depends="get-ccm-password,release-notes-getcmprojectname,create-bom"> |
191 |
271 <if> |
192 <hlm:python> |
272 <and> |
|
273 <istrue value="${ccm.enabled}" /> |
|
274 <available file="${build.log.dir}/${build.id}_bom.xml" /> |
|
275 </and> |
|
276 <then> |
|
277 <hlm:python> |
193 import amara |
278 import amara |
194 import nokia.nokiaccm |
279 import ant |
195 import ant |
280 import bomtofile |
196 |
281 import ccmutil |
197 class BOMToFile(object): |
282 |
198 """ |
283 bomfile = open(r"${build.log.dir}/${build.id}_bom.xml") |
199 Read BOM and output in text |
|
200 """ |
|
201 def __init__(self, session, project_name, project, output_dir): |
|
202 self.project_name = project_name |
|
203 self.project = project |
|
204 self.output_dir = output_dir |
|
205 self.session = session |
|
206 |
|
207 def writeprojects(self): |
|
208 fileout = file(self.output_dir + '/' + self.project_name + '_projects.txt', 'w') |
|
209 |
|
210 i = 1 |
|
211 for project in self.project.baseline: |
|
212 fileout.write(str(i) + ") " + str(project) + "\n") |
|
213 |
|
214 i += 1 |
|
215 fileout.close() |
|
216 |
|
217 def writebaselines(self): |
|
218 fileout = file(self.output_dir + '/' + self.project_name + '_baselines.txt', 'w') |
|
219 |
|
220 i = 1 |
|
221 for project in self.project.baseline: |
|
222 fileout.write(str(i) + ") " + str(project) + "\n") |
|
223 |
|
224 cmproject = self.session.create(str(project)) |
|
225 |
|
226 try: |
|
227 baseline = str(cmproject.baseline).strip() |
|
228 if baseline == "None": |
|
229 fileout.write(str(i) + ") " + str(project) + "\n") |
|
230 else: |
|
231 fileout.write(str(i) + ") " + baseline + "\n") |
|
232 i += 1 |
|
233 except Exception, ex: |
|
234 print ex |
|
235 fileout.close() |
|
236 |
|
237 def writetasks(self): |
|
238 if self.project.xml_properties.has_key("task"): |
|
239 fileout = file(self.output_dir + '/' + self.project_name + '_tasks.txt', 'w') |
|
240 |
|
241 i = 1 |
|
242 for task in self.project.task: |
|
243 fileout.write(str(i) + ") Task " + str(task) + "\n") |
|
244 i += 1 |
|
245 fileout.close() |
|
246 |
|
247 bomfile = open(r"${build.log.dir}/${build.id}_BOM.xml") |
|
248 bom = amara.parse(bomfile) |
284 bom = amara.parse(bomfile) |
249 database = ant.get_property(r'${ccm.database}') |
|
250 username = ant.get_property(r'${ccm.user.login}') |
|
251 password = ant.get_property(r'${ccm.user.password}') |
285 password = ant.get_property(r'${ccm.user.password}') |
252 engine = ant.get_property(r'${ccm.engine.host}') |
286 session = ccmutil.get_session(ant.get_property(r'${ccm.database}'), ant.get_property(r'${ccm.user.login}'), password, ant.get_property(r'${ccm.engine.host}'), ant.get_property(r'${ccm.database.path}')) |
253 dbpath = ant.get_property(r'${ccm.database.path}') |
|
254 if database != None: |
|
255 session = nokia.nokiaccm.open_session(username, password, database=database) |
|
256 else: |
|
257 session = nokia.nokiaccm.open_session(username, password, engine, dbpath) |
|
258 |
|
259 for p in bom.bom.content.project: |
287 for p in bom.bom.content.project: |
260 if p.name == ant.get_property(r'${ccm.toplevel.project}'): |
288 if p.name == ant.get_property(r'${ccm.toplevel.project}'): |
261 btof = BOMToFile(session, 'MC', p, ant.get_property(r'${releasenotes.output.dir}')) |
289 bomwriter = bomtofile.BOMWriter(session, 'MC', p, ant.get_property(r'${releasenotes.output.dir}')) |
262 |
290 bomwriter.writeprojects() |
263 btof.writeprojects() |
291 bomwriter.writebaselines() |
264 btof.writebaselines() |
292 bomwriter.writetasks() |
265 |
|
266 btof.writetasks() |
|
267 |
293 |
268 if (str(p.name).startswith('IBUSAL')): |
294 if (str(p.name).startswith('IBUSAL')): |
269 btof = BOMToFile(session, 'IBUSAL', p, ant.get_property(r'${releasenotes.output.dir}')) |
295 bomwriter = bomtofile.BOMWriter(session, 'IBUSAL', p, ant.get_property(r'${releasenotes.output.dir}')) |
270 |
296 bomwriter.writeprojects() |
271 btof.writeprojects() |
297 bomwriter.writetasks() |
272 |
|
273 btof.writetasks() |
|
274 |
|
275 session.close() |
298 session.close() |
276 bomfile.close() |
299 bomfile.close() |
277 |
300 </hlm:python> |
278 </hlm:python> |
301 </then> |
279 </target> |
302 </if> |
280 |
303 </target> |
281 <!-- Private: Read BOM and write ICF list --> |
304 |
|
305 <!-- Read BOM and write ICF list |
|
306 @scope private |
|
307 --> |
282 <target name="release-notes-icfs" depends="create-bom"> |
308 <target name="release-notes-icfs" depends="create-bom"> |
283 <exec executable="python" dir="${helium.dir}/tools/relnotes" failonerror="${failonerror}"> |
309 <exec executable="python" failonerror="${failonerror}"> |
284 <arg value="icf2txt.py"/> |
310 <arg line="-m icf2txt"/> |
285 <arg value="${build.log.dir}/${build.id}_BOM.xml"/> |
311 <arg value="${temp.build.dir}/${build.id}_BOM.xml"/> |
286 <arg value="${releasenotes.output.dir}/icdicf.txt"/> |
312 <arg value="${releasenotes.output.dir}/icdicf.txt"/> |
287 </exec> |
313 </exec> |
288 </target> |
314 </target> |
289 |
315 |
290 <!-- Private: --> |
316 <!-- @scope private --> |
291 <target name="release-notes-test" if="hlm.enable.asserts"> |
317 <target name="release-notes-test" if="hlm.enable.asserts"> |
292 <hlm:python> |
318 <if> |
|
319 <istrue value="${ccm.enabled}" /> |
|
320 <then> |
|
321 <hlm:python> |
293 import ccm |
322 import ccm |
294 #check for ccm session leaks |
323 #check for ccm session leaks |
295 assert (len(ccm.running_sessions()) == 0) |
324 assert (len(ccm.running_sessions()) == 0) |
296 </hlm:python> |
325 </hlm:python> |
|
326 </then> |
|
327 </if> |
297 </target> |
328 </target> |
298 |
329 |
299 <!-- |
330 <!-- |
300 Generates a product release note based on a template in config dir |
331 Generates a product release note based on a template in config dir |
301 --> |
332 --> |