You've already forked crosspoint-reader
mirror of
https://github.com/crosspoint-reader/crosspoint-reader.git
synced 2026-04-29 10:26:52 -07:00
02822e01b3
## Summary * Includes short SHA in version string for better version tracking, so it looks like `1.1.0-dev-feat-kosync-xpath-05c6cf8` * Closes https://github.com/crosspoint-reader/crosspoint-reader/issues/1247 --- ### AI Usage While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it helps set the right context for reviewers. Did you use AI tools to help write this code? _**< YES >**_
107 lines
3.5 KiB
Python
107 lines
3.5 KiB
Python
"""
|
|
PlatformIO pre-build script: inject git branch and short SHA into
|
|
CROSSPOINT_VERSION for the default (dev) environment.
|
|
|
|
Results in a version string like: 1.1.0-dev-feat-kosync-xpath-05c6cf8
|
|
Release environments are unaffected; they set CROSSPOINT_VERSION in the ini.
|
|
"""
|
|
|
|
import configparser
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
def warn(msg):
|
|
print(f'WARNING [git_branch.py]: {msg}', file=sys.stderr)
|
|
|
|
|
|
def run_git_value(project_dir, args, label):
|
|
try:
|
|
value = subprocess.check_output(
|
|
['git', *args],
|
|
text=True, stderr=subprocess.PIPE, cwd=project_dir
|
|
).strip()
|
|
# Strip characters that would break a C string literal
|
|
return ''.join(c for c in value if c not in '"\\')
|
|
except FileNotFoundError:
|
|
warn(f'git not found on PATH; {label} suffix will be "unknown"')
|
|
return 'unknown'
|
|
except subprocess.CalledProcessError as e:
|
|
warn(
|
|
f'git command failed (exit {e.returncode}): '
|
|
f'{e.stderr.strip()}; {label} suffix will be "unknown"'
|
|
)
|
|
return 'unknown'
|
|
except OSError as e:
|
|
warn(
|
|
f'OS error reading git {label}: {e}; '
|
|
f'{label} suffix will be "unknown"'
|
|
)
|
|
return 'unknown'
|
|
except Exception as e: # pylint: disable=broad-exception-caught
|
|
warn(
|
|
f'Unexpected error reading git {label}: {e}; '
|
|
f'{label} suffix will be "unknown"'
|
|
)
|
|
return 'unknown'
|
|
|
|
|
|
def get_git_branch(project_dir):
|
|
branch = run_git_value(
|
|
project_dir, ['rev-parse', '--abbrev-ref', 'HEAD'], 'branch'
|
|
)
|
|
# Detached HEAD has no branch name.
|
|
if branch == 'HEAD':
|
|
return 'detached'
|
|
return branch
|
|
|
|
|
|
def get_git_short_sha(project_dir):
|
|
return run_git_value(
|
|
project_dir, ['rev-parse', '--short', 'HEAD'], 'short SHA'
|
|
)
|
|
|
|
|
|
def get_base_version(project_dir):
|
|
ini_path = os.path.join(project_dir, 'platformio.ini')
|
|
if not os.path.isfile(ini_path):
|
|
warn(f'platformio.ini not found at {ini_path}; base version will be "0.0.0"')
|
|
return '0.0.0'
|
|
config = configparser.ConfigParser()
|
|
config.read(ini_path)
|
|
if not config.has_option('crosspoint', 'version'):
|
|
warn('No [crosspoint] version in platformio.ini; base version will be "0.0.0"')
|
|
return '0.0.0'
|
|
return config.get('crosspoint', 'version')
|
|
|
|
|
|
def inject_version(env):
|
|
# Only applies to the dev (default) environment; release envs set the
|
|
# version via build_flags in platformio.ini and are unaffected.
|
|
if env['PIOENV'] != 'default':
|
|
return
|
|
|
|
project_dir = env['PROJECT_DIR']
|
|
base_version = get_base_version(project_dir)
|
|
branch = get_git_branch(project_dir)
|
|
short_sha = get_git_short_sha(project_dir)
|
|
version_string = f'{base_version}-dev-{branch}-{short_sha}'
|
|
|
|
env.Append(CPPDEFINES=[('CROSSPOINT_VERSION', f'\\"{version_string}\\"')])
|
|
print(f'CrossPoint build version: {version_string}')
|
|
|
|
|
|
# PlatformIO/SCons entry point — Import and env are SCons builtins injected at runtime.
|
|
# When run directly with Python (e.g. for validation), a lightweight fake env is used
|
|
# so the git/version logic can be exercised without a full build.
|
|
try:
|
|
Import('env') # noqa: F821 # type: ignore[name-defined]
|
|
inject_version(env) # noqa: F821 # type: ignore[name-defined]
|
|
except NameError:
|
|
class _Env(dict):
|
|
def Append(self, **_): pass
|
|
|
|
_project_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
inject_version(_Env({'PIOENV': 'default', 'PROJECT_DIR': _project_dir}))
|