|
1 <?xml version="1.0" encoding="UTF-8"?> |
|
2 <!-- |
|
3 ============================================================================ |
|
4 Name : ci.ant.xml |
|
5 Part of : Helium |
|
6 |
|
7 Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
8 All rights reserved. |
|
9 This component and the accompanying materials are made available |
|
10 under the terms of the License "Eclipse Public License v1.0" |
|
11 which accompanies this distribution, and is available |
|
12 at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
13 |
|
14 Initial Contributors: |
|
15 Nokia Corporation - initial contribution. |
|
16 |
|
17 Contributors: |
|
18 |
|
19 Description: |
|
20 |
|
21 ============================================================================ |
|
22 --> |
|
23 <project name="ci" xmlns:hlm="http://www.nokia.com/helium"> |
|
24 <description> |
|
25 CI related targets |
|
26 </description> |
|
27 |
|
28 <!-- Delete all the folders based on configurations file inside dir-path, optional attribute pool-size's default value is 4 --> |
|
29 <target name="delete-folders-from-list" if = "ci.cleanup.env.dir"> |
|
30 <exec osfamily="windows" executable="python" failonerror="true" outputproperty="delete.folders.drive"> |
|
31 <arg value="${helium.dir}/tools/common/python/scripts/searchnextdrive.py"/> |
|
32 </exec> |
|
33 <hlm:deleteFoldersFromDirMacro dir-path="${ci.cleanup.env.dir}" delete-folders-drive="${delete.folders.drive}"/> |
|
34 </target> |
|
35 |
|
36 <!-- Delete all the folders based on configurations file inside dir-path, optional attribute pool-size's default value is 4 --> |
|
37 <scriptdef name="deleteFoldersFromDirMacro" language="jython" uri="http://www.nokia.com/helium"> |
|
38 <attribute name="dir-path" /> |
|
39 <attribute name="pool-size" /> |
|
40 <attribute name="delete-folders-drive" /> |
|
41 import os |
|
42 import fileutils |
|
43 import threadpool |
|
44 import subprocess |
|
45 import sys |
|
46 |
|
47 dir_path = str(attributes.get('dir-path')) |
|
48 del_folder_drive = attributes.get('delete-folders-drive') |
|
49 pool_size = attributes.get('pool-size') |
|
50 if pool_size != None: |
|
51 pool_size = str(pool_size) |
|
52 else: |
|
53 pool_size = "4" |
|
54 delete_dirs = [] |
|
55 found_inputs = [] |
|
56 # Read config files |
|
57 self.log(str("Scanning %s." % dir_path)) |
|
58 for path_ in os.listdir(dir_path): |
|
59 self.log(str("Checking %s." % path_)) |
|
60 filename = os.path.join(dir_path, path_) |
|
61 if (os.path.isfile(filename)): |
|
62 found_inputs.append(filename) |
|
63 file_ = open(filename) |
|
64 for delete_dir in file_.readlines(): |
|
65 delete_dir = os.path.normpath(delete_dir.strip()) |
|
66 if (len(delete_dir) > 0) and os.path.isdir(delete_dir): |
|
67 delete_dirs.append(delete_dir) |
|
68 file_.close() |
|
69 |
|
70 # Delete all dirs based on config |
|
71 for dir_ in delete_dirs: |
|
72 try: |
|
73 if os.sep == '\\': |
|
74 fileutils.subst(del_folder_drive, dir_) |
|
75 self.log(str("substed for deleling folders")) |
|
76 self.log(str("Removing %s\\" % del_folder_drive)) |
|
77 fileutils.rmtree("%s\\" % del_folder_drive) |
|
78 fileutils.unsubst(del_folder_drive) |
|
79 self.log(str("unsbusted substed for deleling folders")) |
|
80 else: |
|
81 self.log(str("Removing %s" % dir_)) |
|
82 fileutils.rmtree(dir_) |
|
83 except Exception, e: |
|
84 if os.sep == '\\': |
|
85 fileutils.unsubst(del_folder_drive) |
|
86 self.log(str("unsbusted for deleling folders")) |
|
87 self.log(str("ERROR: %s" % e)) |
|
88 |
|
89 # Delete all config files |
|
90 for path_ in found_inputs: |
|
91 self.log(str("Deleting %s." % path_)) |
|
92 os.remove(path_) |
|
93 </scriptdef> |
|
94 |
|
95 <!-- Macro for the folders to be deleted in a file based on the folder creation time |
|
96 If the folders are created at the same time, then it will delete only one of them (this |
|
97 needs to be handled properly in the future releases if required)--> |
|
98 <scriptdef name="BADeleteMacro" language="jython" uri="http://www.nokia.com/helium"> |
|
99 <attribute name="outputdir"/> |
|
100 <attribute name="rootdir"/> |
|
101 <attribute name="no.ba.remain"/> |
|
102 <![CDATA[ |
|
103 import os |
|
104 import time |
|
105 ctime_dict = {} |
|
106 root_dir = str(attributes.get('rootdir')) |
|
107 output_dir = str(attributes.get('outputdir')) |
|
108 for dir_ in os.listdir(root_dir): |
|
109 if (os.path.isdir(os.path.join(root_dir, dir_))): |
|
110 dir_ctime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(os.path.getctime(os.path.join(root_dir, dir_)))) |
|
111 ctime_dict[dir_ctime] = dir_ |
|
112 ctime_list = ctime_dict.keys() |
|
113 ctime_list.sort() |
|
114 self.log(str("ctime_list: %s" % ctime_list)) |
|
115 filename = time.strftime('%Y%m%d%H%M%S', time.localtime()) |
|
116 filename = os.path.join(output_dir, filename + '_file_delete.txt') |
|
117 self.log(str("Creating %s" % filename)) |
|
118 file_ = open(filename, 'w+') |
|
119 count = len(ctime_list) |
|
120 ba_to_leave = int(str(attributes.get('no.ba.remain'))) |
|
121 self.log(str("Leaving %d build areas." % ba_to_leave)) |
|
122 if (ba_to_leave > 0): |
|
123 for ctime_entry in ctime_list: |
|
124 print count |
|
125 if (ba_to_leave >= count): |
|
126 break |
|
127 file_.write(os.path.join(root_dir, ctime_dict[ctime_entry]) + '\n') |
|
128 count -= 1 |
|
129 file_.close() |
|
130 ]]> |
|
131 </scriptdef> |
|
132 |
|
133 <!-- This target flags the Build areas for deletion. So the cleanup build robot could remove them. --> |
|
134 <target name="flag-ba-for-deletion" if = "ci.cleanup.env.dir"> |
|
135 <mkdir dir="${ci.cleanup.env.dir}"/> |
|
136 <if> |
|
137 <not> |
|
138 <isset property="ci.min.ba.maintain"/> |
|
139 </not> |
|
140 <then> |
|
141 <property name="ci.min.ba.maintain" value="2"/> |
|
142 </then> |
|
143 </if> |
|
144 <hlm:BADeleteMacro outputdir="${ci.cleanup.env.dir}" rootdir="${prep.root.dir}" no.ba.remain="${ci.min.ba.maintain}"/> |
|
145 </target> |
|
146 |
|
147 <!-- This task monitor the sessions available under the session file and update/create new ones if needed. --> |
|
148 <scriptdef name="monitorCCMSession" language="jython" uri="http://www.nokia.com/helium"> |
|
149 <attribute name="delivery"/> |
|
150 <attribute name="sessionfile"/> |
|
151 import ccm |
|
152 import nokia.nokiaccm |
|
153 import configuration |
|
154 import os |
|
155 import logging |
|
156 import traceback |
|
157 logging.basicConfig(level=logging.INFO) |
|
158 |
|
159 databases = [] |
|
160 delivery = str(attributes.get('delivery')) |
|
161 sessionFile = str(attributes.get('sessionfile')) |
|
162 configBuilder = configuration.NestedConfigurationBuilder(open(delivery, 'r')) |
|
163 configSet = configBuilder.getConfiguration() |
|
164 for config in configSet.getConfigurations(): |
|
165 if config['database'] not in databases: |
|
166 databases.append(config['database']) |
|
167 |
|
168 config = configuration.PropertiesConfiguration() |
|
169 if os.path.exists(sessionFile): |
|
170 self.log(str("Opening the file %s..." % sessionFile)) |
|
171 config.load(open(sessionFile, 'r')) |
|
172 else: |
|
173 self.log(str("File %s will be created..." % sessionFile)) |
|
174 |
|
175 for database in databases: |
|
176 self.log(str("Checking %s..." % database)) |
|
177 update_session = True |
|
178 if config.has_key(database): |
|
179 sessionid = config[database] |
|
180 # test if valid |
|
181 self.log(str("Is session %s still valid?..." % sessionid)) |
|
182 if ccm.session_exists(sessionid, database=database): |
|
183 self.log(str("Yes.")) |
|
184 update_session = False |
|
185 |
|
186 if update_session: |
|
187 try: |
|
188 self.log(str("Opening a new session for %s..." % database)) |
|
189 session = nokia.nokiaccm.open_session(database=database) |
|
190 session.close_on_exit = False |
|
191 config[database] = session.addr() |
|
192 except Exception, exc: |
|
193 traceback.print_exc() |
|
194 raise exc |
|
195 |
|
196 self.log(str("Updating the file %s..." % sessionFile)) |
|
197 config.store(open(sessionFile, 'w+')) |
|
198 </scriptdef> |
|
199 |
|
200 <!-- Task that generates an XML configuration of the work that will be done by ccm-get-input. --> |
|
201 <macrodef name="findProjects" uri="http://www.nokia.com/helium"> |
|
202 <attribute name="delivery"/> |
|
203 <attribute name="sessionfile"/> |
|
204 <attribute name="output"/> |
|
205 <sequential> |
|
206 <hlm:python> |
|
207 import ccm |
|
208 import configuration |
|
209 import os |
|
210 import logging |
|
211 import amara |
|
212 |
|
213 logging.basicConfig(level=logging.INFO) |
|
214 |
|
215 delivery = str(r'@{delivery}') |
|
216 sessionFile = str(r'@{sessionfile}') |
|
217 outputFilename = str(r'@{output}') |
|
218 |
|
219 sconfig = configuration.PropertiesConfiguration() |
|
220 |
|
221 print "Opening the file %s..." % sessionFile |
|
222 sconfig.load(open(sessionFile, 'r')) |
|
223 |
|
224 configBuilder = configuration.NestedConfigurationBuilder(open(delivery, 'r')) |
|
225 configSet = configBuilder.getConfiguration() |
|
226 projects = [] |
|
227 for config in configSet.getConfigurations(): |
|
228 if config.type == "checkout" and not config.get_boolean('skip.ci', False): |
|
229 try: |
|
230 sessionid = sconfig[config['database']] |
|
231 session = ccm.Session(None, None, None, ccm_addr=sessionid, close_on_exit=False) |
|
232 ccmproject = session.create(config.name) |
|
233 wapath = os.path.join(config['dir'], ccmproject.name, ccmproject.name) |
|
234 result = session.get_workarea_info(wapath) |
|
235 print "Found wa for project %s." % result['project'].objectname |
|
236 if config.has_key('ci.custom.query'): |
|
237 projects.append({u'database': unicode(config['database']), u'action': u'checkout', u'name': unicode(result['project'].objectname), u'customQuery': unicode(config['ci.custom.query'])}) |
|
238 else: |
|
239 projects.append({u'database': unicode(config['database']), u'action': u'checkout', u'name': unicode(result['project'].objectname)}) |
|
240 except ccm.CCMException, exc: |
|
241 projects.append({u'database': unicode(config['database']), u'action': u'to_be_checkout', u'name': unicode(config.name)}) |
|
242 elif config.type == "snapshot" and not config.get_boolean('skip.ci', False): |
|
243 sessionid = sconfig[config['database']] |
|
244 session = ccm.Session(None, None, None, ccm_addr=sessionid, close_on_exit=False) |
|
245 ccmproject = session.create(config.name) |
|
246 versionfile = os.path.join(config['dir'], ccmproject.name, 'project.version') |
|
247 if (os.path.exists(versionfile)): |
|
248 stream = open(versionfile, "r") |
|
249 projectname = stream.read().strip() |
|
250 stream.close() |
|
251 if (projectname != config.name): |
|
252 if config.has_key('ci.custom.query'): |
|
253 projects.append({u'database': unicode(config['database']), u'action': u'snapshot_update', u'name': unicode(config.name), u'customQuery': unicode(config['ci.custom.query'])}) |
|
254 else: |
|
255 projects.append({u'database': unicode(config['database']), u'action': u'snapshot_update', u'name': unicode(config.name)}) |
|
256 else: |
|
257 if config.has_key('ci.custom.query'): |
|
258 projects.append({u'database': unicode(config['database']), u'action': u'snapshot', u'name': unicode(config.name), u'customQuery': unicode(config['ci.custom.query'])}) |
|
259 else: |
|
260 projects.append({u'database': unicode(config['database']), u'action': u'snapshot', u'name': unicode(config.name)}) |
|
261 |
|
262 doc = amara.create_document() |
|
263 root = doc.xml_create_element(u"config") |
|
264 doc.xml_append(root) |
|
265 |
|
266 for project in projects: |
|
267 p = doc.xml_create_element(u"project", attributes=project) |
|
268 root.xml_append(p) |
|
269 |
|
270 output = open(outputFilename, "w+") |
|
271 output.write(doc.xml()) |
|
272 output.close() |
|
273 </hlm:python> |
|
274 </sequential> |
|
275 </macrodef> |
|
276 |
|
277 <!-- Validate input for the ci-monitor-ccm-session target --> |
|
278 <target name="ci-monitor-ccm-session-validate" depends="ccm-prepare-input"> |
|
279 <if> |
|
280 <and> |
|
281 <available file="${prep.delivery.conf.parsed}"/> |
|
282 <isset property="ci.session.file"/> |
|
283 <isset property="run.ccm"/> |
|
284 </and> |
|
285 <then> |
|
286 <property name="do.ci-monitor-ccm-session" value="true"/> |
|
287 </then> |
|
288 <else> |
|
289 <echo>Delivery file not available or 'ci.session.file' not defined or ccm.enabled not set to true.</echo> |
|
290 </else> |
|
291 </if> |
|
292 </target> |
|
293 |
|
294 <!-- Validate input for the ci-prep-wa-create-list target. --> |
|
295 <target name="ci-prep-wa-create-list-validate" depends="ci-monitor-ccm-session-validate" if="do.ci-monitor-ccm-session"> |
|
296 <if> |
|
297 <and> |
|
298 <isset property="ci.project.config"/> |
|
299 </and> |
|
300 <then> |
|
301 <property name="do.ci-prep-wa-create-list" value="true"/> |
|
302 </then> |
|
303 <else> |
|
304 <echo>'ci.project.config' not defined.</echo> |
|
305 </else> |
|
306 </if> |
|
307 </target> |
|
308 |
|
309 <!-- Bootstrapper target for Cruise Control. It generates a session file compatible with CCM task. --> |
|
310 <target name="ci-monitor-ccm-session" depends="ci-monitor-ccm-session-validate" if="do.ci-monitor-ccm-session"> |
|
311 <hlm:monitorCCMSession delivery="${prep.delivery.conf.parsed}" sessionfile="${ci.session.file}"/> |
|
312 </target> |
|
313 |
|
314 <!-- Bootstrapper target for Cruise Control. This target output the future work that ccm-get-input will be doing. --> |
|
315 <target name="ci-prep-wa-create-list" depends="ci-prep-wa-create-list-validate" if="do.ci-prep-wa-create-list"> |
|
316 <hlm:findProjects delivery="${prep.delivery.conf.parsed}" sessionfile="${ci.session.file}" output="${ci.project.config}"/> |
|
317 </target> |
|
318 |
|
319 </project> |