Skip to content

Commit 8780b97

Browse files
committed
Fix
1 parent 440902b commit 8780b97

4 files changed

Lines changed: 99 additions & 37 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ jobs:
2323
full: ${{ steps.git_version.outputs.BUILD_VERSION_FULL }}
2424
extended: ${{ steps.git_version.outputs.BUILD_VERSION_EXTENDED }}
2525
default_branch: ${{ steps.git_version.outputs.BUILD_VERSION_DEFAULT_BRANCH }}
26+
release_branches: ${{ steps.git_version.outputs.BUILD_VERSION_RELEASE_BRANCHES }}
2627

2728
steps:
2829
- uses: actions/checkout@v4
@@ -69,6 +70,7 @@ jobs:
6970
echo " Full: ${{ steps.git_version.outputs.BUILD_VERSION_FULL }}"
7071
echo " Extended: ${{ steps.git_version.outputs.BUILD_VERSION_EXTENDED }}"
7172
echo " DefaultBranch: ${{ steps.git_version.outputs.BUILD_VERSION_DEFAULT_BRANCH }}"
73+
echo " ReleaseBranches: ${{ steps.git_version.outputs.BUILD_VERSION_RELEASE_BRANCHES }}"
7274
echo "═══════════════════════════════════════"
7375
7476
- name: Upload build artifacts

src/git_version/cli.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import argparse
2-
import sys
32

43
from .core import GitVersion
54

@@ -28,7 +27,7 @@ def main() -> None:
2827
choices=[
2928
"tag", "version", "version_major", "version_minor", "version_patch",
3029
"build", "branch", "short", "full", "extended", "commit",
31-
"default_branch", "env", "all",
30+
"default_branch", "release_branches", "env", "all",
3231
],
3332
default="all",
3433
help="Which property to output (default: all)",

src/git_version/core.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import re
33
import subprocess
4+
import fnmatch
45
from functools import cached_property
56

67

@@ -10,15 +11,19 @@ class GitVersion:
1011
Args:
1112
repo_path: Path to the Git repository (default: current working directory).
1213
tag_pattern: Glob pattern to match version tags (default: "v[0-9]*").
14+
release_branches: List of branch patterns considered as release branches.
15+
Defaults to [default_branch, "release/*"].
1316
"""
1417

1518
def __init__(
1619
self,
1720
repo_path: str | None = None,
1821
tag_pattern: str = "v[0-9]*",
22+
release_branches: list[str] | None = None,
1923
):
2024
self.repo_path = os.path.abspath(repo_path or os.getcwd())
2125
self.tag_pattern = tag_pattern
26+
self._release_branches = release_branches
2227

2328
def _git(self, *args: str) -> str:
2429
"""Execute a git command safely and return stripped stdout."""
@@ -74,6 +79,16 @@ def default_branch(self) -> str:
7479
result = self._git("config", "--get", "init.defaultBranch")
7580
return result or "master"
7681

82+
@cached_property
83+
def release_branches(self) -> list[str]:
84+
"""List of release branch patterns.
85+
86+
Defaults to [default_branch, "release/*"] if not explicitly set.
87+
"""
88+
if self._release_branches is not None:
89+
return self._release_branches
90+
return [self.default_branch, "release/*"]
91+
7792
@cached_property
7893
def build(self) -> str:
7994
"""Number of commits since the last version tag."""
@@ -94,16 +109,31 @@ def short(self) -> str:
94109

95110
@cached_property
96111
def full(self) -> str:
97-
"""Full version string with commit hash: '<version>-<short>'."""
98-
return f"{self.version}-{self.short}"
112+
"""Full version string.
113+
114+
If the current branch matches a release branch pattern, returns just the
115+
version (e.g. '1.0.0.1'). Otherwise returns the extended version with
116+
commit hash (e.g. '1.0.0.1-a1b2c3').
117+
"""
118+
if self._is_release_branch():
119+
return self.version
120+
return self.extended
99121

100122
@cached_property
101123
def extended(self) -> str:
102-
"""Extended version: same as 'version' if build==0, else 'full'."""
103-
if self.build == "0":
104-
return self.version
124+
"""Extended version: '<version>-<short>' (e.g. '1.0.0.1-a1b2c3')."""
105125
return f"{self.version}-{self.short}"
106126

127+
def _is_release_branch(self) -> bool:
128+
"""Check if the current branch matches any release branch pattern."""
129+
current = self.branch
130+
if not current:
131+
return False
132+
for pattern in self.release_branches:
133+
if fnmatch.fnmatch(current, pattern):
134+
return True
135+
return False
136+
107137
@cached_property
108138
def commit(self) -> str:
109139
"""Full 40-character commit hash."""
@@ -132,6 +162,7 @@ def env(self, prefix: str = "BUILD_VERSION") -> dict[str, str]:
132162
f"{prefix}_COMMIT": self.commit,
133163
f"{prefix}_BRANCH": self.branch,
134164
f"{prefix}_DEFAULT_BRANCH": self.default_branch,
165+
f"{prefix}_RELEASE_BRANCHES": " ".join(self.release_branches),
135166
}
136167

137168
def __str__(self) -> str:
@@ -143,4 +174,5 @@ def __str__(self) -> str:
143174
Build: {self.build}
144175
Extended: {self.extended}
145176
Commit: {self.commit}
177+
Release branches: {", ".join(self.release_branches)}
146178
"""

tests/test_git_version.py

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import os
21
import tempfile
32
import subprocess
43
from pathlib import Path
@@ -81,41 +80,30 @@ def test_short(self, git_repo):
8180
gv = GitVersion(repo_path=str(git_repo))
8281
assert len(gv.short) == 6
8382

84-
def test_full(self, git_repo):
83+
def test_full_on_release_branch(self, git_repo):
84+
"""On a release branch (master), full should equal version."""
8585
gv = GitVersion(repo_path=str(git_repo))
86+
assert gv.full == gv.version
87+
assert gv.full == "1.0.0.1"
88+
89+
def test_full_on_non_release_branch(self, git_repo):
90+
"""On a non-release branch, full should equal extended (version-short)."""
91+
gv = GitVersion(
92+
repo_path=str(git_repo),
93+
release_branches=["main", "release/*"],
94+
)
95+
assert gv.full == gv.extended
8696
assert gv.full == f"1.0.0.1-{gv.short}"
8797

8898
def test_extended_with_build(self, git_repo):
99+
"""Extended always includes commit hash."""
89100
gv = GitVersion(repo_path=str(git_repo))
90-
assert gv.extended == gv.full
91-
92-
def test_extended_without_build(self, git_repo):
93-
"""When build == 0, extended should equal version."""
94-
with tempfile.TemporaryDirectory() as tmpdir:
95-
repo = Path(tmpdir)
96-
subprocess.run(["git", "init"], cwd=repo, capture_output=True, check=True)
97-
subprocess.run(
98-
["git", "config", "user.email", "test@test.com"],
99-
cwd=repo, capture_output=True, check=True,
100-
)
101-
subprocess.run(
102-
["git", "config", "user.name", "Test"],
103-
cwd=repo, capture_output=True, check=True,
104-
)
105-
(repo / "file.txt").write_text("hello")
106-
subprocess.run(["git", "add", "."], cwd=repo, capture_output=True, check=True)
107-
subprocess.run(
108-
["git", "commit", "-m", "initial"],
109-
cwd=repo, capture_output=True, check=True,
110-
)
111-
subprocess.run(
112-
["git", "tag", "v2.0.0"],
113-
cwd=repo, capture_output=True, check=True,
114-
)
101+
assert gv.extended == f"{gv.version}-{gv.short}"
115102

116-
gv = GitVersion(repo_path=str(repo))
117-
assert gv.build == "0"
118-
assert gv.extended == gv.version
103+
def test_extended_always_contains_commit(self, git_repo):
104+
"""Extended always includes version and short commit hash."""
105+
gv = GitVersion(repo_path=str(git_repo))
106+
assert gv.extended == f"{gv.version}-{gv.short}"
119107

120108
def test_commit(self, git_repo):
121109
gv = GitVersion(repo_path=str(git_repo))
@@ -135,6 +123,7 @@ def test_env(self, git_repo):
135123
assert env["TEST_BUILD"] == "1"
136124
assert env["TEST_TAG"] == "v1.0.0"
137125
assert env["TEST_BRANCH"] == "master"
126+
assert env["TEST_FULL"] == env["TEST"] # On release branch, full == version
138127
assert len(env["TEST_COMMIT"]) == 40
139128
assert len(env["TEST_SHORT"]) == 6
140129

@@ -178,6 +167,46 @@ def test_not_a_git_repo(self):
178167
assert gv.short == ""
179168
assert gv.commit == ""
180169

170+
def test_release_branches_default(self, git_repo):
171+
"""Default release_branches should include default branch and release/*."""
172+
gv = GitVersion(repo_path=str(git_repo))
173+
branches = gv.release_branches
174+
assert "master" in branches
175+
assert "release/*" in branches
176+
assert len(branches) == 2
177+
178+
def test_release_branches_custom(self, git_repo):
179+
"""Custom release_branches should be returned as-is."""
180+
gv = GitVersion(
181+
repo_path=str(git_repo),
182+
release_branches=["main", "release/*", "hotfix/*"],
183+
)
184+
assert gv.release_branches == ["main", "release/*", "hotfix/*"]
185+
186+
def test_release_branches_single(self, git_repo):
187+
"""Single branch in release_branches list."""
188+
gv = GitVersion(
189+
repo_path=str(git_repo),
190+
release_branches=["main"],
191+
)
192+
assert gv.release_branches == ["main"]
193+
194+
def test_release_branches_in_env(self, git_repo):
195+
"""release_branches should appear in env output."""
196+
gv = GitVersion(repo_path=str(git_repo))
197+
env = gv.env(prefix="TEST")
198+
assert "TEST_RELEASE_BRANCHES" in env
199+
assert "master" in env["TEST_RELEASE_BRANCHES"]
200+
assert "release/*" in env["TEST_RELEASE_BRANCHES"]
201+
202+
def test_release_branches_in_str(self, git_repo):
203+
"""release_branches should appear in string representation."""
204+
gv = GitVersion(repo_path=str(git_repo))
205+
output = str(gv)
206+
assert "Release branches" in output
207+
assert "master" in output
208+
assert "release/*" in output
209+
181210
def test_str(self, git_repo):
182211
gv = GitVersion(repo_path=str(git_repo))
183212
output = str(gv)

0 commit comments

Comments
 (0)