Andrew Geissler | 9aee500 | 2022-03-30 16:27:02 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # ex:ts=4:sw=4:sts=4:et |
| 3 | # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- |
| 4 | # |
| 5 | # Generate Toaster Fixtures for 'poky.xml' and 'oe-core.xml' |
| 6 | # |
| 7 | # Copyright (C) 2022 Wind River Systems |
| 8 | # SPDX-License-Identifier: GPL-2.0-only |
| 9 | # |
| 10 | # Edit the 'current_releases' table for each new release cycle |
| 11 | # |
| 12 | # Usage: ./get_fixtures all |
| 13 | # |
| 14 | |
| 15 | import os |
| 16 | import sys |
| 17 | import argparse |
| 18 | |
| 19 | verbose = False |
| 20 | |
| 21 | #################################### |
| 22 | # Releases |
| 23 | # |
| 24 | # https://wiki.yoctoproject.org/wiki/Releases |
| 25 | # |
| 26 | # NOTE: for the current releases table, it helps to keep continuing releases |
| 27 | # in the same table positions since this minimizes the patch diff for review. |
| 28 | # The order of the table does not matter since Toaster presents them sorted. |
| 29 | # |
| 30 | # Traditionally, the two most current releases are included in addition to the |
| 31 | # 'master' branch and the local installation's 'HEAD'. |
| 32 | # It is also policy to include all active LTS releases. |
| 33 | # |
| 34 | |
| 35 | # [Codename, Yocto Project Version, Release Date, Current Version, Support Level, Poky Version, BitBake branch] |
| 36 | current_releases = [ |
| 37 | # Release slot #1 |
| 38 | ['Kirkstone','3.5','April 2022','','Future - Long Term Support (until Apr. 2024)','27.0','1.54'], |
| 39 | # ['Dunfell','3.1','April 2021','3.1.5 (March 2022)','Stable - Support for 13 months (until Apr. 2022)','23.0','1.46'], |
| 40 | # Release slot #2 'local' |
| 41 | ['HEAD','HEAD','','Local Yocto Project','HEAD','','HEAD'], |
| 42 | # Release slot #3 'master' |
| 43 | ['Master','master','','Yocto Project master','master','','master'], |
| 44 | # Release slot #4 |
| 45 | ['Honister','3.4','October 2021','3.4.2 (February 2022)','Support for 7 months (until May 2022)','26.0','1.52'], |
| 46 | # ['Gatesgarth','3.2','Oct 2020','3.2.4 (May 2021)','EOL','24.0','1.48'], |
| 47 | # Optional Release slot #4 |
| 48 | ['Hardknott','3.3','April 2021','3.3.5 (March 2022)','Stable - Support for 13 months (until Apr. 2022)','25.0','1.50'], |
| 49 | ] |
| 50 | |
| 51 | default_poky_layers = [ |
| 52 | 'openembedded-core', |
| 53 | 'meta-poky', |
| 54 | 'meta-yocto-bsp', |
| 55 | ] |
| 56 | |
| 57 | default_oe_core_layers = [ |
| 58 | 'openembedded-core', |
| 59 | ] |
| 60 | |
| 61 | #################################### |
| 62 | # Templates |
| 63 | |
| 64 | prolog_template = '''\ |
| 65 | <?xml version="1.0" encoding="utf-8"?> |
| 66 | <django-objects version="1.0"> |
| 67 | <!-- Set the project default value for DISTRO --> |
| 68 | <object model="orm.toastersetting" pk="1"> |
| 69 | <field type="CharField" name="name">DEFCONF_DISTRO</field> |
| 70 | <field type="CharField" name="value">{{distro}}</field> |
| 71 | </object> |
| 72 | ''' |
| 73 | |
| 74 | #<!-- Bitbake versions which correspond to the metadata release -->') |
| 75 | bitbakeversion_poky_template = '''\ |
| 76 | <object model="orm.bitbakeversion" pk="{{bitbake_id}}"> |
| 77 | <field type="CharField" name="name">{{name}}</field> |
| 78 | <field type="CharField" name="giturl">git://git.yoctoproject.org/poky</field> |
| 79 | <field type="CharField" name="branch">{{branch}}</field> |
| 80 | <field type="CharField" name="dirpath">bitbake</field> |
| 81 | </object> |
| 82 | ''' |
| 83 | bitbakeversion_oecore_template = '''\ |
| 84 | <object model="orm.bitbakeversion" pk="{{bitbake_id}}"> |
| 85 | <field type="CharField" name="name">{{name}}</field> |
| 86 | <field type="CharField" name="giturl">git://git.openembedded.org/bitbake</field> |
| 87 | <field type="CharField" name="branch">{{bitbakeversion}}</field> |
| 88 | </object> |
| 89 | ''' |
| 90 | |
| 91 | # <!-- Releases available --> |
| 92 | releases_available_template = '''\ |
| 93 | <object model="orm.release" pk="{{ra_count}}"> |
| 94 | <field type="CharField" name="name">{{name}}</field> |
| 95 | <field type="CharField" name="description">{{description}}</field> |
| 96 | <field rel="ManyToOneRel" to="orm.bitbakeversion" name="bitbake_version">{{ra_count}}</field> |
| 97 | <field type="CharField" name="branch_name">{{release}}</field> |
| 98 | <field type="TextField" name="helptext">Toaster will run your builds {{help_source}}.</field> |
| 99 | </object> |
| 100 | ''' |
| 101 | |
| 102 | # <!-- Default project layers for each release --> |
| 103 | default_layers_template = '''\ |
| 104 | <object model="orm.releasedefaultlayer" pk="{{rdl_count}}"> |
| 105 | <field rel="ManyToOneRel" to="orm.release" name="release">{{release_id}}</field> |
| 106 | <field type="CharField" name="layer_name">{{layer}}</field> |
| 107 | </object> |
| 108 | ''' |
| 109 | |
| 110 | default_layers_preface = '''\ |
| 111 | <!-- Default layers provided by poky |
| 112 | openembedded-core |
| 113 | meta-poky |
| 114 | meta-yocto-bsp |
| 115 | --> |
| 116 | ''' |
| 117 | |
| 118 | layer_poky_template = '''\ |
| 119 | <object model="orm.layer" pk="{{layer_id}}"> |
| 120 | <field type="CharField" name="name">{{layer}}</field> |
| 121 | <field type="CharField" name="layer_index_url"></field> |
| 122 | <field type="CharField" name="vcs_url">{{vcs_url}}</field> |
| 123 | <field type="CharField" name="vcs_web_url">{{vcs_web_url}}</field> |
| 124 | <field type="CharField" name="vcs_web_tree_base_url">{{vcs_web_tree_base_url}}</field> |
| 125 | <field type="CharField" name="vcs_web_file_base_url">{{vcs_web_file_base_url}}</field> |
| 126 | </object> |
| 127 | ''' |
| 128 | |
| 129 | layer_oe_core_template = '''\ |
| 130 | <object model="orm.layer" pk="{{layer_id}}"> |
| 131 | <field type="CharField" name="name">{{layer}}</field> |
| 132 | <field type="CharField" name="vcs_url">{{vcs_url}}</field> |
| 133 | <field type="CharField" name="vcs_web_url">{{vcs_web_url}}</field> |
| 134 | <field type="CharField" name="vcs_web_tree_base_url">{{vcs_web_tree_base_url}}</field> |
| 135 | <field type="CharField" name="vcs_web_file_base_url">{{vcs_web_file_base_url}}</field> |
| 136 | </object> |
| 137 | ''' |
| 138 | |
| 139 | layer_version_template = '''\ |
| 140 | <object model="orm.layer_version" pk="{{lv_count}}"> |
| 141 | <field rel="ManyToOneRel" to="orm.layer" name="layer">{{layer_id}}</field> |
| 142 | <field type="IntegerField" name="layer_source">0</field> |
| 143 | <field rel="ManyToOneRel" to="orm.release" name="release">{{release_id}}</field> |
| 144 | <field type="CharField" name="branch">{{branch}}</field> |
| 145 | <field type="CharField" name="dirpath">{{dirpath}}</field> |
| 146 | </object> |
| 147 | ''' |
| 148 | |
| 149 | layer_version_HEAD_template = '''\ |
| 150 | <object model="orm.layer_version" pk="{{lv_count}}"> |
| 151 | <field rel="ManyToOneRel" to="orm.layer" name="layer">{{layer_id}}</field> |
| 152 | <field type="IntegerField" name="layer_source">0</field> |
| 153 | <field rel="ManyToOneRel" to="orm.release" name="release">{{release_id}}</field> |
| 154 | <field type="CharField" name="branch">{{branch}}</field> |
| 155 | <field type="CharField" name="commit">{{commit}}</field> |
| 156 | <field type="CharField" name="dirpath">{{dirpath}}</field> |
| 157 | </object> |
| 158 | ''' |
| 159 | |
| 160 | layer_version_oe_core_template = '''\ |
| 161 | <object model="orm.layer_version" pk="1"> |
| 162 | <field rel="ManyToOneRel" to="orm.layer" name="layer">1</field> |
| 163 | <field rel="ManyToOneRel" to="orm.release" name="release">2</field> |
| 164 | <field type="CharField" name="local_path">OE-CORE-LAYER-DIR</field> |
| 165 | <field type="CharField" name="branch">HEAD</field> |
| 166 | <field type="CharField" name="dirpath">meta</field> |
| 167 | <field type="IntegerField" name="layer_source">0</field> |
| 168 | </object> |
| 169 | ''' |
| 170 | |
| 171 | epilog_template = '''\ |
| 172 | </django-objects> |
| 173 | ''' |
| 174 | |
| 175 | ################################# |
| 176 | # Helper Routines |
| 177 | # |
| 178 | |
| 179 | def print_str(str,fd): |
| 180 | # Avoid extra newline at end |
| 181 | if str and (str[-1] == '\n'): |
| 182 | str = str[0:-1] |
| 183 | print(str,file=fd) |
| 184 | |
| 185 | def print_template(template,params,fd): |
| 186 | for line in template.split('\n'): |
| 187 | p = line.find('{{') |
| 188 | while p > 0: |
| 189 | q = line.find('}}') |
| 190 | key = line[p+2:q] |
| 191 | if key in params: |
| 192 | line = line[0:p] + params[key] + line[q+2:] |
| 193 | else: |
| 194 | line = line[0:p] + '?' + key + '?' + line[q+2:] |
| 195 | p = line.find('{{') |
| 196 | if line: |
| 197 | print(line,file=fd) |
| 198 | |
| 199 | ################################# |
| 200 | # Generate poky.xml |
| 201 | # |
| 202 | |
| 203 | def generate_poky(): |
| 204 | fd = open('poky.xml','w') |
| 205 | |
| 206 | params = {} |
| 207 | params['distro'] = 'poky' |
| 208 | print_template(prolog_template,params,fd) |
| 209 | print_str('',fd) |
| 210 | |
| 211 | print_str(' <!-- Bitbake versions which correspond to the metadata release -->',fd) |
| 212 | for i,release in enumerate(current_releases): |
| 213 | params = {} |
| 214 | params['release'] = release[0] |
| 215 | params['Release'] = release[0] |
| 216 | params['release_version'] = release[1] |
| 217 | if not (params['release'] in ('HEAD')): # 'master', |
| 218 | params['release'] = params['release'][0].lower() + params['release'][1:] |
| 219 | params['name'] = params['release'] |
| 220 | params['bitbake_id'] = str(i+1) |
| 221 | params['branch'] = params['release'] |
| 222 | print_template(bitbakeversion_poky_template,params,fd) |
| 223 | print_str('',fd) |
| 224 | |
| 225 | print_str('',fd) |
| 226 | print_str(' <!-- Releases available -->',fd) |
| 227 | for i,release in enumerate(current_releases): |
| 228 | params = {} |
| 229 | params['release'] = release[0] |
| 230 | params['Release'] = release[0] |
| 231 | params['release_version'] = release[1] |
| 232 | if not (params['release'] in ('HEAD')): #'master', |
| 233 | params['release'] = params['release'][0].lower() + params['release'][1:] |
| 234 | params['h_release'] = '?h={{release}}' |
| 235 | params['name'] = params['release'] |
| 236 | params['ra_count'] = str(i+1) |
| 237 | params['branch'] = params['release'] |
| 238 | |
| 239 | if 'HEAD' == params['release']: |
| 240 | params['help_source'] = 'with the version of the Yocto Project you have cloned or downloaded to your computer' |
| 241 | params['description'] = 'Local Yocto Project' |
| 242 | params['name'] = 'local' |
| 243 | else: |
| 244 | params['help_source'] = 'using the tip of the <a href="https://git.yoctoproject.org/cgit/cgit.cgi/poky/log/{{h_release}}">Yocto Project {{Release}} branch</a>' |
| 245 | params['description'] = 'Yocto Project {{release_version}} "{{Release}}"' |
| 246 | if 'master' == params['release']: |
| 247 | params['h_release'] = '' |
| 248 | params['description'] = 'Yocto Project master' |
| 249 | |
| 250 | print_template(releases_available_template,params,fd) |
| 251 | print_str('',fd) |
| 252 | |
| 253 | print_str(' <!-- Default project layers for each release -->',fd) |
| 254 | rdl_count = 1 |
| 255 | for i,release in enumerate(current_releases): |
| 256 | for j,layer in enumerate(default_poky_layers): |
| 257 | params = {} |
| 258 | params['layer'] = layer |
| 259 | params['release'] = release[0] |
| 260 | params['Release'] = release[0] |
| 261 | params['release_version'] = release[1] |
| 262 | if not (params['release'] in ('master','HEAD')): |
| 263 | params['release'] = params['release'][0].lower() + params['release'][1:] |
| 264 | params['release_id'] = str(i+1) |
| 265 | params['rdl_count'] = str(rdl_count) |
| 266 | params['branch'] = params['release'] |
| 267 | print_template(default_layers_template,params,fd) |
| 268 | rdl_count += 1 |
| 269 | print_str('',fd) |
| 270 | |
| 271 | print_str(default_layers_preface,fd) |
| 272 | lv_count = 1 |
| 273 | for i,layer in enumerate(default_poky_layers): |
| 274 | params = {} |
| 275 | params['layer'] = layer |
| 276 | params['layer_id'] = str(i+1) |
| 277 | params['vcs_url'] = 'git://git.yoctoproject.org/poky' |
| 278 | params['vcs_web_url'] = 'https://git.yoctoproject.org/cgit/cgit.cgi/poky' |
| 279 | params['vcs_web_tree_base_url'] = 'https://git.yoctoproject.org/cgit/cgit.cgi/poky/tree/%path%?h=%branch%' |
| 280 | params['vcs_web_file_base_url'] = 'https://git.yoctoproject.org/cgit/cgit.cgi/poky/tree/%path%?h=%branch%' |
| 281 | |
| 282 | if i: |
| 283 | print_str('',fd) |
| 284 | print_template(layer_poky_template,params,fd) |
| 285 | for j,release in enumerate(current_releases): |
| 286 | params['release'] = release[0] |
| 287 | params['Release'] = release[0] |
| 288 | params['release_version'] = release[1] |
| 289 | if not (params['release'] in ('master','HEAD')): |
| 290 | params['release'] = params['release'][0].lower() + params['release'][1:] |
| 291 | params['release_id'] = str(j+1) |
| 292 | params['lv_count'] = str(lv_count) |
| 293 | params['branch'] = params['release'] |
| 294 | params['commit'] = params['release'] |
| 295 | |
| 296 | params['dirpath'] = params['layer'] |
| 297 | if params['layer'] in ('openembedded-core'): #'openembedded-core', |
| 298 | params['dirpath'] = 'meta' |
| 299 | |
| 300 | if 'HEAD' == params['release']: |
| 301 | print_template(layer_version_HEAD_template,params,fd) |
| 302 | else: |
| 303 | print_template(layer_version_template,params,fd) |
| 304 | lv_count += 1 |
| 305 | |
| 306 | print_str(epilog_template,fd) |
| 307 | fd.close() |
| 308 | |
| 309 | ################################# |
| 310 | # Generate oe-core.xml |
| 311 | # |
| 312 | |
| 313 | def generate_oe_core(): |
| 314 | fd = open('oe-core.xml','w') |
| 315 | |
| 316 | params = {} |
| 317 | params['distro'] = 'nodistro' |
| 318 | print_template(prolog_template,params,fd) |
| 319 | print_str('',fd) |
| 320 | |
| 321 | print_str(' <!-- Bitbake versions which correspond to the metadata release -->',fd) |
| 322 | for i,release in enumerate(current_releases): |
| 323 | params = {} |
| 324 | params['release'] = release[0] |
| 325 | params['Release'] = release[0] |
| 326 | params['bitbakeversion'] = release[6] |
| 327 | params['release_version'] = release[1] |
| 328 | if not (params['release'] in ('HEAD')): # 'master', |
| 329 | params['release'] = params['release'][0].lower() + params['release'][1:] |
| 330 | params['name'] = params['release'] |
| 331 | params['bitbake_id'] = str(i+1) |
| 332 | params['branch'] = params['release'] |
| 333 | print_template(bitbakeversion_oecore_template,params,fd) |
| 334 | print_str('',fd) |
| 335 | |
| 336 | print_str(' <!-- Releases available -->',fd) |
| 337 | for i,release in enumerate(current_releases): |
| 338 | params = {} |
| 339 | params['release'] = release[0] |
| 340 | params['Release'] = release[0] |
| 341 | params['release_version'] = release[1] |
| 342 | if not (params['release'] in ('HEAD')): #'master', |
| 343 | params['release'] = params['release'][0].lower() + params['release'][1:] |
| 344 | params['h_release'] = '?h={{release}}' |
| 345 | params['name'] = params['release'] |
| 346 | params['ra_count'] = str(i+1) |
| 347 | params['branch'] = params['release'] |
| 348 | |
| 349 | if 'HEAD' == params['release']: |
| 350 | params['help_source'] = 'with the version of OpenEmbedded that you have cloned or downloaded to your computer' |
| 351 | params['description'] = 'Local Openembedded' |
| 352 | params['name'] = 'local' |
| 353 | else: |
| 354 | params['help_source'] = 'using the tip of the <a href=\\"https://cgit.openembedded.org/openembedded-core/log/{{h_release}}\\">OpenEmbedded {{Release}}</a> branch' |
| 355 | params['description'] = 'Openembedded {{Release}}' |
| 356 | if 'master' == params['release']: |
| 357 | params['h_release'] = '' |
| 358 | params['description'] = 'OpenEmbedded core master' |
| 359 | params['Release'] = params['release'] |
| 360 | |
| 361 | print_template(releases_available_template,params,fd) |
| 362 | print_str('',fd) |
| 363 | |
| 364 | print_str(' <!-- Default layers for each release -->',fd) |
| 365 | rdl_count = 1 |
| 366 | for i,release in enumerate(current_releases): |
| 367 | for j,layer in enumerate(default_oe_core_layers): |
| 368 | params = {} |
| 369 | params['layer'] = layer |
| 370 | params['release'] = release[0] |
| 371 | params['Release'] = release[0] |
| 372 | params['release_version'] = release[1] |
| 373 | if not (params['release'] in ('master','HEAD')): |
| 374 | params['release'] = params['release'][0].lower() + params['release'][1:] |
| 375 | params['release_id'] = str(i+1) |
| 376 | params['rdl_count'] = str(rdl_count) |
| 377 | params['branch'] = params['release'] |
| 378 | print_template(default_layers_template,params,fd) |
| 379 | rdl_count += 1 |
| 380 | print_str('',fd) |
| 381 | |
| 382 | print_str('',fd) |
| 383 | print_str(' <!-- Layer for the Local release -->',fd) |
| 384 | lv_count = 1 |
| 385 | for i,layer in enumerate(default_oe_core_layers): |
| 386 | params = {} |
| 387 | params['layer'] = layer |
| 388 | params['layer_id'] = str(i+1) |
| 389 | params['vcs_url'] = 'git://git.openembedded.org/openembedded-core' |
| 390 | params['vcs_web_url'] = 'https://cgit.openembedded.org/openembedded-core' |
| 391 | params['vcs_web_tree_base_url'] = 'https://cgit.openembedded.org/openembedded-core/tree/%path%?h=%branch%' |
| 392 | params['vcs_web_file_base_url'] = 'https://cgit.openembedded.org/openembedded-core/tree/%path%?h=%branch%' |
| 393 | if i: |
| 394 | print_str('',fd) |
| 395 | print_template(layer_oe_core_template,params,fd) |
| 396 | |
| 397 | print_template(layer_version_oe_core_template,params,fd) |
| 398 | print_str('',fd) |
| 399 | |
| 400 | print_str(epilog_template,fd) |
| 401 | fd.close() |
| 402 | |
| 403 | ################################# |
| 404 | # Help |
| 405 | # |
| 406 | |
| 407 | def list_releases(): |
| 408 | print("Release ReleaseVer BitbakeVer Support Level") |
| 409 | print("========== =========== ========== ==============================================") |
| 410 | for release in current_releases: |
| 411 | print("%10s %10s %11s %s" % (release[0],release[1],release[6],release[4])) |
| 412 | |
| 413 | ################################# |
| 414 | # main |
| 415 | # |
| 416 | |
| 417 | def main(argv): |
| 418 | global verbose |
| 419 | |
| 420 | parser = argparse.ArgumentParser(description='gen_fixtures.py: table generate the fixture files') |
| 421 | parser.add_argument('--poky', '-p', action='store_const', const='poky', dest='command', help='Generate the poky.xml file') |
| 422 | parser.add_argument('--oe-core', '-o', action='store_const', const='oe_core', dest='command', help='Generate the oe-core.xml file') |
| 423 | parser.add_argument('--all', '-a', action='store_const', const='all', dest='command', help='Generate all fixture files') |
| 424 | parser.add_argument('--list', '-l', action='store_const', const='list', dest='command', help='List the release table') |
| 425 | parser.add_argument('--verbose', '-v', action='store_true', dest='verbose', help='Enable verbose debugging output') |
| 426 | args = parser.parse_args() |
| 427 | |
| 428 | verbose = args.verbose |
| 429 | if 'poky' == args.command: |
| 430 | generate_poky() |
| 431 | elif 'oe_core' == args.command: |
| 432 | generate_oe_core() |
| 433 | elif 'all' == args.command: |
| 434 | generate_poky() |
| 435 | generate_oe_core() |
| 436 | elif 'all' == args.command: |
| 437 | list_releases() |
| 438 | elif 'list' == args.command: |
| 439 | list_releases() |
| 440 | |
| 441 | else: |
| 442 | print("No command for 'gen_fixtures.py' selected") |
| 443 | |
| 444 | if __name__ == '__main__': |
| 445 | main(sys.argv[1:]) |