blob: efaebe43b5867fd37cbe5087505fe2158beea8f0 [file] [log] [blame]
Andrew Geissler9aee5002022-03-30 16:27:02 +00001#!/usr/bin/env python3
2#
3# Add version information to poky.yaml based upon current git branch/tags
Patrick Williamsdb4c27e2022-08-05 08:10:29 -05004# Also generate the list of available manuals (releases.rst file)
Andrew Geissler9aee5002022-03-30 16:27:02 +00005#
6# Copyright Linux Foundation
7# Author: Richard Purdie <richard.purdie@linuxfoundation.org>
Patrick Williamsdb4c27e2022-08-05 08:10:29 -05008# Author: Quentin Schulz <foss@0leil.net>
Andrew Geissler9aee5002022-03-30 16:27:02 +00009#
10# SPDX-License-Identifier: MIT
11#
12
13
14import subprocess
15import collections
16import sys
17import os
18import itertools
Patrick Williamsdb4c27e2022-08-05 08:10:29 -050019import re
Andrew Geissler9aee5002022-03-30 16:27:02 +000020
21ourversion = None
22if len(sys.argv) == 2:
23 ourversion = sys.argv[1]
24
25ourversion = None
26if len(sys.argv) == 2:
27 ourversion = sys.argv[1]
28
Patrick Williams2390b1b2022-11-03 13:47:49 -050029activereleases = ["langdale", "kirkstone", "dunfell"]
30devbranch = "mickledore"
Andrew Geissler9aee5002022-03-30 16:27:02 +000031ltsseries = ["kirkstone", "dunfell"]
32
Patrick Williams03907ee2022-05-01 06:28:52 -050033# used by run-docs-builds to get the default page
34if ourversion == "getlatest":
35 print(activereleases[0])
36 sys.exit(0)
37
Andrew Geissler9aee5002022-03-30 16:27:02 +000038release_series = collections.OrderedDict()
Patrick Williams2390b1b2022-11-03 13:47:49 -050039release_series["mickledore"] = "4.2"
Patrick Williams03907ee2022-05-01 06:28:52 -050040release_series["langdale"] = "4.1"
Andrew Geissler9aee5002022-03-30 16:27:02 +000041release_series["kirkstone"] = "4.0"
42release_series["honister"] = "3.4"
43release_series["hardknott"] = "3.3"
44release_series["gatesgarth"] = "3.2"
45release_series["dunfell"] = "3.1"
46release_series["zeus"] = "3.0"
47release_series["warrior"] = "2.7"
48release_series["thud"] = "2.6"
49release_series["sumo"] = "2.5"
50release_series["rocko"] = "2.4"
51release_series["pyro"] = "2.3"
52release_series["morty"] = "2.2"
53release_series["krogoth"] = "2.1"
54release_series["jethro"] = "2.0"
55release_series["jethro-pre"] = "1.9"
56release_series["fido"] = "1.8"
57release_series["dizzy"] = "1.7"
58release_series["daisy"] = "1.6"
59release_series["dora"] = "1.5"
60release_series["dylan"] = "1.4"
61release_series["danny"] = "1.3"
62release_series["denzil"] = "1.2"
63release_series["edison"] = "1.1"
64release_series["bernard"] = "1.0"
65release_series["laverne"] = "0.9"
66
67
Andrew Geissler9aee5002022-03-30 16:27:02 +000068bitbake_mapping = {
Patrick Williams2390b1b2022-11-03 13:47:49 -050069 "mickledore" : "2.4",
Patrick Williams03907ee2022-05-01 06:28:52 -050070 "langdale" : "2.2",
Andrew Geissler9aee5002022-03-30 16:27:02 +000071 "kirkstone" : "2.0",
72 "honister" : "1.52",
73 "hardknott" : "1.50",
74 "gatesgarth" : "1.48",
75 "dunfell" : "1.46",
76}
77
78# 3.4 onwards doesn't have poky version
79# Early 3.4 release docs do reference it though
80poky_mapping = {
81 "3.4" : "26.0",
82 "3.3" : "25.0",
83 "3.2" : "24.0",
84 "3.1" : "23.0",
85}
86
87ourseries = None
88ourbranch = None
89bitbakeversion = None
90docconfver = None
91
92# Test tags exist and inform the user to fetch if not
93try:
Andrew Geissler78b72792022-06-14 06:47:25 -050094 subprocess.run(["git", "show", "yocto-%s" % release_series[activereleases[0]]], capture_output=True, check=True)
Andrew Geissler9aee5002022-03-30 16:27:02 +000095except subprocess.CalledProcessError:
96 sys.exit("Please run 'git fetch --tags' before building the documentation")
97
98# Try and figure out what we are
99tags = subprocess.run(["git", "tag", "--points-at", "HEAD"], capture_output=True, text=True).stdout
100for t in tags.split():
101 if t.startswith("yocto-"):
102 ourversion = t[6:]
103
104if ourversion:
105 # We're a tagged release
106 components = ourversion.split(".")
107 baseversion = components[0] + "." + components[1]
108 docconfver = ourversion
109 for i in release_series:
110 if release_series[i] == baseversion:
111 ourseries = i
112 ourbranch = i
113 if i in bitbake_mapping:
114 bitbakeversion = bitbake_mapping[i]
115else:
116 # We're floating on a branch
117 branch = subprocess.run(["git", "branch", "--show-current"], capture_output=True, text=True).stdout.strip()
118 ourbranch = branch
119 if branch != "master" and branch not in release_series:
120 # We're not on a known release branch so we have to guess. Compare the numbers of commits
121 # from each release branch and assume the smallest number of commits is the one we're based off
122 possible_branch = None
123 branch_count = 0
124 for b in itertools.chain(release_series.keys(), ["master"]):
125 result = subprocess.run(["git", "log", "--format=oneline", "HEAD..origin/" + b], capture_output=True, text=True)
126 if result.returncode == 0:
127 count = result.stdout.count('\n')
128 if not possible_branch or count < branch_count:
129 print("Branch %s has count %s" % (b, count))
130 possible_branch = b
131 branch_count = count
132 if possible_branch:
133 branch = possible_branch
134 else:
135 branch = "master"
136 print("Nearest release branch estimated to be %s" % branch)
137 if branch == "master":
138 ourseries = devbranch
139 docconfver = "dev"
Patrick Williams03907ee2022-05-01 06:28:52 -0500140 bitbakeversion = "dev"
Andrew Geissler9aee5002022-03-30 16:27:02 +0000141 elif branch in release_series:
142 ourseries = branch
143 if branch in bitbake_mapping:
144 bitbakeversion = bitbake_mapping[branch]
145 else:
146 sys.exit("Unknown series for branch %s" % branch)
147
148 previoustags = subprocess.run(["git", "tag", "--merged", "HEAD"], capture_output=True, text=True).stdout
149 previoustags = [t[6:] for t in previoustags.split() if t.startswith("yocto-" + release_series[ourseries])]
150 futuretags = subprocess.run(["git", "tag", "--merged", ourbranch], capture_output=True, text=True).stdout
151 futuretags = [t[6:] for t in futuretags.split() if t.startswith("yocto-" + release_series[ourseries])]
152
153 # Append .999 against the last known version
154 if len(previoustags) != len(futuretags):
155 ourversion = previoustags[-1] + ".999"
156 else:
157 ourversion = release_series[ourseries] + ".999"
158 if not docconfver:
159 docconfver = ourversion
160
161series = [k for k in release_series]
162previousseries = series[series.index(ourseries)+1:] or [""]
163lastlts = [k for k in previousseries if k in ltsseries] or "dunfell"
164
165print("Version calculated to be %s" % ourversion)
166print("Release series calculated to be %s" % ourseries)
167
168replacements = {
169 "DISTRO" : ourversion,
170 "DISTRO_NAME_NO_CAP" : ourseries,
171 "DISTRO_NAME" : ourseries.capitalize(),
172 "DISTRO_NAME_NO_CAP_MINUS_ONE" : previousseries[0],
173 "DISTRO_NAME_NO_CAP_LTS" : lastlts[0],
174 "YOCTO_DOC_VERSION" : ourversion,
175 "DISTRO_REL_TAG" : "yocto-" + ourversion,
176 "DOCCONF_VERSION" : docconfver,
177 "BITBAKE_SERIES" : bitbakeversion,
178}
179
180if release_series[ourseries] in poky_mapping:
181 pokyversion = poky_mapping[release_series[ourseries]]
182 if ourversion != release_series[ourseries]:
183 pokyversion = pokyversion + "." + ourversion.rsplit(".", 1)[1]
184 else:
185 pokyversion = pokyversion + ".0"
186 replacements["POKYVERSION"] = pokyversion
187
188if os.path.exists("poky.yaml.in"):
189 with open("poky.yaml.in", "r") as r, open("poky.yaml", "w") as w:
190 lines = r.readlines()
191 for line in lines:
192 data = line.split(":")
193 k = data[0].strip()
194 if k in replacements:
195 w.write("%s : \"%s\"\n" % (k, replacements[k]))
196 else:
197 w.write(line)
198
199 print("poky.yaml generated from poky.yaml.in")
200
201
202# In the switcher list of versions we display:
203# - latest dev
204# - latest stable release
205# - latest LTS
206# - latest for each releases listed as active
207# - latest doc version in current series
208# - current doc version
209# (with duplicates removed)
210
Andrew Geissler9aee5002022-03-30 16:27:02 +0000211versions = []
212with open("sphinx-static/switchers.js.in", "r") as r, open("sphinx-static/switchers.js", "w") as w:
213 lines = r.readlines()
214 for line in lines:
Patrick Williams03907ee2022-05-01 06:28:52 -0500215 if "ALL_RELEASES_PLACEHOLDER" in line:
216 w.write(str(list(release_series.keys())))
217 continue
Andrew Geissler9aee5002022-03-30 16:27:02 +0000218 if "VERSIONS_PLACEHOLDER" in line:
Andrew Geisslerd5838332022-05-27 11:33:10 -0500219 w.write(" 'dev': { 'title': 'Unstable (dev)', 'obsolete': false,},\n")
Patrick Williams03907ee2022-05-01 06:28:52 -0500220 for branch in activereleases + ([ourseries] if ourseries not in activereleases else []):
Andrew Geissler9aee5002022-03-30 16:27:02 +0000221 if branch == devbranch:
222 continue
Patrick Williams03907ee2022-05-01 06:28:52 -0500223 branch_versions = subprocess.run('git tag --list yocto-%s*' % (release_series[branch]), shell=True, capture_output=True, text=True).stdout.split()
224 branch_versions = sorted([v.replace("yocto-" + release_series[branch] + ".", "").replace("yocto-" + release_series[branch], "0") for v in branch_versions], key=int)
225 if not branch_versions:
Andrew Geissler9aee5002022-03-30 16:27:02 +0000226 continue
227 version = release_series[branch]
Patrick Williams03907ee2022-05-01 06:28:52 -0500228 if branch_versions[-1] != "0":
229 version = version + "." + branch_versions[-1]
Andrew Geissler9aee5002022-03-30 16:27:02 +0000230 versions.append(version)
Andrew Geisslerd5838332022-05-27 11:33:10 -0500231 w.write(" '%s': {'title': '%s (%s)', 'obsolete': %s,},\n" % (version, branch.capitalize(), version, str(branch not in activereleases).lower()))
Andrew Geissler9aee5002022-03-30 16:27:02 +0000232 if ourversion not in versions and ourseries != devbranch:
Andrew Geisslerd5838332022-05-27 11:33:10 -0500233 w.write(" '%s': {'title': '%s (%s)', 'obsolete': %s,},\n" % (ourversion, ourseries.capitalize(), ourversion, str(ourseries not in activereleases).lower()))
Andrew Geissler9aee5002022-03-30 16:27:02 +0000234 else:
235 w.write(line)
236
237print("switchers.js generated from switchers.js.in")
238
Patrick Williamsdb4c27e2022-08-05 08:10:29 -0500239# generate releases.rst
240
241# list missing tags in yocto-docs
242missing_tags = [
243 'yocto-0.9',
244 'yocto-1.0', 'yocto-1.0.1',
245 'yocto-1.1', 'yocto-1.1.1',
246 'yocto-1.2',
247 'yocto-1.4.4', 'yocto-1.4.5',
248 'yocto-1.5', 'yocto-1.5.2', 'yocto-1.5.3', 'yocto-1.5.4',
249 'yocto-1.6', 'yocto-1.6.1', 'yocto-1.6.2',
250 'yocto-1.7', 'yocto-1.7.1',
251 'yocto-1.9',
252 'yocto-2.5.3',
253 'yocto-3.1', 'yocto-3.1.1', 'yocto-3.1.2', 'yocto-3.1.3',
254 ]
255
256semver = re.compile(r'yocto-(\d+)\.(\d+)(?:\.)?(\d*)')
257
258# git is able to properly order semver versions but not python
259# instead of adding a dependency on semver module, let's convert the version
260# into a decimal number, e.g. 11.23.1 will be 112301 and 1.5 will be 010500 so
261# it can be used as a key for the sorting algorithm.
262# This can be removed once all the old tags are re-created.
263def tag_to_semver_like(v):
264 v_semver = semver.search(v)
265 v_maj, v_min, v_patch = v_semver.groups('0')
266 return int("{:0>2}{:0>2}{:0>2}".format(v_maj, v_min, v_patch), 10)
267
268yocto_tags = subprocess.run(["git", "tag", "--list", "--sort=version:refname", "yocto-*"], capture_output=True, text=True).stdout
269yocto_tags = sorted(yocto_tags.split() + missing_tags, key=tag_to_semver_like)
270tags = [tag[6:] for tag in yocto_tags]
271
272with open('releases.rst', 'w') as f:
273 f.write('===========================\n')
274 f.write(' Supported Release Manuals\n')
275 f.write('===========================\n')
276 f.write('\n')
277
278 for activerelease in activereleases:
279 title = "Release Series %s (%s)" % (release_series[activerelease], activerelease)
280 f.write('*' * len(title) + '\n')
281 f.write(title + '\n')
282 f.write('*' * len(title) + '\n')
283 f.write('\n')
284
285 for tag in tags:
286 if tag == release_series[activerelease] or tag.startswith('%s.' % release_series[activerelease]):
287 f.write('- :yocto_docs:`%s Documentation </%s>`\n' % (tag, tag))
288 f.write('\n')
289
290 f.write('==========================\n')
291 f.write(' Outdated Release Manuals\n')
292 f.write('==========================\n')
293 f.write('\n')
294
295 for series in release_series:
296 if series == devbranch or series in activereleases:
297 continue
298
299 if series == "jethro-pre":
300 continue
301
302 title = "Release Series %s (%s)" % (release_series[series], series)
303 f.write('*' * len(title) + '\n')
304 f.write(title + '\n')
305 f.write('*' * len(title) + '\n')
306 f.write('\n')
307 if series == "jethro":
308 f.write('- :yocto_docs:`1.9 Documentation </1.9>`\n')
309 for tag in tags:
310 if tag == release_series[series] or tag.startswith('%s.' % release_series[series]):
311 f.write('- :yocto_docs:`%s Documentation </%s>`\n' % (tag, tag))
312 f.write('\n')