What changed, and why it matters
This commit improves how the SeedSigner software detects its own version information when running automated tests in GitHub Actions. It adds new environment variables so that pull request builds correctly show the contributor's branch name and username instead of misleading placeholder values. There is no security vulnerability here; it is a quality-of-life improvement for build metadata.
No security action needed. This is a benign CI/metadata improvement. Reviewers can approve as normal.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change updates version detection logic in src/seedsigner/helpers/version.py to prefer GITHUB_HEAD_REF over GITHUB_REF_NAME and a new PR_AUTHOR variable over GITHUB_REPOSITORY_OWNER when running in GitHub Actions CI. The workflow file exports PR_AUTHOR from the pull request context, and tests are updated to cover the new precedence rules. The code only reads environment variables and returns strings for display/metadata purposes; it does not execute commands, perform network operations, or affect cryptographic operations.
Changed components
src/seedsigner/helpers/version.py.github/workflows/tests.ymltests/test_version.pyInspect captured patch +96 / −16
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index c1e14c9..b4165fd 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -39,6 +39,7 @@ jobs:
pip install .
- name: Test with pytest
run: |
+ export PR_AUTHOR="${{ github.event.pull_request.user.login || github.actor }}"
mkdir artifacts
python -m pytest \
--color=yes \
diff --git a/src/seedsigner/helpers/version.py b/src/seedsigner/helpers/version.py
index e9d71fc..cc65e4f 100644
--- a/src/seedsigner/helpers/version.py
+++ b/src/seedsigner/helpers/version.py
@@ -193,8 +193,10 @@ class VersionUtils:
ENV_VAR__IS_SEEDSIGNER_OS_BUILDER = "SEEDSIGNER_OS_BUILDER"
ENV_VAR__GITHUB_ACTIONS__IS_CI = "CI"
+ ENV_VAR__GITHUB_ACTIONS__HEAD_REF = "GITHUB_HEAD_REF"
ENV_VAR__GITHUB_ACTIONS__REF_NAME = "GITHUB_REF_NAME"
ENV_VAR__GITHUB_ACTIONS__SHA = "GITHUB_SHA"
+ ENV_VAR__GITHUB_ACTIONS__PR_AUTHOR = "PR_AUTHOR"
ENV_VAR__GITHUB_ACTIONS__REPOSITORY_OWNER = "GITHUB_REPOSITORY_OWNER"
DOT_GIT_DIR_NAME = ".git" # defined to facilitate mocking in tests
VERSIONFILE__FILENAME = "version.json"
@@ -264,7 +266,7 @@ class VersionUtils:
return VersionUtils._get_version_fork_from_version_file()
elif VersionUtils.is_github_actions_ci():
- # In Github Actions CI, try to get the version name from env vars
+ # In Github Actions CI, try to get the fork name from env vars.
return VersionUtils._get_version_fork_from_github_actions_env_vars()
else:
@@ -459,16 +461,38 @@ class VersionUtils:
@classmethod
def _get_version_name_from_github_actions_env_vars(cls) -> str | None:
- # REF_NAME will be the branch or tag name; SHA is the full commit hash
- # TODO: Will REF_NAME ever be missing?
- ref_name = os.getenv(cls.ENV_VAR__GITHUB_ACTIONS__REF_NAME)
- sha = os.getenv(cls.ENV_VAR__GITHUB_ACTIONS__SHA)
- return ref_name or (sha[:7] if sha else None)
+ """
+ HEAD_REF: head ref or source branch. But only present for PRs.
+ REF_NAME: branch or tag name. But it is "<pr_number>/merge" for unmerged PRs (not
+ what we want)
+ SHA is the full commit hash; not expecting to ever need this fallback.
+ """
+ for env_var in [
+ cls.ENV_VAR__GITHUB_ACTIONS__HEAD_REF,
+ cls.ENV_VAR__GITHUB_ACTIONS__REF_NAME,
+ cls.ENV_VAR__GITHUB_ACTIONS__SHA
+ ]:
+ version_name = os.getenv(env_var)
+ if version_name:
+ if env_var == cls.ENV_VAR__GITHUB_ACTIONS__SHA:
+ # Return the short version
+ version_name = version_name[:7]
+ return version_name
@classmethod
def _get_version_fork_from_github_actions_env_vars(cls) -> str | None:
- return os.getenv("GITHUB_REPOSITORY_OWNER")
+ """
+ PR_AUTHOR: Set by the .github/workflows/tests.yml workflow. Should be the PR author.
+ REPOSITORY_OWNER: the repo owner, usually the main "SeedSigner" org.
+ """
+ for env_var in [
+ cls.ENV_VAR__GITHUB_ACTIONS__PR_AUTHOR,
+ cls.ENV_VAR__GITHUB_ACTIONS__REPOSITORY_OWNER
+ ]:
+ fork_name = os.getenv(env_var)
+ if fork_name:
+ return fork_name
@classmethod
diff --git a/tests/test_version.py b/tests/test_version.py
index 9a1e40e..8c15444 100644
--- a/tests/test_version.py
+++ b/tests/test_version.py
@@ -365,31 +365,86 @@ class TestVersionUtils_GithubActions(VersionBaseTest):
assert VersionUtils.is_github_actions_ci() is False
- def test_get_version_name_from_github_actions_env_vars(self):
+ def test__get_version_name_from_github_actions_env_vars(self):
"""
- get_version_name_from_github_actions_env_vars should return the REF_NAME or SHA
- env vars when set.
+ _get_version_name_from_github_actions_env_vars should prioritize HEAD_REF, then
+ REF_NAME, then SHA env vars when set.
"""
+ test_head_ref = "head_ref"
+ test_ref_name = "ref_name"
+ test_sha = TEST__FULL_COMMIT_HASH
+
# Need to signal that we're in a GitHub Actions CI environment
with patch.dict(os.environ, {
VersionUtils.ENV_VAR__GITHUB_ACTIONS__IS_CI: "true",
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__HEAD_REF: "",
VersionUtils.ENV_VAR__GITHUB_ACTIONS__REF_NAME: "",
VersionUtils.ENV_VAR__GITHUB_ACTIONS__SHA: "",
}):
+ # With none of the env vars set, should return None
assert VersionUtils._get_version_name_from_github_actions_env_vars() is None
- # REF_NAME should be passed straight through
- with patch.dict(os.environ, {VersionUtils.ENV_VAR__GITHUB_ACTIONS__REF_NAME: TEST__VERSION_NAME}):
+ # HEAD_REF should be passed straight through, ignoring other vars
+ with patch.dict(os.environ, {
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__HEAD_REF: test_head_ref,
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__REF_NAME: test_ref_name,
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__SHA: test_sha,
+ }):
result = VersionUtils._get_version_name_from_github_actions_env_vars()
- assert result == TEST__VERSION_NAME
+ assert result == test_head_ref
- # Unlikely scenario: no REF_NAME but SHA is set; should return short commit hash
+ # REF_NAME is our next fallback
with patch.dict(os.environ, {
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__HEAD_REF: "",
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__REF_NAME: test_ref_name,
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__SHA: test_sha,
+ }):
+ result = VersionUtils._get_version_name_from_github_actions_env_vars()
+ assert result == test_ref_name
+
+ # Unlikely scenario: no HEAD_REF nor REF_NAME but SHA is set; should return
+ # short commit hash
+ with patch.dict(os.environ, {
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__HEAD_REF: "",
VersionUtils.ENV_VAR__GITHUB_ACTIONS__REF_NAME: "",
- VersionUtils.ENV_VAR__GITHUB_ACTIONS__SHA: TEST__FULL_COMMIT_HASH,
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__SHA: test_sha,
}):
result = VersionUtils._get_version_name_from_github_actions_env_vars()
- assert result == TEST__SHORT_COMMIT_HASH[:7]
+ assert result == test_sha[:7]
+
+
+ def test__get_version_fork_from_github_actions_env_vars(self):
+ """
+ _get_version_fork_from_github_actions_env_vars should return the PR_AUTHOR, then
+ fall back to REPOSITORY_OWNER.
+ """
+ test_pr_author = "some_pr_author"
+ test_repo_owner = "some_repo_owner"
+
+ # Need to signal that we're in a GitHub Actions CI environment
+ with patch.dict(os.environ, {
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__IS_CI: "true",
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__PR_AUTHOR: "",
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__REPOSITORY_OWNER: "",
+ }):
+ # With none of the env vars set, should return None
+ assert VersionUtils._get_version_fork_from_github_actions_env_vars() is None
+
+ # PR_AUTHOR should be passed straight through, ignoring REPOSITORY_OWNER
+ with patch.dict(os.environ, {
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__PR_AUTHOR: test_pr_author,
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__REPOSITORY_OWNER: test_repo_owner,
+ }):
+ result = VersionUtils._get_version_fork_from_github_actions_env_vars()
+ assert result == test_pr_author
+
+ # REPOSITORY_OWNER is our next fallback
+ with patch.dict(os.environ, {
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__PR_AUTHOR: "",
+ VersionUtils.ENV_VAR__GITHUB_ACTIONS__REPOSITORY_OWNER: test_repo_owner,
+ }):
+ result = VersionUtils._get_version_fork_from_github_actions_env_vars()
+ assert result == test_repo_owner
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.