Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions .github/scripts/compute_vmi_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@

def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Compute the VMI release version from a version file."
description="Compute the VMI release version from the top-level CMakeLists.txt."
)
parser.add_argument(
"--version-file",
default="docs/release/VMI_VERSION",
help="Path to the VMI version file.",
"--cmake-file",
default="CMakeLists.txt",
help="Path to the top-level CMakeLists.txt file.",
)
parser.add_argument(
"--check-tag",
Expand All @@ -29,11 +29,17 @@ def parse_args() -> argparse.Namespace:
return parser.parse_args()


def read_version(version_file: pathlib.Path) -> str:
version = version_file.read_text(encoding="utf-8").strip()
if not re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+", version):
raise ValueError(f"invalid VMI version '{version}' in {version_file}")
return version
def read_version(cmake_file: pathlib.Path) -> str:
content = cmake_file.read_text(encoding="utf-8")
match = re.search(
r'set\s*\(\s*PTOAS_VMI_VERSION\s+"([0-9]+\.[0-9]+\.[0-9]+)"\s*\)',
content,
)
if not match:
raise ValueError(
f'could not find \'set(PTOAS_VMI_VERSION "x.y.z")\' in {cmake_file}'
)
return match.group(1)


def normalize_tag(tag: str) -> str:
Expand All @@ -47,8 +53,8 @@ def normalize_tag(tag: str) -> str:

def main() -> int:
args = parse_args()
version_file = pathlib.Path(args.version_file)
version = read_version(version_file)
cmake_file = pathlib.Path(args.cmake_file)
version = read_version(cmake_file)

if args.check_tag is not None:
normalized_tag = normalize_tag(args.check_tag)
Expand Down
84 changes: 84 additions & 0 deletions .github/scripts/update_vmi_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
# Copyright (c) 2026 Huawei Technologies Co., Ltd.
# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
# CANN Open Software License Agreement Version 2.0 (the "License").
# Please refer to the License for details. You may not use this file except in compliance with the License.
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
# See LICENSE in the root of the software repository for the full text of the License.

import argparse
import pathlib
import re
import sys


VMI_VERSION_RE = re.compile(
r'(set\s*\(\s*PTOAS_VMI_VERSION\s+")([0-9]+\.[0-9]+\.[0-9]+)("\s*\))'
)
TAG_VERSION_RE = re.compile(r"^vmi-v([0-9]+)\.([0-9]+)\.([0-9]+)$")


def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Update the VMI version in the top-level CMakeLists.txt."
)
parser.add_argument(
"--cmake-file",
default="CMakeLists.txt",
help="Path to the top-level CMakeLists.txt file.",
)
parser.add_argument(
"--version",
required=True,
help="Released VMI version, for example vmi-v0.1.3.",
)
parser.add_argument(
"--next",
action="store_true",
help="Advance the resolved version by one patch step.",
)
return parser.parse_args()


def normalize_version(version: str) -> str:
match = TAG_VERSION_RE.fullmatch(version.strip())
if not match:
raise ValueError(f"invalid VMI release tag '{version}'")
return ".".join(match.groups())


def bump_version(version: str) -> str:
major, minor, patch = (int(part) for part in version.split("."))
return f"{major}.{minor}.{patch + 1}"


def update_version(cmake_file: pathlib.Path, version: str) -> bool:
content = cmake_file.read_text(encoding="utf-8")
updated, count = VMI_VERSION_RE.subn(
lambda match: f"{match.group(1)}{version}{match.group(3)}",
content,
count=1,
)
if count != 1:
raise ValueError(
f'could not find \'set(PTOAS_VMI_VERSION "x.y.z")\' in {cmake_file}'
)
if updated == content:
return False
cmake_file.write_text(updated, encoding="utf-8")
return True


def main() -> int:
args = parse_args()
version = normalize_version(args.version)
if args.next:
version = bump_version(version)
update_version(pathlib.Path(args.cmake_file), version)
print(version)
return 0


if __name__ == "__main__":
sys.exit(main())
34 changes: 33 additions & 1 deletion .github/workflows/build_wheel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ jobs:
case "${GITHUB_REF_NAME}" in
vmi-v*)
EXPECTED_RELEASE_VERSION="$(${PY_PATH}/bin/python .github/scripts/compute_vmi_version.py \
--version-file docs/release/VMI_VERSION \
--check-tag "${GITHUB_REF_NAME}")"
PTOAS_VERSION="${GITHUB_REF_NAME#vmi-v}"
PTOAS_CLI_VERSION="vmi ${PTOAS_VERSION}"
Expand Down Expand Up @@ -403,3 +402,36 @@ jobs:
git add CMakeLists.txt
git commit -m "chore(release): bump base version to v${{ steps.bump.outputs.next_base_version }}"
git push origin HEAD:${{ github.event.repository.default_branch }}

bump_vmi_version:
name: Bump VMI version after release
if: github.event_name == 'release' && github.event.action == 'released' && startsWith(github.ref_name, 'vmi-v')
needs: upload_release_assets
runs-on: ubuntu-latest

steps:
- name: Checkout default branch
uses: actions/checkout@v4
with:
ref: ${{ github.event.repository.default_branch }}

- name: Update VMI version
id: bump
run: |
next_vmi_version="$(python3 .github/scripts/update_vmi_version.py \
--version "${GITHUB_REF_NAME}" \
--next)"
echo "next_vmi_version=${next_vmi_version}" >> "$GITHUB_OUTPUT"

- name: Commit version bump
run: |
if git diff --quiet -- CMakeLists.txt; then
echo "CMakeLists.txt already matches the next VMI version."
exit 0
fi

git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add CMakeLists.txt
git commit -m "chore(release): bump VMI version to v${{ steps.bump.outputs.next_vmi_version }}"
git push origin HEAD:${{ github.event.repository.default_branch }}
1 change: 0 additions & 1 deletion .github/workflows/build_wheel_mac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ jobs:
case "${GITHUB_REF_NAME}" in
vmi-v*)
EXPECTED_RELEASE_VERSION="$(python .github/scripts/compute_vmi_version.py \
--version-file docs/release/VMI_VERSION \
--check-tag "${GITHUB_REF_NAME}")"
PTOAS_VERSION="${GITHUB_REF_NAME#vmi-v}"
PTOAS_CLI_VERSION="vmi ${PTOAS_VERSION}"
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ endfunction()
ptoas_preseed_compilers_from_llvm_cache()

project(ptoas VERSION 0.52)
set(PTOAS_VMI_VERSION "0.1.4")

option(PTOAS_VALIDATE_CMAKE4_FETCHCONTENT_COMPAT
"Validate CMake 4 compatibility for legacy FetchContent users" OFF)
Expand Down
1 change: 0 additions & 1 deletion docs/release/VMI_VERSION

This file was deleted.

62 changes: 58 additions & 4 deletions test/python/test_release_version_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,17 @@ def test_ptoas_version_script_accepts_ptoas_tag_prefix(self):
def test_vmi_version_script_accepts_vmi_tag_prefix(self):
with tempfile.TemporaryDirectory() as temp_dir:
temp_root = Path(temp_dir)
version_file = temp_root / "VMI_VERSION"
version_file.write_text("0.1.0\n", encoding="utf-8")
cmake_file = temp_root / "CMakeLists.txt"
cmake_file.write_text(
'project(ptoas VERSION 0.51)\nset(PTOAS_VMI_VERSION "0.1.0")\n',
encoding="utf-8",
)
result = subprocess.run(
[
sys.executable,
str(REPO_ROOT / ".github/scripts/compute_vmi_version.py"),
"--version-file",
str(version_file),
"--cmake-file",
str(cmake_file),
"--check-tag",
"vmi-v0.1.0",
],
Expand All @@ -78,6 +81,57 @@ def test_vmi_version_script_accepts_vmi_tag_prefix(self):
)
self.assertEqual(result.stdout.strip(), "0.1.0")

def test_vmi_version_bump_updates_only_vmi_version(self):
with tempfile.TemporaryDirectory() as temp_dir:
temp_root = Path(temp_dir)
cmake_file = temp_root / "CMakeLists.txt"
cmake_file.write_text(
'project(ptoas VERSION 0.51)\nset(PTOAS_VMI_VERSION "0.1.9")\n',
encoding="utf-8",
)
result = subprocess.run(
[
sys.executable,
str(REPO_ROOT / ".github/scripts/update_vmi_version.py"),
"--cmake-file",
str(cmake_file),
"--version",
"vmi-v0.1.9",
"--next",
],
check=True,
capture_output=True,
text=True,
)
self.assertEqual(result.stdout.strip(), "0.1.10")
self.assertEqual(
cmake_file.read_text(encoding="utf-8"),
'project(ptoas VERSION 0.51)\nset(PTOAS_VMI_VERSION "0.1.10")\n',
)

def test_vmi_version_bump_rejects_ptoas_tag(self):
with tempfile.TemporaryDirectory() as temp_dir:
temp_root = Path(temp_dir)
cmake_file = temp_root / "CMakeLists.txt"
cmake_file.write_text(
'project(ptoas VERSION 0.51)\nset(PTOAS_VMI_VERSION "0.1.0")\n',
encoding="utf-8",
)
result = subprocess.run(
[
sys.executable,
str(REPO_ROOT / ".github/scripts/update_vmi_version.py"),
"--cmake-file",
str(cmake_file),
"--version",
"v0.51",
"--next",
],
capture_output=True,
text=True,
)
self.assertNotEqual(result.returncode, 0)

def test_ptoas_version_bump_rejects_vmi_tag(self):
with tempfile.TemporaryDirectory() as temp_dir:
temp_root = Path(temp_dir)
Expand Down
Loading