Naming clean up; version.json gets "v" prefix; explicit SeedSigner OS builder paths
What changed, and why it matters
This commit is a routine code cleanup and build-system improvement. It renames internal variables (for example, changing 'version_commit_hash' to 'short_commit_hash'), makes the version string consistently include a 'v' prefix, and adds explicit support for detecting the SeedSigner OS build environment. There is no change that affects security or user safety.
No security action required; review as normal code-quality / build-process change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff refactors the Version helper and its consumers: renames attributes/methods for clarity, adds Version.to_dict(), and restructures VersionUtils.get_version_name/fork/timestamp/commit_hash to branch explicitly for SeedSigner OS builder environments. It also updates tests and screenshot generation to match the renamed API. No cryptographic, input-validation, or privilege changes are present.
Changed components
src/seedsigner/helpers/version.pysrc/seedsigner/gui/screens/settings_screens.pysrc/seedsigner/views/settings_views.pytests/screenshot_generator/generator.pytests/test_version.pyInspect captured patch +119 / −30
diff --git a/src/seedsigner/gui/screens/settings_screens.py b/src/seedsigner/gui/screens/settings_screens.py
index 67835fa..375ded4 100644
--- a/src/seedsigner/gui/screens/settings_screens.py
+++ b/src/seedsigner/gui/screens/settings_screens.py
@@ -316,7 +316,7 @@ class VersionScreen(BaseTopNavScreen):
version_name: str = None
version_fork: str = None
version_timestamp: datetime = None
- version_commit_hash: str = None
+ short_commit_hash: str = None
def __post_init__(self):
self.title = _("Version")
@@ -344,7 +344,7 @@ class VersionScreen(BaseTopNavScreen):
(left, timestamp_char_height, timestamp_char_width, bottom) = timestamp_font.getbbox("UTC", anchor="ls")
screen_y = self.top_nav.height + GUIConstants.COMPONENT_PADDING * 2
- if not self.version_fork and not self.version_commit_hash:
+ if not self.version_fork and not self.short_commit_hash:
# Center the version name if there's no fork/commit info
screen_y = int(self.canvas_height / 2) - (-1 * version_name_char_height) # char_height is negative
@@ -366,7 +366,7 @@ class VersionScreen(BaseTopNavScreen):
if self.version_fork:
screen_x = 0
- if self.version_commit_hash:
+ if self.short_commit_hash:
# right-align the labels
screen_x = commit_label_width - fork_label_width
self.components.append(TextArea(
@@ -387,7 +387,7 @@ class VersionScreen(BaseTopNavScreen):
))
screen_y = self.components[-1].screen_y + self.components[-1].height + GUIConstants.COMPONENT_PADDING
- if self.version_commit_hash:
+ if self.short_commit_hash:
self.components.append(TextArea(
text=f"commit: ",
is_text_centered=False,
@@ -395,7 +395,7 @@ class VersionScreen(BaseTopNavScreen):
screen_y=screen_y,
))
self.components.append(TextArea(
- text=self.version_commit_hash,
+ text=self.short_commit_hash,
is_text_centered=False,
font_name=GUIConstants.FIXED_WIDTH_EMPHASIS_FONT_NAME,
font_size=GUIConstants.get_top_nav_title_font_size(),
diff --git a/src/seedsigner/helpers/version.py b/src/seedsigner/helpers/version.py
index 20335a5..7590f9d 100644
--- a/src/seedsigner/helpers/version.py
+++ b/src/seedsigner/helpers/version.py
@@ -85,7 +85,7 @@ class Version(Singleton):
_version_name: str = None
_version_fork: str = None
_version_timestamp: datetime = None
- _version_commit_hash: str = None
+ _short_commit_hash: str = None
@classmethod
@@ -100,7 +100,7 @@ class Version(Singleton):
version._version_name = VersionUtils.get_version_name()
version._version_fork = VersionUtils.get_version_fork()
version._version_timestamp = VersionUtils.get_version_timestamp()
- version._version_commit_hash = VersionUtils.get_short_commit_hash()
+ version._short_commit_hash = VersionUtils.get_short_commit_hash()
return cls._instance
@@ -120,13 +120,13 @@ class Version(Singleton):
@classmethod
- def get_version_commit_hash(cls) -> str | None:
- return cls.get_instance()._version_commit_hash
+ def get_short_commit_hash(cls) -> str | None:
+ return cls.get_instance()._short_commit_hash
@classmethod
@not_allowed_in_seedsigner_os
- def override_data(cls, version_name, version_fork, version_timestamp, version_commit_hash):
+ def override_data(cls, version_name, version_fork, version_timestamp, short_commit_hash):
"""
Only used by the screenshot generator.
"""
@@ -134,9 +134,19 @@ class Version(Singleton):
instance._version_name = version_name
instance._version_fork = version_fork
instance._version_timestamp = version_timestamp
- instance._version_commit_hash = version_commit_hash
+ instance._short_commit_hash = short_commit_hash
+ @classmethod
+ def to_dict(cls) -> dict:
+ instance = cls.get_instance()
+ return {
+ VersionUtils.VERSIONFILE_ATTR__NAME: instance._version_name,
+ VersionUtils.VERSIONFILE_ATTR__FORK: instance._version_fork,
+ VersionUtils.VERSIONFILE_ATTR__TIMESTAMP: instance._version_timestamp.isoformat() if instance._version_timestamp else None,
+ VersionUtils.VERSIONFILE_ATTR__COMMIT_HASH: instance._short_commit_hash,
+ }
+
class VersionUtils:
""" *********************************************************************************
@@ -187,7 +197,11 @@ class VersionUtils:
# Shouldn't be possible. Raise an exception to alert testers before this
# image goes out.
raise Exception("Could not read the version from the version.json file.")
- return VersionUtils._prefix_version_name(version_name)
+
+ # Note: the version.json file already contains any necessary pre-processing so
+ # if we're on a semantic version tag, version_name will already be prefixed
+ # with "v".
+ return version_name
elif VersionUtils.is_github_actions_ci():
# In Github Actions CI, try to get the version name from env vars
@@ -197,10 +211,18 @@ class VersionUtils:
else:
raise Exception("Could not determine version from Github Actions env vars.")
+ elif VersionUtils._is_seedsigner_os_builder_env():
+ # In the SeedSigner OS build environment, get the version name from env var.
+ # Note: This get_version_name call will never fail because the env var that
+ # provides the version name is what defines whether we're in the SeedSigner OS
+ # builder in the first place.
+ version_name = VersionUtils._get_version_name_from_seedsigner_os_builder_env_var()
+ return VersionUtils._prefix_version_name(version_name)
+
else:
# In local dev, we try the following methods in order:
for get_version_name_method in [
- VersionUtils._get_version_name_from_seedsigner_os_env_var,
+ VersionUtils._get_version_name_from_seedsigner_os_builder_env_var,
VersionUtils._get_version_name_from_git_shell,
VersionUtils._get_version_name_from_git_HEAD,
]:
@@ -230,6 +252,10 @@ class VersionUtils:
# In Github Actions CI, try to get the version name from env vars
return VersionUtils._get_version_fork_from_github_actions_env_vars()
+ elif VersionUtils._is_seedsigner_os_builder_env():
+ # In the SeedSigner OS build environment `git` shell call should be available
+ return VersionUtils._get_version_fork_from_git_shell()
+
else:
# In local dev we try to access the current git state via:
for get_version_fork_method in [
@@ -263,8 +289,13 @@ class VersionUtils:
# In Github Actions CI `git` shell call should be available
return VersionUtils._get_version_timestamp_from_git_shell()
+ elif VersionUtils._is_seedsigner_os_builder_env():
+ # In the SeedSigner OS build environment `git` shell call should be available
+ return VersionUtils._get_version_timestamp_from_git_shell()
+
else:
- # In local dev we use the last modified time of the source python files
+ # In local dev we change our approach and instead use the last modified time
+ # of the source python files.
return VersionUtils._get_last_modified_timestamp_from_src_files()
@@ -284,6 +315,10 @@ class VersionUtils:
# In Github Actions CI the "SHA" env var should always be available
full_commit_hash = VersionUtils._get_full_commit_hash_from_github_actions_env_vars()
+ elif VersionUtils._is_seedsigner_os_builder_env():
+ # In the SeedSigner OS build environment `git` shell call should be available
+ full_commit_hash = VersionUtils._get_full_commit_hash_from_git_shell()
+
else:
# In local dev we try to access the current git state via:
for get_full_commit_hash_method in [
@@ -388,7 +423,15 @@ class VersionUtils:
Utilities used in the SeedSigner OS build environment and writing the version.json file.
************************************************************************************* """
@classmethod
- def _get_version_name_from_seedsigner_os_env_var(cls) -> str | None:
+ def _is_seedsigner_os_builder_env(cls) -> bool:
+ """
+ Simple check to see if we're running in the SeedSigner OS build environment.
+ """
+ return os.getenv(cls.ENV_VAR__SEEDSIGNER_OS_BUILDER__VERSION_NAME) is not None
+
+
+ @classmethod
+ def _get_version_name_from_seedsigner_os_builder_env_var(cls) -> str | None:
"""
Primarily used during the SeedSigner OS build process to set the version name via env var.
diff --git a/src/seedsigner/views/settings_views.py b/src/seedsigner/views/settings_views.py
index ee14ce1..1c7fcc1 100644
--- a/src/seedsigner/views/settings_views.py
+++ b/src/seedsigner/views/settings_views.py
@@ -331,21 +331,21 @@ class VersionView(View):
from seedsigner.helpers.version import Version
version_fork = Version.get_version_fork()
- version_commit_hash = Version.get_version_commit_hash()
+ short_commit_hash = Version.get_short_commit_hash()
- print(f"{version_fork=}, {version_commit_hash=}")
+ print(f"{version_fork=}, {short_commit_hash=}")
if version_fork and version_fork.lower() == "seedsigner":
# Don't display fork name or commit hash for the main repo
version_fork = None
- version_commit_hash = None
+ short_commit_hash = None
self.run_screen(
settings_screens.VersionScreen,
version_name=Version.get_version_name(),
version_fork=version_fork,
version_timestamp=Version.get_version_timestamp(),
- version_commit_hash=version_commit_hash,
+ short_commit_hash=short_commit_hash,
)
return Destination(SettingsMenuView)
\ No newline at end of file
diff --git a/tests/screenshot_generator/generator.py b/tests/screenshot_generator/generator.py
index 2566a3a..bd088eb 100644
--- a/tests/screenshot_generator/generator.py
+++ b/tests/screenshot_generator/generator.py
@@ -205,7 +205,7 @@ def generate_screenshots(locale):
version_name=version_name,
version_fork="SeedSigner", # main repo; screenshot should hide fork and commit hash
version_timestamp=version_timestamp,
- version_commit_hash="abcd1234" # dummy value should be ignored
+ short_commit_hash="abcd1234" # dummy value should be ignored
)
# Automatically populate all Settings options Views
diff --git a/tests/test_version.py b/tests/test_version.py
index 726a517..354a571 100644
--- a/tests/test_version.py
+++ b/tests/test_version.py
@@ -27,7 +27,7 @@ TEST__SEMANTIC_TAG = "1.2.3-rc1"
TEST__SHORT_COMMIT_HASH = "c5efda3"
TEST__FULL_COMMIT_HASH = "c5efda306c60877191013a6093d92cd0bfcccec8"
TEST__VERSION_DICT = {
- VersionUtils.VERSIONFILE_ATTR__NAME: TEST__VERSION_NAME,
+ VersionUtils.VERSIONFILE_ATTR__NAME: VersionUtils._prefix_version_name(TEST__VERSION_NAME),
VersionUtils.VERSIONFILE_ATTR__FORK: TEST__VERSION_FORK,
VersionUtils.VERSIONFILE_ATTR__TIMESTAMP: TEST__VERSION_TIMESTAMP.isoformat(),
VersionUtils.VERSIONFILE_ATTR__COMMIT_HASH: TEST__SHORT_COMMIT_HASH,
@@ -256,12 +256,14 @@ class TestVersionUtils_VersionFile(VersionBaseTest):
def test__read_version_file(self):
"""
Low-level test for reading the version.json file.
+
+ Note that the version.json file will already "v" prefix version_name as needed.
"""
self.write_test_version_file()
version_data = VersionUtils._read_version_file()
assert version_data is not None
- assert version_data[VersionUtils.VERSIONFILE_ATTR__NAME] == TEST__VERSION_NAME
+ assert version_data[VersionUtils.VERSIONFILE_ATTR__NAME] == VersionUtils._prefix_version_name(TEST__VERSION_NAME)
assert version_data[VersionUtils.VERSIONFILE_ATTR__FORK] == TEST__VERSION_FORK
assert version_data[VersionUtils.VERSIONFILE_ATTR__TIMESTAMP] == TEST__VERSION_TIMESTAMP.isoformat()
assert version_data[VersionUtils.VERSIONFILE_ATTR__COMMIT_HASH] == TEST__SHORT_COMMIT_HASH
@@ -283,12 +285,12 @@ class TestVersionUtils_VersionFile(VersionBaseTest):
assert VersionUtils._read_version_file() is None
- def test__get_version_name_from_seedsigner_os_env_var(self):
+ def test__get_version_name_from_seedsigner_os_builder_env_var(self):
assert os.environ.get(VersionUtils.ENV_VAR__SEEDSIGNER_OS_BUILDER__VERSION_NAME) is None
- assert VersionUtils._get_version_name_from_seedsigner_os_env_var() is None
+ assert VersionUtils._get_version_name_from_seedsigner_os_builder_env_var() is None
with mock.patch.dict(os.environ, {VersionUtils.ENV_VAR__SEEDSIGNER_OS_BUILDER__VERSION_NAME: TEST__VERSION_NAME}):
- result = VersionUtils._get_version_name_from_seedsigner_os_env_var()
+ result = VersionUtils._get_version_name_from_seedsigner_os_builder_env_var()
assert result == TEST__VERSION_NAME
@@ -401,6 +403,41 @@ class TestVersionUtils_GithubActions(VersionBaseTest):
+class TestVersionUtils_SeedSignerOSBuilder(VersionBaseTest):
+ def test_seed_signer_os_builder_env_var(self):
+ """
+ Test the high-level basic public calls. Does just the minimal necessary mocking
+ since all the downstream helper methods are tested in detail elsewhere.
+ """
+ # Simulate running in the SeedSigner OS build environment
+ with mock.patch.dict(os.environ, {VersionUtils.ENV_VAR__SEEDSIGNER_OS_BUILDER__VERSION_NAME: TEST__VERSION_NAME}):
+ # SeedSigner OS builder uses some limited `git` shell calls; mock out the
+ # associated calls.
+ with mock.patch.multiple(
+ "seedsigner.helpers.version.VersionUtils",
+ _get_version_timestamp_from_git_shell=Mock(return_value=TEST__VERSION_TIMESTAMP),
+ _get_version_fork_from_git_shell=Mock(return_value=TEST__VERSION_FORK),
+ _get_full_commit_hash_from_git_shell=Mock(return_value=TEST__FULL_COMMIT_HASH),
+ ):
+ assert VersionUtils.get_version_name() == VersionUtils._prefix_version_name(TEST__VERSION_NAME)
+ assert VersionUtils.get_version_fork() == TEST__VERSION_FORK
+ assert VersionUtils.get_short_commit_hash() == TEST__SHORT_COMMIT_HASH
+ assert VersionUtils.get_version_timestamp() == TEST__VERSION_TIMESTAMP
+
+
+ def test_is_seedsigner_os_builder_env(self):
+ """
+ is_seedsigner_os_builder_env should return True only when the
+ ENV_VAR__SEEDSIGNER_OS_BUILDER__VERSION_NAME env var is set.
+ """
+ with mock.patch.dict(os.environ, {}, clear=True):
+ assert VersionUtils._is_seedsigner_os_builder_env() is False
+
+ with mock.patch.dict(os.environ, {VersionUtils.ENV_VAR__SEEDSIGNER_OS_BUILDER__VERSION_NAME: TEST__VERSION_NAME}):
+ assert VersionUtils._is_seedsigner_os_builder_env() is True
+
+
+
class TestVersionUtils_GitShell(VersionBaseTest):
def test_local_dev_with_git_shell_calls(self):
"""
@@ -847,7 +884,7 @@ class TestVersion(VersionBaseTest):
with patch("seedsigner.models.settings.Settings.HOSTNAME", Settings.SEEDSIGNER_OS):
Version.get_version_name() == TEST__VERSION_DICT[VersionUtils.VERSIONFILE_ATTR__NAME]
Version.get_version_fork() == TEST__VERSION_DICT[VersionUtils.VERSIONFILE_ATTR__FORK]
- Version.get_version_commit_hash() == TEST__VERSION_DICT[VersionUtils.VERSIONFILE_ATTR__COMMIT_HASH]
+ Version.get_short_commit_hash() == TEST__VERSION_DICT[VersionUtils.VERSIONFILE_ATTR__COMMIT_HASH]
Version.get_version_timestamp() == TEST__VERSION_TIMESTAMP
@@ -864,9 +901,9 @@ class TestVersion(VersionBaseTest):
# Initially the version data is pulled from the usual sources
self.write_test_version_file()
with patch("seedsigner.models.settings.Settings.HOSTNAME", Settings.SEEDSIGNER_OS):
- assert Version.get_version_name() == f"v{TEST__VERSION_DICT[VersionUtils.VERSIONFILE_ATTR__NAME]}"
+ assert Version.get_version_name() == TEST__VERSION_DICT[VersionUtils.VERSIONFILE_ATTR__NAME]
assert Version.get_version_fork() == TEST__VERSION_DICT[VersionUtils.VERSIONFILE_ATTR__FORK]
- assert Version.get_version_commit_hash() == TEST__VERSION_DICT[VersionUtils.VERSIONFILE_ATTR__COMMIT_HASH]
+ assert Version.get_short_commit_hash() == TEST__VERSION_DICT[VersionUtils.VERSIONFILE_ATTR__COMMIT_HASH]
assert Version.get_version_timestamp() == TEST__VERSION_TIMESTAMP
# While we're in the mocked SeedSigner OS environment, verify that the
@@ -878,16 +915,25 @@ class TestVersion(VersionBaseTest):
Version.override_data(
version_name=override_name,
version_fork=override_fork,
- version_commit_hash=override_commit_hash,
+ short_commit_hash=override_commit_hash,
version_timestamp=override_timestamp,
)
assert Version.get_version_name() == override_name
assert Version.get_version_fork() == override_fork
- assert Version.get_version_commit_hash() == override_commit_hash
+ assert Version.get_short_commit_hash() == override_commit_hash
assert Version.get_version_timestamp() == override_timestamp
+ def test_to_dict(self):
+ """
+ Test that Version.to_dict() returns the expected dictionary.
+ """
+ self.write_test_version_file()
+ with patch("seedsigner.models.settings.Settings.HOSTNAME", Settings.SEEDSIGNER_OS):
+ assert Version.to_dict() == TEST__VERSION_DICT
+
+
class TestNotAllowedInSeedSignerOSDecorator(BaseTest):
SUCCESS = "success"
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.