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
45 changes: 34 additions & 11 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,39 @@ def _git(args, cwd):
return result.stdout.strip()


def _ls_remote_targets():
"""Remotes to query for tags, in priority order.

Vercel's ``origin`` points at an internal mirror that lags GitHub by a
few seconds when a deploy hook fires immediately after a tag push, so
prefer GitHub directly when env vars expose the repo slug.
"""
targets = []
owner = os.environ.get('VERCEL_GIT_REPO_OWNER')
repo = os.environ.get('VERCEL_GIT_REPO_SLUG')
if owner and repo:
targets.append(f'https://github.com/{owner}/{repo}.git')
targets.append('origin')
return targets


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:
head = (
os.environ.get('VERCEL_GIT_COMMIT_SHA')
or _git(['rev-parse', 'HEAD'], cwd)
)
if not head:
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
for target in _ls_remote_targets():
refs = _git(['ls-remote', '--tags', target], cwd)
if not refs:
continue
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


Expand All @@ -62,8 +84,9 @@ def resolve_version(cwd=BASE):

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.
2. Remote tag at HEAD via ``git ls-remote`` — preferring GitHub directly
(via ``VERCEL_GIT_REPO_*`` env vars) over ``origin``, since Vercel's
mirrored origin can lag immediately after a tag push.
3. ``git describe --tags --always`` (describe-with-distance or short SHA).
4. ``unknown`` if git is unavailable or *cwd* is not a repo.
"""
Expand Down
28 changes: 28 additions & 0 deletions test/build/test_resolve_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,33 @@ def test_ls_remote_fallback_when_local_tag_refs_missing(self):
self.assertEqual(build.resolve_version(clone), 'v9.9.9')


def test_ls_remote_targets_prefer_github_when_vercel_env_set(self):
prev_owner = os.environ.get('VERCEL_GIT_REPO_OWNER')
prev_repo = os.environ.get('VERCEL_GIT_REPO_SLUG')
try:
os.environ['VERCEL_GIT_REPO_OWNER'] = 'someone'
os.environ['VERCEL_GIT_REPO_SLUG'] = 'thing'
targets = build._ls_remote_targets()
self.assertEqual(
targets,
['https://github.com/someone/thing.git', 'origin'],
)
finally:
for k, v in (
('VERCEL_GIT_REPO_OWNER', prev_owner),
('VERCEL_GIT_REPO_SLUG', prev_repo),
):
if v is None:
os.environ.pop(k, None)
else:
os.environ[k] = v

def test_ls_remote_targets_origin_only_without_env(self):
for k in ('VERCEL_GIT_REPO_OWNER', 'VERCEL_GIT_REPO_SLUG'):
if k in os.environ:
self.skipTest(f'{k} is set in this environment')
self.assertEqual(build._ls_remote_targets(), ['origin'])


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