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