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
51 changes: 39 additions & 12 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,50 @@ def read(path):
return f.read()


def resolve_version(cwd=BASE):
"""Return git-tag version string for the repo at *cwd*.

Order of preference:
1. ``git describe --tags --always`` (tag, or short SHA if no tag).
2. ``unknown`` if git is unavailable or *cwd* is not a repo.
"""
def _git(args, cwd):
try:
result = subprocess.run(
['git', 'describe', '--tags', '--always'],
cwd=cwd, capture_output=True, text=True,
['git', *args], cwd=cwd, capture_output=True, text=True,
)
except (FileNotFoundError, OSError):
return 'unknown'
return None
if result.returncode != 0:
return 'unknown'
return result.stdout.strip() or 'unknown'
return None
return result.stdout.strip()


def _tag_at_head_via_ls_remote(cwd):
head = _git(['rev-parse', 'HEAD'], cwd)
refs = _git(['ls-remote', '--tags', 'origin'], cwd)
if not head or not refs:
return None
for line in refs.splitlines():
parts = line.split()
if len(parts) >= 2 and parts[0] == head:
name = parts[1].replace('refs/tags/', '').replace('^{}', '')
if name:
return name
return None


def resolve_version(cwd=BASE):
"""Return git-tag version string for the repo at *cwd*.

Order of preference:
1. Local exact-match tag at HEAD (``git describe --exact-match --tags``).
2. Remote tag at HEAD via ``git ls-remote`` — fallback for shallow CI
clones where local tag refs aren't connected to HEAD.
3. ``git describe --tags --always`` (describe-with-distance or short SHA).
4. ``unknown`` if git is unavailable or *cwd* is not a repo.
"""
tag = _git(['describe', '--exact-match', '--tags', 'HEAD'], cwd)
if tag:
return tag
tag = _tag_at_head_via_ls_remote(cwd)
if tag:
return tag
described = _git(['describe', '--tags', '--always'], cwd)
return described or 'unknown'


def build():
Expand Down
24 changes: 24 additions & 0 deletions test/build/test_resolve_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,30 @@ def test_not_a_repo(self):
with tempfile.TemporaryDirectory() as d:
self.assertEqual(build.resolve_version(d), 'unknown')

def test_ls_remote_fallback_when_local_tag_refs_missing(self):
# Vercel-like failure mode: HEAD is at a tagged commit on origin,
# but local tag refs aren't populated (shallow clone quirks). The
# ls-remote fallback should still surface the tag.
with tempfile.TemporaryDirectory() as remote, \
tempfile.TemporaryDirectory() as clone:
init_repo(remote)
git(remote, 'tag', 'v9.9.9')
git(remote, 'config', 'receive.denyCurrentBranch', 'ignore')
git(clone, 'clone', '--depth=1', remote, '.')
# Strip local tag refs to simulate missing-tag-locally state
for entry in os.listdir(os.path.join(clone, '.git', 'refs', 'tags')):
os.remove(os.path.join(clone, '.git', 'refs', 'tags', entry))
packed = os.path.join(clone, '.git', 'packed-refs')
if os.path.exists(packed):
with open(packed) as f:
lines = [l for l in f if 'refs/tags/' not in l]
with open(packed, 'w') as f:
f.writelines(lines)
self.assertIsNone(
build._git(['describe', '--exact-match', '--tags', 'HEAD'], clone)
)
self.assertEqual(build.resolve_version(clone), 'v9.9.9')


if __name__ == '__main__':
unittest.main()
Loading