Skip to content

Commit 69e34b6

Browse files
committed
all: Switch to new preview build versioning scheme.
See micropython#12127 for details. Previously at the point when a release is made, we update mpconfig.h and set a git tag. i.e. the version increments at the release. Now the version increments immediately after the release. The workflow is: 1. Final commit in the cycle updates mpconfig.h to set (X, Y, 0, 0) (i.e. clear the pre-release state). 2. This commit is tagged "vX.Y.0". 3. First commit for the new cycle updates mpconfig.h to set (X, Y+1, 0, 1) (i.e. increment the minor version, set the pre-release state). 4. This commit is tagged "vX.Y+1.0-preview". The idea is that a nightly build is actually a "preview" of the _next_ release. i.e. any documentation describing the current release may not actually match the nightly build. So we use "preview" as our semver pre-release identifier. Changes in this commit: - Add MICROPY_VERSION_PRERELEASE to mpconfig.h to allow indicating that this is not a release version. - Remove unused MICROPY_VERSION integer. - Append "-preview" to MICROPY_VERSION_STRING when the pre-release state is set. - Update py/makeversionhdr.py to no longer generate MICROPY_GIT_HASH. - Remove the one place MICROPY_GIT_HASH was used (it can use MICROPY_GIT_TAG instead). - Update py/makeversionhdr.py to also understand MICROPY_VERSION_PRERELEASE in mpconfig.h. - Update py/makeversionhdr.py to convert the git-describe output into semver-compatible "X.Y.Z-preview.N.gHASH". - Update autobuild.sh to generate filenames using the new scheme. - Update remove_old_firmware.py to match new scheme. - Update mpremote's pyproject.toml to handle the "-preview" suffix in the tag. setuptools_scm maps to this "rc0" to match PEP440. - Fix docs heading where it incorrectly said "vvX.Y.Z" for release docs. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <[email protected]>
1 parent e00a144 commit 69e34b6

File tree

9 files changed

+117
-79
lines changed

9 files changed

+117
-79
lines changed

docs/conf.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121
# documentation root, use os.path.abspath to make it absolute, like shown here.
2222
sys.path.insert(0, os.path.abspath('.'))
2323

24-
# The members of the html_context dict are available inside topindex.html
24+
# The MICROPY_VERSION env var should be "vX.Y.Z" (or unset).
2525
micropy_version = os.getenv('MICROPY_VERSION') or 'latest'
2626
micropy_all_versions = (os.getenv('MICROPY_ALL_VERSIONS') or 'latest').split(',')
2727
url_pattern = '%s/en/%%s' % (os.getenv('MICROPY_URL_PREFIX') or '/',)
28+
29+
# The members of the html_context dict are available inside topindex.html
2830
html_context = {
2931
'cur_version':micropy_version,
3032
'all_versions':[

docs/templates/layout.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
{% if is_release %}
1010
<div class="wy-alert wy-alert-danger">
1111
<p>
12-
This is the v{{ release }} version of the MicroPython
12+
This is the {{ release }} version of the MicroPython
1313
documentation. The <a href="/en/latest/{{ pagename }}.html">latest
1414
development version</a> of this page may be more current.
1515
</p>

ports/cc3200/tools/update-wipy.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,9 @@ def find_tag(tag):
152152
with open(tag_file_path) as tag_file:
153153
for line in tag_file:
154154
bline = bytes(line, "ascii")
155-
if b"MICROPY_GIT_HASH" in bline:
155+
if b"MICROPY_GIT_TAG" in bline:
156156
bline = (
157-
bline.lstrip(b"#define MICROPY_GIT_HASH ")
157+
bline.lstrip(b"#define MICROPY_GIT_TAG ")
158158
.replace(b'"', b"")
159159
.replace(b"\r", b"")
160160
.replace(b"\n", b"")

py/makeversionhdr.py

+46-45
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@
1313
import subprocess
1414

1515

16+
# The MicroPython repository tags a release commit as "vX.Y.Z", and the commit
17+
# immediately following as "vX.(Y+1).Z-preview".
18+
# This function will return:
19+
# "vX.Y.Z" -- building at the release commit
20+
# "vX.Y.Z-preview" -- building at the first commit in the next cycle
21+
# "vX.Y.Z-preview.N.gHASH" -- building at any subsequent commit in the cycle
22+
# "vX.Y.Z-preview.N.gHASH.dirty" -- building at any subsequent commit in the cycle
23+
# with local changes
1624
def get_version_info_from_git(repo_path):
1725
# Python 2.6 doesn't have check_output, so check for that
1826
try:
@@ -29,47 +37,33 @@ def get_version_info_from_git(repo_path):
2937
stderr=subprocess.STDOUT,
3038
universal_newlines=True,
3139
).strip()
32-
except subprocess.CalledProcessError as er:
33-
if er.returncode == 128:
34-
# git exit code of 128 means no repository found
35-
return None
36-
git_tag = ""
37-
except OSError:
38-
return None
39-
try:
40-
git_hash = subprocess.check_output(
41-
["git", "rev-parse", "--short", "HEAD"],
42-
cwd=repo_path,
43-
stderr=subprocess.STDOUT,
44-
universal_newlines=True,
45-
).strip()
40+
# Turn git-describe's output into semver compatible (dot-separated
41+
# identifiers inside the prerelease field).
42+
git_tag = git_tag.split("-", 1)
43+
if len(git_tag) == 1:
44+
return git_tag[0]
45+
else:
46+
return git_tag[0] + "-" + git_tag[1].replace("-", ".")
4647
except subprocess.CalledProcessError:
47-
git_hash = "unknown"
48-
except OSError:
4948
return None
50-
51-
try:
52-
# Check if there are any modified files.
53-
subprocess.check_call(
54-
["git", "diff", "--no-ext-diff", "--quiet", "--exit-code"],
55-
cwd=repo_path,
56-
stderr=subprocess.STDOUT,
57-
)
58-
# Check if there are any staged files.
59-
subprocess.check_call(
60-
["git", "diff-index", "--cached", "--quiet", "HEAD", "--"],
61-
cwd=repo_path,
62-
stderr=subprocess.STDOUT,
63-
)
64-
except subprocess.CalledProcessError:
65-
git_hash += "-dirty"
6649
except OSError:
6750
return None
6851

69-
return git_tag, git_hash
70-
7152

53+
# When building from a source tarball (or any situation where the git repo
54+
# isn't available), this function will use the info in mpconfig.h as a
55+
# fallback. The release commit sets MICROPY_VERSION_PRERELEASE to 0, and the
56+
# commit immediately following increments MICROPY_VERSION_MINOR and sets
57+
# MICROPY_VERSION_PRERELEASE back to 1.
58+
# This function will return:
59+
# "vX.Y.Z" -- building at the release commit
60+
# "vX.Y.Z-preview" -- building at any other commit
7261
def get_version_info_from_mpconfig(repo_path):
62+
print(
63+
"makeversionhdr.py: Warning: No git repo or tag info available, falling back to mpconfig.h version info.",
64+
file=sys.stderr,
65+
)
66+
7367
with open(os.path.join(repo_path, "py", "mpconfig.h")) as f:
7468
for line in f:
7569
if line.startswith("#define MICROPY_VERSION_MAJOR "):
@@ -78,21 +72,30 @@ def get_version_info_from_mpconfig(repo_path):
7872
ver_minor = int(line.strip().split()[2])
7973
elif line.startswith("#define MICROPY_VERSION_MICRO "):
8074
ver_micro = int(line.strip().split()[2])
81-
git_tag = "v%d.%d.%d" % (ver_major, ver_minor, ver_micro)
82-
return git_tag, "<no hash>"
75+
elif line.startswith("#define MICROPY_VERSION_PRERELEASE "):
76+
ver_prerelease = int(line.strip().split()[2])
77+
git_tag = "v%d.%d.%d%s" % (
78+
ver_major,
79+
ver_minor,
80+
ver_micro,
81+
"-preview" if ver_prerelease else "",
82+
)
83+
return git_tag
8384
return None
8485

8586

8687
def make_version_header(repo_path, filename):
87-
info = None
88+
git_tag = None
8889
if "MICROPY_GIT_TAG" in os.environ:
89-
info = [os.environ["MICROPY_GIT_TAG"], os.environ["MICROPY_GIT_HASH"]]
90-
if info is None:
91-
info = get_version_info_from_git(repo_path)
92-
if info is None:
93-
info = get_version_info_from_mpconfig(repo_path)
90+
git_tag = os.environ["MICROPY_GIT_TAG"]
91+
if git_tag is None:
92+
git_tag = get_version_info_from_git(repo_path)
93+
if git_tag is None:
94+
git_tag = get_version_info_from_mpconfig(repo_path)
9495

95-
git_tag, git_hash = info
96+
if not git_tag:
97+
print("makeversionhdr.py: Error: No version information available.")
98+
sys.exit(1)
9699

97100
build_date = datetime.date.today()
98101
if "SOURCE_DATE_EPOCH" in os.environ:
@@ -104,11 +107,9 @@ def make_version_header(repo_path, filename):
104107
file_data = """\
105108
// This file was generated by py/makeversionhdr.py
106109
#define MICROPY_GIT_TAG "%s"
107-
#define MICROPY_GIT_HASH "%s"
108110
#define MICROPY_BUILD_DATE "%s"
109111
""" % (
110112
git_tag,
111-
git_hash,
112113
build_date.strftime("%Y-%m-%d"),
113114
)
114115

py/modsys.c

+14-6
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,24 @@ const mp_print_t mp_sys_stdout_print = {&mp_sys_stdout_obj, mp_stream_write_adap
5959
STATIC const MP_DEFINE_STR_OBJ(mp_sys_version_obj, "3.4.0; " MICROPY_BANNER_NAME_AND_VERSION);
6060
6161
// version_info - Python language version that this implementation conforms to, as a tuple of ints
62-
#define I(n) MP_OBJ_NEW_SMALL_INT(n)
63-
// TODO: CPython is now at 5-element array, but save 2 els so far...
64-
STATIC const mp_obj_tuple_t mp_sys_version_info_obj = {{&mp_type_tuple}, 3, {I(3), I(4), I(0)}};
62+
// TODO: CPython is now at 5-element array (major, minor, micro, releaselevel, serial), but save 2 els so far...
63+
STATIC const mp_rom_obj_tuple_t mp_sys_version_info_obj = {{&mp_type_tuple}, 3, {MP_ROM_INT(3), MP_ROM_INT(4), MP_ROM_INT(0)}};
6564

6665
// sys.implementation object
6766
// this holds the MicroPython version
68-
STATIC const mp_obj_tuple_t mp_sys_implementation_version_info_obj = {
67+
STATIC const mp_rom_obj_tuple_t mp_sys_implementation_version_info_obj = {
6968
{&mp_type_tuple},
70-
3,
71-
{ I(MICROPY_VERSION_MAJOR), I(MICROPY_VERSION_MINOR), I(MICROPY_VERSION_MICRO) }
69+
4,
70+
{
71+
MP_ROM_INT(MICROPY_VERSION_MAJOR),
72+
MP_ROM_INT(MICROPY_VERSION_MINOR),
73+
MP_ROM_INT(MICROPY_VERSION_MICRO),
74+
#if MICROPY_VERSION_PRERELEASE
75+
MP_ROM_QSTR(MP_QSTR_preview),
76+
#else
77+
MP_ROM_QSTR(MP_QSTR_),
78+
#endif
79+
}
7280
};
7381
STATIC const MP_DEFINE_STR_OBJ(mp_sys_implementation_machine_obj, MICROPY_BANNER_MACHINE);
7482
#if MICROPY_PERSISTENT_CODE_LOAD

py/mpconfig.h

+21-11
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,32 @@
2626
#ifndef MICROPY_INCLUDED_PY_MPCONFIG_H
2727
#define MICROPY_INCLUDED_PY_MPCONFIG_H
2828

29-
// Current version of MicroPython
29+
// Current version of MicroPython. This is used by sys.implementation.version
30+
// as well as a fallback to generate MICROPY_GIT_TAG if the git repo or tags
31+
// are unavailable.
3032
#define MICROPY_VERSION_MAJOR 1
31-
#define MICROPY_VERSION_MINOR 21
33+
#define MICROPY_VERSION_MINOR 22
3234
#define MICROPY_VERSION_MICRO 0
33-
34-
// Combined version as a 32-bit number for convenience
35-
#define MICROPY_VERSION ( \
36-
MICROPY_VERSION_MAJOR << 16 \
37-
| MICROPY_VERSION_MINOR << 8 \
38-
| MICROPY_VERSION_MICRO)
39-
40-
// String version
41-
#define MICROPY_VERSION_STRING \
35+
#define MICROPY_VERSION_PRERELEASE 1
36+
37+
// Combined version as a 32-bit number for convenience to allow version
38+
// comparison. Doesn't include prerelease state.
39+
// e.g. #if MICROPY_VERSION < MICROPY_MAKE_VERSION(1, 22, 0)
40+
#define MICROPY_MAKE_VERSION(major, minor, patch) (major << 16 | minor << 8 | patch)
41+
#define MICROPY_VERSION MICROPY_MAKE_VERSION(MICROPY_VERSION_MAJOR, MICROPY_VERSION_MINOR, MICROPY_VERSION_MICRO)
42+
43+
// String version. This is only used directly for platform.platform and
44+
// os.uname().release. All other version info available in the firmware (e.g.
45+
// the REPL banner) comes from MICROPY_GIT_TAG.
46+
#define MICROPY_VERSION_STRING_BASE \
4247
MP_STRINGIFY(MICROPY_VERSION_MAJOR) "." \
4348
MP_STRINGIFY(MICROPY_VERSION_MINOR) "." \
4449
MP_STRINGIFY(MICROPY_VERSION_MICRO)
50+
#if MICROPY_VERSION_PRERELEASE
51+
#define MICROPY_VERSION_STRING MICROPY_VERSION_STRING_BASE "-preview"
52+
#else
53+
#define MICROPY_VERSION_STRING MICROPY_VERSION_STRING_BASE
54+
#endif
4555

4656
// This file contains default configuration settings for MicroPython.
4757
// You can override any of the options below using mpconfigport.h file

tools/autobuild/autobuild.sh

+12-2
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,19 @@ pushd ${MICROPY_AUTOBUILD_MICROPYTHON_REPO}
5454
make -C mpy-cross
5555

5656
# make the firmware tag
57+
# final filename will be <BOARD><-VARIANT>-<DATE>-v<SEMVER>.ext
58+
# where SEMVER is vX.Y.Z or vX.Y.Z-preview.N.gHASH or vX.Y.Z-preview.N.gHASH.dirty
5759
FW_DATE=$(date '+%Y%m%d')
58-
FW_GIT="$(git describe --dirty || echo unknown)"
59-
FW_TAG="-$FW_DATE-unstable-$FW_GIT"
60+
# same logic as makeversionhdr.py, convert git-describe output into semver-compatible
61+
FW_GIT_TAG="$(git describe --tags --dirty --always --match 'v[1-9].*')"
62+
FW_SEMVER_MAJOR_MINOR_PATCH="$(echo $FW_GIT_TAG | cut -d'-' -f1)"
63+
FW_SEMVER_PRERELEASE="$(echo $FW_GIT_TAG | cut -s -d'-' -f2-)"
64+
if [ -z "$FW_SEMVER_PRERELEASE" ]; then
65+
FW_SEMVER="$FW_SEMVER_MAJOR_MINOR_PATCH"
66+
else
67+
FW_SEMVER="$FW_SEMVER_MAJOR_MINOR_PATCH-$(echo $FW_SEMVER_PRERELEASE | tr - .)"
68+
fi
69+
FW_TAG="-$FW_DATE-$FW_SEMVER"
6070

6171
# build new firmware
6272
cd ports/cc3200

tools/autobuild/remove_old_firmware.py

+12-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def main():
1414

1515
# SSH to get list of existing files.
1616
p = subprocess.run(
17-
["ssh", ssh_machine, "find", ssh_firmware_dir, "-name", "\\*-unstable-v\\*"],
17+
["ssh", ssh_machine, "find", ssh_firmware_dir, "-name", "\\*-preview.\\*"],
1818
capture_output=True,
1919
)
2020
if p.returncode != 0:
@@ -26,31 +26,33 @@ def main():
2626
boards = {}
2727
for file in all_files:
2828
m = re.match(
29-
rb"([a-z/.]+)/([A-Za-z0-9_-]+)-(20[0-9]{6})-unstable-(v[0-9.-]+-g[0-9a-f]+).",
29+
rb"([a-z/.]+)/([A-Za-z0-9_-]+)-(20[0-9]{6})-(v[0-9.]+)-preview.([0-9]+).g[0-9a-f]+.",
3030
file,
3131
)
3232
if not m:
3333
continue
34-
dir, board, date, version = m.groups()
34+
dir, board, date, version, ncommits = m.groups()
3535
if board not in boards:
3636
boards[board] = {}
37-
if (date, version) not in boards[board]:
38-
boards[board][(date, version)] = []
39-
boards[board][(date, version)].append(file)
37+
if (date, version, ncommits) not in boards[board]:
38+
boards[board][(date, version, ncommits)] = []
39+
boards[board][(date, version, ncommits)].append(file)
4040

4141
# Collect files to remove based on date and version.
4242
remove = []
4343
for board in boards.values():
44-
filelist = [(date, version, files) for (date, version), files in board.items()]
44+
filelist = [
45+
(date, version, ncommits, files) for (date, version, ncommits), files in board.items()
46+
]
4547
filelist.sort(reverse=True)
4648
keep = []
47-
for date, version, files in filelist:
48-
if keep and version == keep[-1]:
49+
for date, version, ncommits, files in filelist:
50+
if keep and (version, ncommits) == keep[-1]:
4951
remove.extend(files)
5052
elif len(keep) >= NUM_KEEP_PER_BOARD:
5153
remove.extend(files)
5254
else:
53-
keep.append(version)
55+
keep.append((version, ncommits))
5456

5557
if DEBUG:
5658
all_files.sort(reverse=True)

tools/mpremote/pyproject.toml

+6-1
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,14 @@ mpremote = "mpremote.main:main"
3636
[tool.hatch.metadata.hooks.requirements_txt]
3737
files = ["requirements.txt"]
3838

39+
# This will be PEP-440 normalised into either:
40+
# mpremote-X.Y.Z (on vX.Y.Z release tag)
41+
# mpremote-X.Y.Zrc0 (on vX.Y.Z-preview tag, i.e. first commit in the cycle)
42+
# mpremote-X.Y.Zrc0.postN+gHASH (N commits past vX.Y.Z-preview tag)
43+
# mpremote-X.Y.Zrc0.postN+gHASH.dDATE (N commits past vX.Y.Z-preview tag, dirty)
3944
[tool.hatch.version]
4045
source = "vcs"
41-
tag-pattern = "(?P<version>v(\\d+).(\\d+).(\\d+))"
46+
tag-pattern = "(?P<version>v(\\d+).(\\d+).(\\d+)(-preview)?)"
4247
raw-options = { root = "../..", version_scheme = "post-release" }
4348

4449
[tool.hatch.build]

0 commit comments

Comments
 (0)